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