IntArrayData.java revision 1844:9c7526916609
1179335Syongari/* 2179335Syongari * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3179335Syongari * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4179335Syongari * 5179335Syongari * This code is free software; you can redistribute it and/or modify it 6179335Syongari * under the terms of the GNU General Public License version 2 only, as 7179335Syongari * published by the Free Software Foundation. Oracle designates this 8179335Syongari * particular file as subject to the "Classpath" exception as provided 9179335Syongari * by Oracle in the LICENSE file that accompanied this code. 10179335Syongari * 11179335Syongari * This code is distributed in the hope that it will be useful, but WITHOUT 12179335Syongari * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13179335Syongari * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14179335Syongari * version 2 for more details (a copy is included in the LICENSE file that 15179335Syongari * accompanied this code). 16179335Syongari * 17179335Syongari * You should have received a copy of the GNU General Public License version 18179335Syongari * 2 along with this work; if not, write to the Free Software Foundation, 19179335Syongari * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20179335Syongari * 21179335Syongari * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22179335Syongari * or visit www.oracle.com if you need additional information or have any 23179335Syongari * questions. 24179335Syongari */ 25179335Syongari 26179335Syongaripackage jdk.nashorn.internal.runtime.arrays; 27179335Syongari 28179335Syongariimport static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 29179335Syongari 30179335Syongariimport java.lang.invoke.MethodHandle; 31179335Syongariimport java.lang.invoke.MethodHandles; 32179335Syongariimport java.util.Arrays; 33179335Syongariimport jdk.nashorn.internal.runtime.JSType; 34179335Syongariimport jdk.nashorn.internal.runtime.ScriptRuntime; 35179335Syongari 36179335Syongari/** 37179335Syongari * Implementation of {@link ArrayData} as soon as an int has been 38179335Syongari * written to the array. This is the default data for new arrays 39179335Syongari */ 40179335Syongarifinal class IntArrayData extends ContinuousArrayData implements IntElements { 41179335Syongari /** 42179335Syongari * The wrapped array 43179335Syongari */ 44179335Syongari private int[] array; 45179335Syongari 46179335Syongari IntArrayData() { 47179335Syongari this(new int[ArrayData.CHUNK_SIZE], 0); 48179335Syongari } 49179335Syongari 50179335Syongari IntArrayData(final int length) { 51179335Syongari super(length); 52179335Syongari this.array = new int[ArrayData.nextSize(length)]; 53215298Smarius } 54215298Smarius 55179335Syongari /** 56179335Syongari * Constructor 57215298Smarius * @param array an int array 58179335Syongari * @param length a length, not necessarily array.length 59179335Syongari */ 60179335Syongari IntArrayData(final int[] array, final int length) { 61179335Syongari super(length); 62179335Syongari assert array == null || array.length >= length; 63179335Syongari this.array = array; 64179335Syongari } 65179335Syongari 66179335Syongari @Override 67179335Syongari public final Class<?> getElementType() { 68179335Syongari return int.class; 69179335Syongari } 70179335Syongari 71179335Syongari @Override 72179335Syongari public final Class<?> getBoxedElementType() { 73179335Syongari return Integer.class; 74179335Syongari } 75179335Syongari 76179335Syongari @Override 77179335Syongari public final int getElementWeight() { 78179335Syongari return 1; 79179335Syongari } 80179335Syongari 81179335Syongari @Override 82179335Syongari public final ContinuousArrayData widest(final ContinuousArrayData otherData) { 83179335Syongari return otherData; 84179335Syongari } 85179335Syongari 86179335Syongari private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "getElem", int.class, int.class).methodHandle(); 87179335Syongari private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "setElem", void.class, int.class, int.class).methodHandle(); 88179335Syongari 89179335Syongari @Override 90179335Syongari public Object[] asObjectArray() { 91179335Syongari return toObjectArray(true); 92179335Syongari } 93179335Syongari 94179335Syongari @SuppressWarnings("unused") 95179335Syongari private int getElem(final int index) { 96179335Syongari if (has(index)) { 97179335Syongari return array[index]; 98179335Syongari } 99179335Syongari throw new ClassCastException(); 100179335Syongari } 101179335Syongari 102179335Syongari @SuppressWarnings("unused") 103179335Syongari private void setElem(final int index, final int elem) { 104179335Syongari if (hasRoomFor(index)) { 105179335Syongari array[index] = elem; 106179335Syongari return; 107179335Syongari } 108179335Syongari throw new ClassCastException(); 109179335Syongari } 110179335Syongari 111179335Syongari @Override 112213229Smarius public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) { 113179335Syongari return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint); 114179335Syongari } 115213893Smarius 116213364Smarius @Override 117179335Syongari public MethodHandle getElementSetter(final Class<?> elementType) { 118179335Syongari return elementType == int.class ? getContinuousElementSetter(SET_ELEM, elementType) : null; 119179335Syongari } 120179335Syongari 121179335Syongari @Override 122179335Syongari public IntArrayData copy() { 123179335Syongari return new IntArrayData(array.clone(), (int)length()); 124179335Syongari } 125179335Syongari 126179335Syongari @Override 127179335Syongari public Object asArrayOfType(final Class<?> componentType) { 128179335Syongari if (componentType == int.class) { 129179335Syongari final int len = (int)length(); 130179335Syongari return array.length == len ? array.clone() : Arrays.copyOf(array, len); 131179335Syongari } 132179335Syongari return super.asArrayOfType(componentType); 133179335Syongari } 134179335Syongari 135179335Syongari private Object[] toObjectArray(final boolean trim) { 136179335Syongari assert length() <= array.length : "length exceeds internal array size"; 137179335Syongari final int len = (int)length(); 138213364Smarius final Object[] oarray = new Object[trim ? len : array.length]; 139179335Syongari 140179335Syongari for (int index = 0; index < len; index++) { 141179335Syongari oarray[index] = array[index]; 142179335Syongari } 143179335Syongari 144179335Syongari return oarray; 145179335Syongari } 146179335Syongari 147179335Syongari private double[] toDoubleArray() { 148179335Syongari assert length() <= array.length : "length exceeds internal array size"; 149179335Syongari final int len = (int)length(); 150179335Syongari final double[] darray = new double[array.length]; 151179335Syongari 152179335Syongari for (int index = 0; index < len; index++) { 153179335Syongari darray[index] = array[index]; 154179335Syongari } 155179335Syongari 156179335Syongari return darray; 157215298Smarius } 158179335Syongari 159179335Syongari private NumberArrayData convertToDouble() { 160179335Syongari return new NumberArrayData(toDoubleArray(), (int)length()); 161179335Syongari } 162179335Syongari 163179335Syongari private ObjectArrayData convertToObject() { 164179335Syongari return new ObjectArrayData(toObjectArray(false), (int)length()); 165179335Syongari } 166179335Syongari 167179335Syongari @Override 168179335Syongari public ArrayData convert(final Class<?> type) { 169179335Syongari if (type == Integer.class || type == Byte.class || type == Short.class) { 170179335Syongari return this; 171179335Syongari } else if (type == Double.class || type == Float.class) { 172179335Syongari return convertToDouble(); 173179335Syongari } else { 174179335Syongari return convertToObject(); 175179335Syongari } 176179335Syongari } 177179335Syongari 178179335Syongari @Override 179179335Syongari public ArrayData shiftLeft(final int by) { 180179335Syongari if (by >= length()) { 181179335Syongari shrink(0); 182179335Syongari } else { 183179335Syongari System.arraycopy(array, by, array, 0, array.length - by); 184179335Syongari } 185179335Syongari setLength(Math.max(0, length() - by)); 186179335Syongari 187179335Syongari return this; 188179335Syongari } 189215298Smarius 190179335Syongari @Override 191179335Syongari public ArrayData shiftRight(final int by) { 192179335Syongari final ArrayData newData = ensure(by + length() - 1); 193179335Syongari if (newData != this) { 194179335Syongari newData.shiftRight(by); 195179335Syongari return newData; 196179335Syongari } 197179335Syongari System.arraycopy(array, 0, array, by, array.length - by); 198179335Syongari 199179335Syongari return this; 200179335Syongari } 201179335Syongari 202179335Syongari @Override 203179335Syongari public ArrayData ensure(final long safeIndex) { 204179335Syongari if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) { 205179335Syongari return new SparseArrayData(this, safeIndex + 1); 206179335Syongari } 207179335Syongari final int alen = array.length; 208179335Syongari if (safeIndex >= alen) { 209179335Syongari final int newLength = ArrayData.nextSize((int)safeIndex); 210179335Syongari array = Arrays.copyOf(array, newLength); 211179335Syongari } 212179335Syongari if (safeIndex >= length()) { 213179335Syongari setLength(safeIndex + 1); 214179335Syongari } 215179335Syongari return this; 216179335Syongari } 217179335Syongari 218179335Syongari @Override 219179335Syongari public ArrayData shrink(final long newLength) { 220179335Syongari Arrays.fill(array, (int)newLength, array.length, 0); 221179335Syongari return this; 222179335Syongari } 223179335Syongari 224179335Syongari @Override 225179335Syongari public ArrayData set(final int index, final Object value, final boolean strict) { 226179335Syongari if (JSType.isRepresentableAsInt(value)) { 227179335Syongari return set(index, JSType.toInt32(value), strict); 228179335Syongari } else if (value == ScriptRuntime.UNDEFINED) { 229179335Syongari return new UndefinedArrayFilter(this).set(index, value, strict); 230179335Syongari } 231179335Syongari 232179335Syongari final ArrayData newData = convert(value == null ? Object.class : value.getClass()); 233179335Syongari return newData.set(index, value, strict); 234179335Syongari } 235179335Syongari 236179335Syongari @Override 237179335Syongari public ArrayData set(final int index, final int value, final boolean strict) { 238179335Syongari array[index] = value; 239179335Syongari setLength(Math.max(index + 1, length())); 240179335Syongari 241179335Syongari return this; 242179335Syongari } 243179335Syongari 244179335Syongari @Override 245179335Syongari public ArrayData set(final int index, final double value, final boolean strict) { 246179335Syongari if (JSType.isRepresentableAsInt(value)) { 247179335Syongari array[index] = (int)(long)value; 248179335Syongari setLength(Math.max(index + 1, length())); 249179335Syongari return this; 250179335Syongari } 251179335Syongari 252179335Syongari return convert(Double.class).set(index, value, strict); 253179335Syongari } 254215298Smarius 255179335Syongari @Override 256179335Syongari public int getInt(final int index) { 257215298Smarius return array[index]; 258179335Syongari } 259179335Syongari 260179335Syongari @Override 261179335Syongari public int getIntOptimistic(final int index, final int programPoint) { 262179335Syongari return array[index]; 263179335Syongari } 264179335Syongari 265179335Syongari @Override 266179335Syongari public double getDouble(final int index) { 267179335Syongari return array[index]; 268179335Syongari } 269179335Syongari 270179335Syongari @Override 271179335Syongari public double getDoubleOptimistic(final int index, final int programPoint) { 272179335Syongari return array[index]; 273179335Syongari } 274179335Syongari 275179335Syongari @Override 276179335Syongari public Object getObject(final int index) { 277179335Syongari return array[index]; 278179335Syongari } 279179335Syongari 280179335Syongari @Override 281179335Syongari public boolean has(final int index) { 282179335Syongari return 0 <= index && index < length(); 283179335Syongari } 284179335Syongari 285179335Syongari @Override 286179335Syongari public ArrayData delete(final int index) { 287179335Syongari return new DeletedRangeArrayFilter(this, index, index); 288179335Syongari } 289179335Syongari 290179335Syongari @Override 291179335Syongari public ArrayData delete(final long fromIndex, final long toIndex) { 292179335Syongari return new DeletedRangeArrayFilter(this, fromIndex, toIndex); 293179335Syongari } 294179335Syongari 295179335Syongari @Override 296179335Syongari public Object pop() { 297179335Syongari final int len = (int)length(); 298179335Syongari if (len == 0) { 299179335Syongari return ScriptRuntime.UNDEFINED; 300179335Syongari } 301179335Syongari 302179335Syongari final int newLength = len - 1; 303179335Syongari final int elem = array[newLength]; 304179335Syongari array[newLength] = 0; 305179335Syongari setLength(newLength); 306179335Syongari 307179335Syongari return elem; 308179335Syongari } 309179335Syongari 310215298Smarius @Override 311179335Syongari public ArrayData slice(final long from, final long to) { 312179335Syongari return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)(to - (from < 0 ? from + length() : from))); 313179335Syongari } 314179335Syongari 315179335Syongari @Override 316179335Syongari public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 317179335Syongari final long oldLength = length(); 318179335Syongari final long newLength = oldLength - removed + added; 319179335Syongari if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 320179335Syongari throw new UnsupportedOperationException(); 321179335Syongari } 322179335Syongari final ArrayData returnValue = removed == 0 ? 323179335Syongari EMPTY_ARRAY : 324179335Syongari new IntArrayData( 325179335Syongari Arrays.copyOfRange( 326179335Syongari array, 327179335Syongari start, 328179335Syongari start + removed), 329179335Syongari removed); 330179335Syongari 331179335Syongari if (newLength != oldLength) { 332179335Syongari final int[] newArray; 333179335Syongari 334179335Syongari if (newLength > array.length) { 335179335Syongari newArray = new int[ArrayData.nextSize((int)newLength)]; 336179335Syongari System.arraycopy(array, 0, newArray, 0, start); 337215298Smarius } else { 338215298Smarius newArray = array; 339215298Smarius } 340215298Smarius 341215298Smarius System.arraycopy(array, start + removed, newArray, start + added, (int)(oldLength - start - removed)); 342179335Syongari array = newArray; 343179335Syongari setLength(newLength); 344215298Smarius } 345215298Smarius 346215298Smarius return returnValue; 347215298Smarius } 348215298Smarius 349179335Syongari @Override 350179335Syongari public double fastPush(final int arg) { 351179335Syongari final int len = (int)length(); 352179335Syongari if (len == array.length) { 353179335Syongari array = Arrays.copyOf(array, nextSize(len)); 354179335Syongari } 355179335Syongari array[len] = arg; 356 return increaseLength(); 357 } 358 359 //length must not be zero 360 @Override 361 public int fastPopInt() { 362 if (length() == 0) { 363 throw new ClassCastException(); //relink 364 } 365 final int newLength = (int)decreaseLength(); 366 final int elem = array[newLength]; 367 array[newLength] = 0; 368 return elem; 369 } 370 371 @Override 372 public double fastPopDouble() { 373 return fastPopInt(); 374 } 375 376 @Override 377 public Object fastPopObject() { 378 return fastPopInt(); 379 } 380 381 @Override 382 public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) { 383 final int otherLength = (int)otherData.length(); 384 final int thisLength = (int)length(); 385 assert otherLength > 0 && thisLength > 0; 386 387 final int[] otherArray = ((IntArrayData)otherData).array; 388 final int newLength = otherLength + thisLength; 389 final int[] newArray = new int[ArrayData.alignUp(newLength)]; 390 391 System.arraycopy(array, 0, newArray, 0, thisLength); 392 System.arraycopy(otherArray, 0, newArray, thisLength, otherLength); 393 394 return new IntArrayData(newArray, newLength); 395 } 396 397 @Override 398 public String toString() { 399 assert length() <= array.length : length() + " > " + array.length; 400 return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length())); 401 } 402} 403