8138632: Sparse array does not handle growth of underlying dense array

Thu, 01 Oct 2015 10:37:25 +0200

author
hannesw
date
Thu, 01 Oct 2015 10:37:25 +0200
changeset 1556
92bcafb57da3
parent 1555
bf4599bb97b5
child 1557
a105e7b0eff9

8138632: Sparse array does not handle growth of underlying dense array
Reviewed-by: attila, sundar

src/jdk/nashorn/internal/runtime/ScriptObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ArrayData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java file | annotate | diff | comparison | revisions
test/script/basic/JDK-8138632.js file | annotate | diff | comparison | revisions
test/script/basic/JDK-8138632.js.EXPECTED file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Thu Oct 01 21:27:30 2015 +0530
     1.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Thu Oct 01 10:37:25 2015 +0200
     1.3 @@ -710,8 +710,7 @@
     1.4          final long longIndex = ArrayIndex.toLongIndex(index);
     1.5          final long oldLength = getArray().length();
     1.6          if (longIndex >= oldLength) {
     1.7 -            setArray(getArray().ensure(longIndex));
     1.8 -            doesNotHaveEnsureDelete(longIndex, oldLength, false);
     1.9 +            setArray(getArray().ensure(longIndex).safeDelete(oldLength, longIndex - 1, false));
    1.10          }
    1.11          setArray(getArray().set(index, value, false));
    1.12      }
    1.13 @@ -2678,11 +2677,7 @@
    1.14          }
    1.15  
    1.16          if (newLength > arrayLength) {
    1.17 -            data = data.ensure(newLength - 1);
    1.18 -            if (data.canDelete(arrayLength, newLength - 1, false)) {
    1.19 -               data = data.delete(arrayLength, newLength - 1);
    1.20 -            }
    1.21 -            setArray(data);
    1.22 +            setArray(data.ensure(newLength - 1).safeDelete(arrayLength, newLength - 1, false));
    1.23              return;
    1.24          }
    1.25  
    1.26 @@ -3103,23 +3098,12 @@
    1.27          return false;
    1.28      }
    1.29  
    1.30 -    private void doesNotHaveEnsureDelete(final long longIndex, final long oldLength, final boolean strict) {
    1.31 -        if (longIndex > oldLength) {
    1.32 -            ArrayData array = getArray();
    1.33 -            if (array.canDelete(oldLength, longIndex - 1, strict)) {
    1.34 -                array = array.delete(oldLength, longIndex - 1);
    1.35 -            }
    1.36 -            setArray(array);
    1.37 -        }
    1.38 -    }
    1.39 -
    1.40      private void doesNotHave(final int index, final int value, final int callSiteFlags) {
    1.41          final long oldLength = getArray().length();
    1.42          final long longIndex = ArrayIndex.toLongIndex(index);
    1.43          if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
    1.44              final boolean strict = isStrictFlag(callSiteFlags);
    1.45 -            setArray(getArray().set(index, value, strict));
    1.46 -            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
    1.47 +            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
    1.48          }
    1.49      }
    1.50  
    1.51 @@ -3128,8 +3112,7 @@
    1.52          final long longIndex = ArrayIndex.toLongIndex(index);
    1.53          if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
    1.54              final boolean strict = isStrictFlag(callSiteFlags);
    1.55 -            setArray(getArray().set(index, value, strict));
    1.56 -            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
    1.57 +            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
    1.58          }
    1.59      }
    1.60  
    1.61 @@ -3138,8 +3121,7 @@
    1.62          final long longIndex = ArrayIndex.toLongIndex(index);
    1.63          if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
    1.64              final boolean strict = isStrictFlag(callSiteFlags);
    1.65 -            setArray(getArray().set(index, value, strict));
    1.66 -            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
    1.67 +            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
    1.68          }
    1.69      }
    1.70  
    1.71 @@ -3148,8 +3130,7 @@
    1.72          final long longIndex = ArrayIndex.toLongIndex(index);
    1.73          if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
    1.74              final boolean strict = isStrictFlag(callSiteFlags);
    1.75 -            setArray(getArray().set(index, value, strict));
    1.76 -            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
    1.77 +            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
    1.78          }
    1.79      }
    1.80  
     2.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Thu Oct 01 21:27:30 2015 +0530
     2.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Thu Oct 01 10:37:25 2015 +0200
     2.3 @@ -258,7 +258,7 @@
     2.4       * Factory method for unspecified array - start as int
     2.5       * @return ArrayData
     2.6       */
     2.7 -    public final static ArrayData initialArray() {
     2.8 +    public static ArrayData initialArray() {
     2.9          return new IntArrayData();
    2.10      }
    2.11  
    2.12 @@ -278,7 +278,7 @@
    2.13       * @param size size required
    2.14       * @return size given, always >= size
    2.15       */
    2.16 -    protected final static int alignUp(final int size) {
    2.17 +    protected static int alignUp(final int size) {
    2.18          return size + CHUNK_SIZE - 1 & ~(CHUNK_SIZE - 1);
    2.19      }
    2.20  
    2.21 @@ -288,7 +288,7 @@
    2.22       * @param length the initial length
    2.23       * @return ArrayData
    2.24       */
    2.25 -    public static final ArrayData allocate(final int length) {
    2.26 +    public static ArrayData allocate(final int length) {
    2.27          if (length == 0) {
    2.28              return new IntArrayData();
    2.29          } else if (length >= SparseArrayData.MAX_DENSE_LENGTH) {
    2.30 @@ -304,7 +304,7 @@
    2.31       * @param  array the array
    2.32       * @return ArrayData wrapping this array
    2.33       */
    2.34 -    public static final ArrayData allocate(final Object array) {
    2.35 +    public static ArrayData allocate(final Object array) {
    2.36          final Class<?> clazz = array.getClass();
    2.37  
    2.38          if (clazz == int[].class) {
    2.39 @@ -324,7 +324,7 @@
    2.40       * @param array the array to use for initial elements
    2.41       * @return the ArrayData
    2.42       */
    2.43 -    public static final ArrayData allocate(final int[] array) {
    2.44 +    public static ArrayData allocate(final int[] array) {
    2.45           return new IntArrayData(array, array.length);
    2.46      }
    2.47  
    2.48 @@ -334,7 +334,7 @@
    2.49       * @param array the array to use for initial elements
    2.50       * @return the ArrayData
    2.51       */
    2.52 -    public static final ArrayData allocate(final long[] array) {
    2.53 +    public static ArrayData allocate(final long[] array) {
    2.54          return new LongArrayData(array, array.length);
    2.55      }
    2.56  
    2.57 @@ -344,7 +344,7 @@
    2.58       * @param array the array to use for initial elements
    2.59       * @return the ArrayData
    2.60       */
    2.61 -    public static final ArrayData allocate(final double[] array) {
    2.62 +    public static ArrayData allocate(final double[] array) {
    2.63          return new NumberArrayData(array, array.length);
    2.64      }
    2.65  
    2.66 @@ -354,7 +354,7 @@
    2.67       * @param array the array to use for initial elements
    2.68       * @return the ArrayData
    2.69       */
    2.70 -    public static final ArrayData allocate(final Object[] array) {
    2.71 +    public static ArrayData allocate(final Object[] array) {
    2.72          return new ObjectArrayData(array, array.length);
    2.73      }
    2.74  
    2.75 @@ -364,7 +364,7 @@
    2.76       * @param buf the nio ByteBuffer to wrap
    2.77       * @return the ArrayData
    2.78       */
    2.79 -    public static final ArrayData allocate(final ByteBuffer buf) {
    2.80 +    public static ArrayData allocate(final ByteBuffer buf) {
    2.81          return new ByteBufferArrayData(buf);
    2.82      }
    2.83  
    2.84 @@ -374,7 +374,7 @@
    2.85       * @param underlying  the underlying ArrayData to wrap in the freeze filter
    2.86       * @return the frozen ArrayData
    2.87       */
    2.88 -    public static final ArrayData freeze(final ArrayData underlying) {
    2.89 +    public static ArrayData freeze(final ArrayData underlying) {
    2.90          return new FrozenArrayFilter(underlying);
    2.91      }
    2.92  
    2.93 @@ -384,7 +384,7 @@
    2.94       * @param underlying  the underlying ArrayData to wrap in the seal filter
    2.95       * @return the sealed ArrayData
    2.96       */
    2.97 -    public static final ArrayData seal(final ArrayData underlying) {
    2.98 +    public static ArrayData seal(final ArrayData underlying) {
    2.99          return new SealedArrayFilter(underlying);
   2.100      }
   2.101  
   2.102 @@ -394,7 +394,7 @@
   2.103       * @param  underlying the underlying ArrayData to wrap in the non extensible filter
   2.104       * @return new array data, filtered
   2.105       */
   2.106 -    public static final ArrayData preventExtension(final ArrayData underlying) {
   2.107 +    public static ArrayData preventExtension(final ArrayData underlying) {
   2.108          return new NonExtensibleArrayFilter(underlying);
   2.109      }
   2.110  
   2.111 @@ -404,7 +404,7 @@
   2.112       * @param underlying the underlying ArrayDAta to wrap in the non extensible filter
   2.113       * @return new array data, filtered
   2.114       */
   2.115 -    public static final ArrayData setIsLengthNotWritable(final ArrayData underlying) {
   2.116 +    public static ArrayData setIsLengthNotWritable(final ArrayData underlying) {
   2.117          return new LengthNotWritableFilter(underlying);
   2.118      }
   2.119  
   2.120 @@ -676,19 +676,34 @@
   2.121      }
   2.122  
   2.123      /**
   2.124 -     * Returns if element at specific index range can be deleted or not.
   2.125 +     * Returns if element at specific index can be deleted or not.
   2.126       *
   2.127 -     * @param fromIndex  the start index
   2.128 -     * @param toIndex    the end index
   2.129 +     * @param longIndex  the index
   2.130       * @param strict     are we in strict mode
   2.131       *
   2.132       * @return true if range can be deleted
   2.133       */
   2.134 -    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
   2.135 +    public boolean canDelete(final long longIndex, final boolean strict) {
   2.136          return true;
   2.137      }
   2.138  
   2.139      /**
   2.140 +     * Delete a range from the array if {@code fromIndex} is less than or equal to {@code toIndex}
   2.141 +     * and the array supports deletion.
   2.142 +     *
   2.143 +     * @param fromIndex  the start index (inclusive)
   2.144 +     * @param toIndex    the end index (inclusive)
   2.145 +     * @param strict     are we in strict mode
   2.146 +     * @return an array with the range deleted, or this array if no deletion took place
   2.147 +     */
   2.148 +    public final ArrayData safeDelete(final long fromIndex, final long toIndex, final boolean strict) {
   2.149 +        if (fromIndex <= toIndex && canDelete(fromIndex, strict)) {
   2.150 +            return delete(fromIndex, toIndex);
   2.151 +        }
   2.152 +        return this;
   2.153 +    }
   2.154 +
   2.155 +    /**
   2.156       * Returns property descriptor for element at a given index
   2.157       *
   2.158       * @param global the global object
     3.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java	Thu Oct 01 21:27:30 2015 +0530
     3.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java	Thu Oct 01 10:37:25 2015 +0200
     3.3 @@ -164,7 +164,7 @@
     3.4      }
     3.5  
     3.6      @Override
     3.7 -    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
     3.8 +    public boolean canDelete(final long longIndex, final boolean strict) {
     3.9          return false;
    3.10      }
    3.11  
     4.1 --- a/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java	Thu Oct 01 21:27:30 2015 +0530
     4.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java	Thu Oct 01 10:37:25 2015 +0200
     4.3 @@ -50,15 +50,15 @@
     4.4  
     4.5      @Override
     4.6      public boolean canDelete(final int index, final boolean strict) {
     4.7 -        if (strict) {
     4.8 -            throw typeError("cant.delete.property", Integer.toString(index), "sealed array");
     4.9 -        }
    4.10 -        return false;
    4.11 +        return canDelete(ArrayIndex.toLongIndex(index), strict);
    4.12      }
    4.13  
    4.14      @Override
    4.15 -    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
    4.16 -        return canDelete((int) fromIndex, strict);
    4.17 +    public boolean canDelete(final long longIndex, final boolean strict) {
    4.18 +        if (strict) {
    4.19 +            throw typeError("cant.delete.property", Long.toString(longIndex), "sealed array");
    4.20 +        }
    4.21 +        return false;
    4.22      }
    4.23  
    4.24      @Override
     5.1 --- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Thu Oct 01 21:27:30 2015 +0530
     5.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Thu Oct 01 10:37:25 2015 +0200
     5.3 @@ -166,8 +166,9 @@
     5.4      @Override
     5.5      public ArrayData set(final int index, final Object value, final boolean strict) {
     5.6          if (index >= 0 && index < maxDenseLength) {
     5.7 +            final long oldLength = underlying.length();
     5.8              ensure(index);
     5.9 -            underlying = underlying.set(index, value, strict);
    5.10 +            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
    5.11              setLength(Math.max(underlying.length(), length()));
    5.12          } else {
    5.13              final Long longIndex = indexToKey(index);
    5.14 @@ -181,8 +182,9 @@
    5.15      @Override
    5.16      public ArrayData set(final int index, final int value, final boolean strict) {
    5.17          if (index >= 0 && index < maxDenseLength) {
    5.18 +            final long oldLength = underlying.length();
    5.19              ensure(index);
    5.20 -            underlying = underlying.set(index, value, strict);
    5.21 +            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
    5.22              setLength(Math.max(underlying.length(), length()));
    5.23          } else {
    5.24              final Long longIndex = indexToKey(index);
    5.25 @@ -195,8 +197,9 @@
    5.26      @Override
    5.27      public ArrayData set(final int index, final long value, final boolean strict) {
    5.28          if (index >= 0 && index < maxDenseLength) {
    5.29 +            final long oldLength = underlying.length();
    5.30              ensure(index);
    5.31 -            underlying = underlying.set(index, value, strict);
    5.32 +            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
    5.33              setLength(Math.max(underlying.length(), length()));
    5.34          } else {
    5.35              final Long longIndex = indexToKey(index);
    5.36 @@ -209,8 +212,9 @@
    5.37      @Override
    5.38      public ArrayData set(final int index, final double value, final boolean strict) {
    5.39          if (index >= 0 && index < maxDenseLength) {
    5.40 +            final long oldLength = underlying.length();
    5.41              ensure(index);
    5.42 -            underlying = underlying.set(index, value, strict);
    5.43 +            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
    5.44              setLength(Math.max(underlying.length(), length()));
    5.45          } else {
    5.46              final Long longIndex = indexToKey(index);
     6.1 --- a/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java	Thu Oct 01 21:27:30 2015 +0530
     6.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java	Thu Oct 01 10:37:25 2015 +0200
     6.3 @@ -83,7 +83,7 @@
     6.4      }
     6.5  
     6.6      @Override
     6.7 -    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
     6.8 +    public boolean canDelete(final long longIndex, final boolean strict) {
     6.9          return false;
    6.10      }
    6.11  
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/script/basic/JDK-8138632.js	Thu Oct 01 10:37:25 2015 +0200
     7.3 @@ -0,0 +1,35 @@
     7.4 +/*
     7.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
     7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 + * 
     7.8 + * This code is free software; you can redistribute it and/or modify it
     7.9 + * under the terms of the GNU General Public License version 2 only, as
    7.10 + * published by the Free Software Foundation.
    7.11 + * 
    7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.15 + * version 2 for more details (a copy is included in the LICENSE file that
    7.16 + * accompanied this code).
    7.17 + * 
    7.18 + * You should have received a copy of the GNU General Public License version
    7.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.21 + * 
    7.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    7.23 + * or visit www.oracle.com if you need additional information or have any
    7.24 + * questions.
    7.25 + */
    7.26 +
    7.27 +/**
    7.28 + * JDK-8138632: Sparse array does not handle growth of underlying dense array
    7.29 + *
    7.30 + * @test
    7.31 + * @run
    7.32 + */
    7.33 +
    7.34 +var x = [];
    7.35 +x[10000000] = 1;
    7.36 +x[10] = 1;
    7.37 +x[20] = 1;
    7.38 +print(Object.keys(x));
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/test/script/basic/JDK-8138632.js.EXPECTED	Thu Oct 01 10:37:25 2015 +0200
     8.3 @@ -0,0 +1,1 @@
     8.4 +10,20,10000000

mercurial