diff options
Diffstat (limited to 'src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java')
-rw-r--r-- | src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java | 195 |
1 files changed, 161 insertions, 34 deletions
diff --git a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java index 8254db63..2522b979 100644 --- a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java +++ b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java @@ -25,15 +25,18 @@ package jdk.nashorn.internal.runtime.arrays; +import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; +import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; - +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.util.Arrays; /** * Implementation of {@link ArrayData} as soon as a double has been * written to the array */ -final class NumberArrayData extends ArrayData { +final class NumberArrayData extends ContinuousArrayData implements NumericElements { /** * The wrapped array */ @@ -44,27 +47,48 @@ final class NumberArrayData extends ArrayData { * @param array an int array * @param length a length, not necessarily array.length */ - NumberArrayData(final double array[], final int length) { + NumberArrayData(final double[] array, final int length) { super(length); assert array.length >= length; - this.array = array; + this.array = array; + } + + @Override + public final Class<?> getElementType() { + return double.class; + } + + @Override + public final Class<?> getBoxedElementType() { + return Double.class; + } + + @Override + public final int getElementWeight() { + return 3; } @Override - public ArrayData copy() { - return new NumberArrayData(array.clone(), (int) length()); + public final ContinuousArrayData widest(final ContinuousArrayData otherData) { + return otherData instanceof IntOrLongElements ? this : otherData; + } + + @Override + public NumberArrayData copy() { + return new NumberArrayData(array.clone(), (int)length()); } @Override public Object[] asObjectArray() { - return toObjectArray(array, (int) length()); + return toObjectArray(true); } - private static Object[] toObjectArray(final double[] array, final int length) { - assert length <= array.length : "length exceeds internal array size"; - final Object[] oarray = new Object[array.length]; + private Object[] toObjectArray(final boolean trim) { + assert length() <= array.length : "length exceeds internal array size"; + final int len = (int)length(); + final Object[] oarray = new Object[trim ? len : array.length]; - for (int index = 0; index < length; index++) { + for (int index = 0; index < len; index++) { oarray[index] = Double.valueOf(array[index]); } return oarray; @@ -72,17 +96,18 @@ final class NumberArrayData extends ArrayData { @Override public Object asArrayOfType(final Class<?> componentType) { - if(componentType == double.class) { - return array.length == length() ? array.clone() : Arrays.copyOf(array, (int) length()); + if (componentType == double.class) { + final int len = (int)length(); + return array.length == len ? array.clone() : Arrays.copyOf(array, len); } return super.asArrayOfType(componentType); } @Override - public ArrayData convert(final Class<?> type) { + public ContinuousArrayData convert(final Class<?> type) { if (type != Double.class && type != Integer.class && type != Long.class) { - final int length = (int) length(); - return new ObjectArrayData(NumberArrayData.toObjectArray(array, length), length); + final int len = (int)length(); + return new ObjectArrayData(toObjectArray(false), len); } return this; } @@ -105,29 +130,22 @@ final class NumberArrayData extends ArrayData { @Override public ArrayData ensure(final long safeIndex) { - if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= array.length) { + if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) { return new SparseArrayData(this, safeIndex + 1); } - - int newLength = array.length; - - while (newLength <= safeIndex) { - newLength = ArrayData.nextSize(newLength); + final int alen = array.length; + if (safeIndex >= alen) { + final int newLength = ArrayData.nextSize((int)safeIndex); + array = Arrays.copyOf(array, newLength); //todo fill with nan or never accessed? } - - if (array.length <= safeIndex) { - array = Arrays.copyOf(array, newLength); - Arrays.fill(array, (int) length(), newLength, Double.NaN); - } - setLength(safeIndex + 1); - return this; + } @Override public ArrayData shrink(final long newLength) { - Arrays.fill(array, (int) newLength, array.length, 0.0); + Arrays.fill(array, (int)newLength, array.length, 0.0); return this; } @@ -164,6 +182,39 @@ final class NumberArrayData extends ArrayData { return this; } + private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), NumberArrayData.class, "getElem", double.class, int.class).methodHandle(); + private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), NumberArrayData.class, "setElem", void.class, int.class, double.class).methodHandle(); + + @SuppressWarnings("unused") + private double getElem(final int index) { + if (has(index)) { + return array[index]; + } + throw new ClassCastException(); + } + + @SuppressWarnings("unused") + private void setElem(final int index, final double elem) { + if (hasRoomFor(index)) { + array[index] = elem; + return; + } + throw new ClassCastException(); + } + + @Override + public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) { + if (returnType == int.class || returnType == long.class) { + return null; + } + return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint); + } + + @Override + public MethodHandle getElementSetter(final Class<?> elementType) { + return elementType.isPrimitive() ? getContinuousElementSetter(MH.asType(SET_ELEM, SET_ELEM.type().changeParameterType(2, elementType)), elementType) : null; + } + @Override public int getInt(final int index) { return (int)array[index]; @@ -180,6 +231,11 @@ final class NumberArrayData extends ArrayData { } @Override + public double getDoubleOptimistic(final int index, final int programPoint) { + return array[index]; + } + + @Override public Object getObject(final int index) { return array[index]; } @@ -201,11 +257,12 @@ final class NumberArrayData extends ArrayData { @Override public Object pop() { - if (length() == 0) { + final int len = (int)length(); + if (len == 0) { return UNDEFINED; } - final int newLength = (int) (length() - 1); + final int newLength = len - 1; final double elem = array[newLength]; array[newLength] = 0; setLength(newLength); @@ -214,19 +271,30 @@ final class NumberArrayData extends ArrayData { @Override public ArrayData slice(final long from, final long to) { - final long start = from < 0 ? (from + length()) : from; + final long start = from < 0 ? from + length() : from; final long newLength = to - start; return new NumberArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); } @Override + public final ArrayData push(final boolean strict, final double item) { + final long len = length(); + final ArrayData newData = ensure(len); + if (newData == this) { + array[(int)len] = item; + return this; + } + return newData.set((int)len, item, strict); + } + + @Override public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { final long oldLength = length(); final long newLength = oldLength - removed + added; if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { throw new UnsupportedOperationException(); } - final ArrayData returnValue = (removed == 0) ? + final ArrayData returnValue = removed == 0 ? EMPTY_ARRAY : new NumberArrayData(Arrays.copyOfRange(array, start, start + removed), removed); if (newLength != oldLength) { @@ -246,4 +314,63 @@ final class NumberArrayData extends ArrayData { return returnValue; } + + @Override + public long fastPush(final int arg) { + return fastPush((double)arg); + } + + @Override + public long fastPush(final long arg) { + return fastPush((double)arg); + } + + @Override + public long fastPush(final double arg) { + final int len = (int)length(); + if (len == array.length) { + //note that fastpush never creates spares arrays, there is nothing to gain by that - it will just use even more memory + array = Arrays.copyOf(array, nextSize(len)); + } + array[len] = arg; + return increaseLength(); + } + + @Override + public double fastPopDouble() { + if (length() == 0) { + throw new ClassCastException(); + } + final int newLength = (int)decreaseLength(); + final double elem = array[newLength]; + array[newLength] = 0; + return elem; + } + + @Override + public Object fastPopObject() { + return fastPopDouble(); + } + + @Override + public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) { + final int otherLength = (int)otherData.length(); + final int thisLength = (int)length(); + assert otherLength > 0 && thisLength > 0; + + final double[] otherArray = ((NumberArrayData)otherData).array; + final int newLength = otherLength + thisLength; + final double[] newArray = new double[ArrayData.alignUp(newLength)]; + + System.arraycopy(array, 0, newArray, 0, thisLength); + System.arraycopy(otherArray, 0, newArray, thisLength, otherLength); + + return new NumberArrayData(newArray, newLength); + } + + @Override + public String toString() { + assert length() <= array.length : length() + " > " + array.length; + return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length())); + } } |