IntArrayData.java revision 1101:be3f5ca1edbf
11590Srgrimes/* 21590Srgrimes * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 31590Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 41590Srgrimes * 51590Srgrimes * This code is free software; you can redistribute it and/or modify it 61590Srgrimes * under the terms of the GNU General Public License version 2 only, as 71590Srgrimes * published by the Free Software Foundation. Oracle designates this 81590Srgrimes * particular file as subject to the "Classpath" exception as provided 91590Srgrimes * by Oracle in the LICENSE file that accompanied this code. 101590Srgrimes * 111590Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT 121590Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 131590Srgrimes * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 141590Srgrimes * version 2 for more details (a copy is included in the LICENSE file that 151590Srgrimes * accompanied this code). 161590Srgrimes * 171590Srgrimes * You should have received a copy of the GNU General Public License version 181590Srgrimes * 2 along with this work; if not, write to the Free Software Foundation, 191590Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 201590Srgrimes * 211590Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 221590Srgrimes * or visit www.oracle.com if you need additional information or have any 231590Srgrimes * questions. 241590Srgrimes */ 251590Srgrimes 261590Srgrimespackage jdk.nashorn.internal.runtime.arrays; 271590Srgrimes 281590Srgrimesimport static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 291590Srgrimesimport java.lang.invoke.MethodHandle; 301590Srgrimesimport java.lang.invoke.MethodHandles; 311590Srgrimesimport java.util.Arrays; 321590Srgrimesimport jdk.nashorn.internal.runtime.JSType; 331590Srgrimesimport jdk.nashorn.internal.runtime.ScriptRuntime; 341590Srgrimes 3578201Sdd/** 361590Srgrimes * Implementation of {@link ArrayData} as soon as an int has been 371590Srgrimes * written to the array. This is the default data for new arrays 381590Srgrimes */ 391590Srgrimesfinal class IntArrayData extends ContinuousArrayData implements IntElements { 401590Srgrimes /** 4178201Sdd * The wrapped array 421590Srgrimes */ 4399112Sobrien private int[] array; 4499112Sobrien 451590Srgrimes IntArrayData() { 461590Srgrimes this(new int[ArrayData.CHUNK_SIZE], 0); 471590Srgrimes } 481590Srgrimes 491590Srgrimes IntArrayData(final int length) { 501590Srgrimes super(length); 5174588Sache this.array = new int[ArrayData.nextSize(length)]; 5216438Sache } 531590Srgrimes 541590Srgrimes /** 551590Srgrimes * Constructor 561590Srgrimes * @param array an int array 571590Srgrimes * @param length a length, not necessarily array.length 581590Srgrimes */ 591590Srgrimes IntArrayData(final int[] array, final int length) { 601590Srgrimes super(length); 6111547Sdg assert array == null || array.length >= length; 621590Srgrimes this.array = array; 631590Srgrimes } 641590Srgrimes 6577291Sdd @Override 661590Srgrimes public final Class<?> getElementType() { 671590Srgrimes return int.class; 681590Srgrimes } 691590Srgrimes 701590Srgrimes @Override 711590Srgrimes public final Class<?> getBoxedElementType() { 721590Srgrimes return Integer.class; 731590Srgrimes } 741590Srgrimes 751590Srgrimes @Override 761590Srgrimes public final int getElementWeight() { 771590Srgrimes return 1; 781590Srgrimes } 7960938Sjake 8011547Sdg @Override 8111547Sdg public final ContinuousArrayData widest(final ContinuousArrayData otherData) { 8236062Sjb return otherData; 831590Srgrimes } 8460938Sjake 8511547Sdg private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "getElem", int.class, int.class).methodHandle(); 861590Srgrimes private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "setElem", void.class, int.class, int.class).methodHandle(); 8791536Siedowse 881590Srgrimes @Override 891590Srgrimes public Object[] asObjectArray() { 9078201Sdd return toObjectArray(true); 9136434Sdanny } 9236434Sdanny 9391541Siedowse @SuppressWarnings("unused") 9474588Sache private int getElem(final int index) { 9591538Siedowse if (has(index)) { 9677291Sdd return array[index]; 9777291Sdd } 9877291Sdd throw new ClassCastException(); 9977291Sdd } 1001590Srgrimes 10192920Simp @SuppressWarnings("unused") 10292920Simp private void setElem(final int index, final int elem) { 10392920Simp if (hasRoomFor(index)) { 10492920Simp array[index] = elem; 10592920Simp return; 10692920Simp } 10792920Simp throw new ClassCastException(); 10892920Simp } 10992920Simp 11092920Simp @Override 1111590Srgrimes public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) { 11236434Sdanny return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint); 11336434Sdanny } 11436434Sdanny 11536434Sdanny @Override 11691541Siedowse public MethodHandle getElementSetter(final Class<?> elementType) { 11781161Sdd return elementType == int.class ? getContinuousElementSetter(SET_ELEM, elementType) : null; 11836434Sdanny } 11936434Sdanny 12036434Sdanny @Override 1211590Srgrimes public IntArrayData copy() { 1221590Srgrimes return new IntArrayData(array.clone(), (int)length()); 1231590Srgrimes } 1241590Srgrimes 1251590Srgrimes @Override 1261590Srgrimes public Object asArrayOfType(final Class<?> componentType) { 1271590Srgrimes if (componentType == int.class) { 1281590Srgrimes final int len = (int)length(); 12916438Sache return array.length == len ? array.clone() : Arrays.copyOf(array, len); 13074588Sache } 13116438Sache return super.asArrayOfType(componentType); 1321590Srgrimes } 13377291Sdd 13491541Siedowse private Object[] toObjectArray(final boolean trim) { 1351590Srgrimes assert length() <= array.length : "length exceeds internal array size"; 1361590Srgrimes final int len = (int)length(); 1371590Srgrimes final Object[] oarray = new Object[trim ? len : array.length]; 1381590Srgrimes 1391590Srgrimes for (int index = 0; index < len; index++) { 1401590Srgrimes oarray[index] = Integer.valueOf(array[index]); 1411590Srgrimes } 1421590Srgrimes 1431590Srgrimes return oarray; 1441590Srgrimes } 1451590Srgrimes 1461590Srgrimes private double[] toDoubleArray() { 1471590Srgrimes assert length() <= array.length : "length exceeds internal array size"; 1481590Srgrimes final int len = (int)length(); 1491590Srgrimes final double[] darray = new double[array.length]; 1501590Srgrimes 1511590Srgrimes for (int index = 0; index < len; index++) { 15277291Sdd darray[index] = array[index]; 15377291Sdd } 15477291Sdd 1551590Srgrimes return darray; 1561590Srgrimes } 1571590Srgrimes 1581590Srgrimes private long[] toLongArray() { 1591590Srgrimes assert length() <= array.length : "length exceeds internal array size"; 1601590Srgrimes final int len = (int)length(); 1611590Srgrimes final long[] larray = new long[array.length]; 16236434Sdanny 16336434Sdanny for (int index = 0; index < len; index++) { 16436434Sdanny larray[index] = array[index]; 1651590Srgrimes } 1661590Srgrimes 1671590Srgrimes return larray; 16836434Sdanny } 16936434Sdanny 17036434Sdanny private LongArrayData convertToLong() { 17191541Siedowse return new LongArrayData(toLongArray(), (int)length()); 17291541Siedowse } 17391541Siedowse 1741590Srgrimes private NumberArrayData convertToDouble() { 1751590Srgrimes return new NumberArrayData(toDoubleArray(), (int)length()); 17636434Sdanny } 1771590Srgrimes 1781590Srgrimes private ObjectArrayData convertToObject() { 17936434Sdanny return new ObjectArrayData(toObjectArray(false), (int)length()); 18036434Sdanny } 1811590Srgrimes 1821590Srgrimes @Override 1831590Srgrimes public ArrayData convert(final Class<?> type) { 1841590Srgrimes if (type == Integer.class) { 1851590Srgrimes return this; 1861590Srgrimes } else if (type == Long.class) { 1871590Srgrimes return convertToLong(); 1881590Srgrimes } else if (type == Double.class) { 1891590Srgrimes return convertToDouble(); 1901590Srgrimes } else { 1911590Srgrimes assert type == null || (!Number.class.isAssignableFrom(type) && !type.isPrimitive()); 1921590Srgrimes return convertToObject(); 1931590Srgrimes } 1941590Srgrimes } 1951590Srgrimes 1961590Srgrimes @Override 1971590Srgrimes public void shiftLeft(final int by) { 1981590Srgrimes System.arraycopy(array, by, array, 0, array.length - by); 1991590Srgrimes } 2001590Srgrimes 2011590Srgrimes @Override 2021590Srgrimes public ArrayData shiftRight(final int by) { 2031590Srgrimes final ArrayData newData = ensure(by + length() - 1); 2041590Srgrimes if (newData != this) { 20536062Sjb newData.shiftRight(by); 2061590Srgrimes return newData; 20716438Sache } 20816438Sache System.arraycopy(array, 0, array, by, array.length - by); 20985648Sdillon 2101590Srgrimes return this; 21111547Sdg } 21211547Sdg 2131590Srgrimes @Override 2141590Srgrimes public ArrayData ensure(final long safeIndex) { 2151590Srgrimes if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) { 2161590Srgrimes return new SparseArrayData(this, safeIndex + 1); 21785648Sdillon } 21889572Sdillon final int alen = array.length; 2191590Srgrimes if (safeIndex >= alen) { 2201590Srgrimes final int newLength = ArrayData.nextSize((int)safeIndex); 2211590Srgrimes array = Arrays.copyOf(array, newLength); 2221590Srgrimes } 2231590Srgrimes setLength(safeIndex + 1); 2241590Srgrimes return this; 2251590Srgrimes } 22691536Siedowse 22791536Siedowse @Override 2281590Srgrimes public ArrayData shrink(final long newLength) { 22989572Sdillon Arrays.fill(array, (int)newLength, array.length, 0); 23085648Sdillon return this; 23178201Sdd } 23262871Skris 2331590Srgrimes @Override 2341590Srgrimes public ArrayData set(final int index, final Object value, final boolean strict) { 2351590Srgrimes if (JSType.isRepresentableAsInt(value)) { 23691536Siedowse return set(index, JSType.toInt32(value), strict); 23791536Siedowse } else if (value == ScriptRuntime.UNDEFINED) { 23891536Siedowse return new UndefinedArrayFilter(this).set(index, value, strict); 23991536Siedowse } 24091536Siedowse 24191536Siedowse final ArrayData newData = convert(value == null ? Object.class : value.getClass()); 24291536Siedowse return newData.set(index, value, strict); 24391536Siedowse } 24491536Siedowse 24591536Siedowse @Override 24691536Siedowse public ArrayData set(final int index, final int value, final boolean strict) { 24791536Siedowse array[index] = value; 24891536Siedowse setLength(Math.max(index + 1, length())); 24991536Siedowse 25091536Siedowse return this; 25191536Siedowse } 25291536Siedowse 25391536Siedowse @Override 25491536Siedowse public ArrayData set(final int index, final long value, final boolean strict) { 25591536Siedowse if (JSType.isRepresentableAsInt(value)) { 25691536Siedowse array[index] = JSType.toInt32(value); 25791536Siedowse setLength(Math.max(index + 1, length())); 25891536Siedowse return this; 25991536Siedowse } 26091536Siedowse 26191536Siedowse return convert(Long.class).set(index, value, strict); 26291536Siedowse } 26391536Siedowse 26491536Siedowse @Override 26591536Siedowse public ArrayData set(final int index, final double value, final boolean strict) { 26691536Siedowse if (JSType.isRepresentableAsInt(value)) { 26791536Siedowse array[index] = (int)(long)value; 26891536Siedowse setLength(Math.max(index + 1, length())); 26991536Siedowse return this; 27091538Siedowse } 27191536Siedowse 27291536Siedowse return convert(Double.class).set(index, value, strict); 27391536Siedowse } 27491536Siedowse 27591536Siedowse @Override 27691536Siedowse public int getInt(final int index) { 27791536Siedowse return array[index]; 27891536Siedowse } 27991536Siedowse 28091538Siedowse @Override 28191536Siedowse public int getIntOptimistic(final int index, final int programPoint) { 28291536Siedowse return array[index]; 28391536Siedowse } 28491536Siedowse 28591536Siedowse @Override 28691536Siedowse public long getLong(final int index) { 28791536Siedowse return array[index]; 28891536Siedowse } 28991536Siedowse 29091536Siedowse @Override 29191536Siedowse public long getLongOptimistic(final int index, final int programPoint) { 29291536Siedowse return array[index]; 29396785Sjmallett } 29491536Siedowse 29591536Siedowse @Override 29691536Siedowse public double getDouble(final int index) { 29791536Siedowse return array[index]; 29891536Siedowse } 29991536Siedowse 30091536Siedowse @Override 30191536Siedowse public double getDoubleOptimistic(final int index, final int programPoint) { 30291536Siedowse return array[index]; 30391536Siedowse } 30491536Siedowse 30591536Siedowse @Override 30691536Siedowse public Object getObject(final int index) { 30791536Siedowse return array[index]; 30891536Siedowse } 30991536Siedowse 31091536Siedowse @Override 31191536Siedowse public boolean has(final int index) { 31291536Siedowse return 0 <= index && index < length(); 31391536Siedowse } 31491536Siedowse 31591536Siedowse @Override 31691536Siedowse public ArrayData delete(final int index) { 31791536Siedowse return new DeletedRangeArrayFilter(this, index, index); 31891536Siedowse } 31991536Siedowse 32091536Siedowse @Override 32191536Siedowse public ArrayData delete(final long fromIndex, final long toIndex) { 32291536Siedowse return new DeletedRangeArrayFilter(this, fromIndex, toIndex); 32391536Siedowse } 32491536Siedowse 32591536Siedowse @Override 32691536Siedowse public Object pop() { 32791536Siedowse final int len = (int)length(); 32891536Siedowse if (len == 0) { 32991536Siedowse return ScriptRuntime.UNDEFINED; 33091536Siedowse } 33191536Siedowse 33291536Siedowse final int newLength = len - 1; 33391536Siedowse final int elem = array[newLength]; 33491536Siedowse array[newLength] = 0; 33591536Siedowse setLength(newLength); 33691536Siedowse 33791538Siedowse return elem; 33891538Siedowse } 33991536Siedowse 34091536Siedowse @Override 34191541Siedowse public ArrayData slice(final long from, final long to) { 34291541Siedowse return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)(to - (from < 0 ? from + length() : from))); 34391541Siedowse } 34491536Siedowse 34591536Siedowse @Override 34691536Siedowse public final ArrayData push(final boolean strict, final int item) { 34791536Siedowse final long len = length(); 34891536Siedowse final ArrayData newData = ensure(len); 34991536Siedowse if (newData == this) { 35091536Siedowse array[(int)len] = item; 35191536Siedowse return this; 35291536Siedowse } 35391536Siedowse return newData.set((int)len, item, strict); 35491536Siedowse } 35591536Siedowse 35691536Siedowse @Override 35791536Siedowse public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 35891536Siedowse final long oldLength = length(); 35991536Siedowse final long newLength = oldLength - removed + added; 36091536Siedowse if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 36191536Siedowse throw new UnsupportedOperationException(); 36291536Siedowse } 36391536Siedowse final ArrayData returnValue = removed == 0 ? 36491536Siedowse EMPTY_ARRAY : 36591536Siedowse new IntArrayData( 36691536Siedowse Arrays.copyOfRange( 36791536Siedowse array, 36891536Siedowse start, 36991536Siedowse start + removed), 37091536Siedowse removed); 37191536Siedowse 37291536Siedowse if (newLength != oldLength) { 37391536Siedowse final int[] newArray; 37491536Siedowse 37591536Siedowse if (newLength > array.length) { 37691536Siedowse newArray = new int[ArrayData.nextSize((int)newLength)]; 3771590Srgrimes System.arraycopy(array, 0, newArray, 0, start); 3781590Srgrimes } else { 3791590Srgrimes newArray = array; 3801590Srgrimes } 38111547Sdg 3821590Srgrimes System.arraycopy(array, start + removed, newArray, start + added, (int)(oldLength - start - removed)); 3831590Srgrimes array = newArray; 3841590Srgrimes setLength(newLength); 3851590Srgrimes } 38677291Sdd 38777291Sdd return returnValue; 38877291Sdd } 3891590Srgrimes 3901590Srgrimes @Override 3911590Srgrimes public long fastPush(final int arg) { 3921590Srgrimes final int len = (int)length(); 3931590Srgrimes if (len == array.length) { 3941590Srgrimes array = Arrays.copyOf(array, nextSize(len)); 3951590Srgrimes } 3961590Srgrimes array[len] = arg; 3971590Srgrimes return increaseLength(); 3981590Srgrimes } 3991590Srgrimes 4001590Srgrimes //length must not be zero 4011590Srgrimes @Override 4021590Srgrimes public int fastPopInt() { 4031590Srgrimes if (length() == 0) { 4041590Srgrimes throw new ClassCastException(); //relink 4051590Srgrimes } 40691536Siedowse final int newLength = (int)decreaseLength(); 4071590Srgrimes final int elem = array[newLength]; 4081590Srgrimes array[newLength] = 0; 4091590Srgrimes return elem; 4101590Srgrimes } 4111590Srgrimes 4121590Srgrimes @Override 4131590Srgrimes public long fastPopLong() { 4141590Srgrimes return fastPopInt(); 4151590Srgrimes } 4161590Srgrimes 4171590Srgrimes @Override 4181590Srgrimes public double fastPopDouble() { 4191590Srgrimes return fastPopInt(); 4201590Srgrimes } 42196785Sjmallett 42296785Sjmallett @Override 4231590Srgrimes public Object fastPopObject() { 4241590Srgrimes return fastPopInt(); 4251590Srgrimes } 4261590Srgrimes 4271590Srgrimes @Override 4281590Srgrimes public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) { 4291590Srgrimes final int otherLength = (int)otherData.length(); 4301590Srgrimes final int thisLength = (int)length(); 4311590Srgrimes assert otherLength > 0 && thisLength > 0; 4321590Srgrimes 4331590Srgrimes final int[] otherArray = ((IntArrayData)otherData).array; 4341590Srgrimes final int newLength = otherLength + thisLength; 4351590Srgrimes final int[] newArray = new int[ArrayData.alignUp(newLength)]; 4361590Srgrimes 4371590Srgrimes System.arraycopy(array, 0, newArray, 0, thisLength); 4381590Srgrimes System.arraycopy(otherArray, 0, newArray, thisLength, otherLength); 4391590Srgrimes 4401590Srgrimes return new IntArrayData(newArray, newLength); 4411590Srgrimes } 4421590Srgrimes 4431590Srgrimes @Override 4441590Srgrimes public String toString() { 4451590Srgrimes assert length() <= array.length : length() + " > " + array.length; 4461590Srgrimes return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length())); 4471590Srgrimes } 4481590Srgrimes} 4491590Srgrimes