Thu, 17 Oct 2013 17:33:16 +0200
8026701: Array.prototype.splice is slow on dense arrays
Reviewed-by: lagergren, sundar, jlaskey
1.1 --- a/src/jdk/nashorn/internal/objects/NativeArray.java Thu Oct 17 12:38:50 2013 +0200 1.2 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java Thu Oct 17 17:33:16 2013 +0200 1.3 @@ -1007,19 +1007,42 @@ 1.4 final long actualStart = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len); 1.5 final long actualDeleteCount = Math.min(Math.max(JSType.toLong(deleteCount), 0), len - actualStart); 1.6 1.7 - final NativeArray array = new NativeArray(actualDeleteCount); 1.8 + NativeArray returnValue; 1.9 1.10 - for (long k = 0; k < actualDeleteCount; k++) { 1.11 - final long from = actualStart + k; 1.12 + if (actualStart <= Integer.MAX_VALUE && actualDeleteCount <= Integer.MAX_VALUE && bulkable(sobj)) { 1.13 + try { 1.14 + returnValue = new NativeArray(sobj.getArray().fastSplice((int)actualStart, (int)actualDeleteCount, items.length)); 1.15 + 1.16 + // Since this is a dense bulkable array we can use faster defineOwnProperty to copy new elements 1.17 + int k = (int) actualStart; 1.18 + for (int i = 0; i < items.length; i++, k++) { 1.19 + sobj.defineOwnProperty(k, items[i]); 1.20 + } 1.21 + } catch (UnsupportedOperationException uoe) { 1.22 + returnValue = slowSplice(sobj, actualStart, actualDeleteCount, items, len); 1.23 + } 1.24 + } else { 1.25 + returnValue = slowSplice(sobj, actualStart, actualDeleteCount, items, len); 1.26 + } 1.27 + 1.28 + return returnValue; 1.29 + } 1.30 + 1.31 + private static NativeArray slowSplice(final ScriptObject sobj, final long start, final long deleteCount, final Object[] items, final long len) { 1.32 + 1.33 + final NativeArray array = new NativeArray(deleteCount); 1.34 + 1.35 + for (long k = 0; k < deleteCount; k++) { 1.36 + final long from = start + k; 1.37 1.38 if (sobj.has(from)) { 1.39 array.defineOwnProperty(ArrayIndex.getArrayIndex(k), sobj.get(from)); 1.40 } 1.41 } 1.42 1.43 - if (items.length < actualDeleteCount) { 1.44 - for (long k = actualStart; k < (len - actualDeleteCount); k++) { 1.45 - final long from = k + actualDeleteCount; 1.46 + if (items.length < deleteCount) { 1.47 + for (long k = start; k < (len - deleteCount); k++) { 1.48 + final long from = k + deleteCount; 1.49 final long to = k + items.length; 1.50 1.51 if (sobj.has(from)) { 1.52 @@ -1029,12 +1052,12 @@ 1.53 } 1.54 } 1.55 1.56 - for (long k = len; k > (len - actualDeleteCount + items.length); k--) { 1.57 + for (long k = len; k > (len - deleteCount + items.length); k--) { 1.58 sobj.delete(k - 1, true); 1.59 } 1.60 - } else if (items.length > actualDeleteCount) { 1.61 - for (long k = len - actualDeleteCount; k > actualStart; k--) { 1.62 - final long from = k + actualDeleteCount - 1; 1.63 + } else if (items.length > deleteCount) { 1.64 + for (long k = len - deleteCount; k > start; k--) { 1.65 + final long from = k + deleteCount - 1; 1.66 final long to = k + items.length - 1; 1.67 1.68 if (sobj.has(from)) { 1.69 @@ -1046,12 +1069,12 @@ 1.70 } 1.71 } 1.72 1.73 - long k = actualStart; 1.74 + long k = start; 1.75 for (int i = 0; i < items.length; i++, k++) { 1.76 sobj.set(k, items[i], true); 1.77 } 1.78 1.79 - final long newLength = len - actualDeleteCount + items.length; 1.80 + final long newLength = len - deleteCount + items.length; 1.81 sobj.set("length", newLength, true); 1.82 1.83 return array;
2.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Oct 17 12:38:50 2013 +0200 2.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Oct 17 17:33:16 2013 +0200 2.3 @@ -594,7 +594,7 @@ 2.4 * @param index key for property 2.5 * @param value value to define 2.6 */ 2.7 - protected final void defineOwnProperty(final int index, final Object value) { 2.8 + public final void defineOwnProperty(final int index, final Object value) { 2.9 assert isValidArrayIndex(index) : "invalid array index"; 2.10 final long longIndex = ArrayIndex.toLongIndex(index); 2.11 if (longIndex >= getArray().length()) {
3.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Thu Oct 17 12:38:50 2013 +0200 3.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Thu Oct 17 17:33:16 2013 +0200 3.3 @@ -461,7 +461,23 @@ 3.4 */ 3.5 public abstract ArrayData slice(long from, long to); 3.6 3.7 - private static Class<?> widestType(final Object... items) { 3.8 + /** 3.9 + * Fast splice operation. This just modifies the array according to the number of 3.10 + * elements added and deleted but does not insert the added elements. Throws 3.11 + * {@code UnsupportedOperationException} if fast splice operation is not supported 3.12 + * for this class or arguments. 3.13 + * 3.14 + * @param start start index of splice operation 3.15 + * @param removed number of removed elements 3.16 + * @param added number of added elements 3.17 + * @throws UnsupportedOperationException if fast splice is not supported for the class or arguments. 3.18 + */ 3.19 + public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 3.20 + throw new UnsupportedOperationException(); 3.21 + } 3.22 + 3.23 + 3.24 + static Class<?> widestType(final Object... items) { 3.25 assert items.length > 0; 3.26 3.27 Class<?> widest = Integer.class;
4.1 --- a/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Thu Oct 17 12:38:50 2013 +0200 4.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Thu Oct 17 17:33:16 2013 +0200 4.3 @@ -269,4 +269,32 @@ 4.4 4.5 return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); 4.6 } 4.7 + 4.8 + @Override 4.9 + public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 4.10 + final long oldLength = length(); 4.11 + final long newLength = oldLength - removed + added; 4.12 + if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 4.13 + throw new UnsupportedOperationException(); 4.14 + } 4.15 + final ArrayData returnValue = (removed == 0) ? 4.16 + EMPTY_ARRAY : new IntArrayData(Arrays.copyOfRange(array, start, start + removed), removed); 4.17 + 4.18 + if (newLength != oldLength) { 4.19 + final int[] newArray; 4.20 + 4.21 + if (newLength > array.length) { 4.22 + newArray = new int[ArrayData.nextSize((int)newLength)]; 4.23 + System.arraycopy(array, 0, newArray, 0, start); 4.24 + } else { 4.25 + newArray = array; 4.26 + } 4.27 + 4.28 + System.arraycopy(array, start + removed, newArray, start + added, (int)(oldLength - start - removed)); 4.29 + array = newArray; 4.30 + setLength(newLength); 4.31 + } 4.32 + 4.33 + return returnValue; 4.34 + } 4.35 }
5.1 --- a/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Thu Oct 17 12:38:50 2013 +0200 5.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Thu Oct 17 17:33:16 2013 +0200 5.3 @@ -92,7 +92,7 @@ 5.4 5.5 @Override 5.6 public ArrayData convert(final Class<?> type) { 5.7 - if (type == Long.class) { 5.8 + if (type == Integer.class || type == Long.class) { 5.9 return this; 5.10 } 5.11 final int length = (int) length(); 5.12 @@ -238,4 +238,32 @@ 5.13 final long newLength = to - start; 5.14 return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); 5.15 } 5.16 + 5.17 + @Override 5.18 + public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 5.19 + final long oldLength = length(); 5.20 + final long newLength = oldLength - removed + added; 5.21 + if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 5.22 + throw new UnsupportedOperationException(); 5.23 + } 5.24 + final ArrayData returnValue = (removed == 0) ? 5.25 + EMPTY_ARRAY : new LongArrayData(Arrays.copyOfRange(array, start, start + removed), removed); 5.26 + 5.27 + if (newLength != oldLength) { 5.28 + final long[] newArray; 5.29 + 5.30 + if (newLength > array.length) { 5.31 + newArray = new long[ArrayData.nextSize((int)newLength)]; 5.32 + System.arraycopy(array, 0, newArray, 0, start); 5.33 + } else { 5.34 + newArray = array; 5.35 + } 5.36 + 5.37 + System.arraycopy(array, start + removed, newArray, start + added, (int)(oldLength - start - removed)); 5.38 + array = newArray; 5.39 + setLength(newLength); 5.40 + } 5.41 + 5.42 + return returnValue; 5.43 + } 5.44 }
6.1 --- a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Thu Oct 17 12:38:50 2013 +0200 6.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Thu Oct 17 17:33:16 2013 +0200 6.3 @@ -218,4 +218,32 @@ 6.4 final long newLength = to - start; 6.5 return new NumberArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); 6.6 } 6.7 + 6.8 + @Override 6.9 + public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 6.10 + final long oldLength = length(); 6.11 + final long newLength = oldLength - removed + added; 6.12 + if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 6.13 + throw new UnsupportedOperationException(); 6.14 + } 6.15 + final ArrayData returnValue = (removed == 0) ? 6.16 + EMPTY_ARRAY : new NumberArrayData(Arrays.copyOfRange(array, start, start + removed), removed); 6.17 + 6.18 + if (newLength != oldLength) { 6.19 + final double[] newArray; 6.20 + 6.21 + if (newLength > array.length) { 6.22 + newArray = new double[ArrayData.nextSize((int)newLength)]; 6.23 + System.arraycopy(array, 0, newArray, 0, start); 6.24 + } else { 6.25 + newArray = array; 6.26 + } 6.27 + 6.28 + System.arraycopy(array, start + removed, newArray, start + added, (int)(oldLength - start - removed)); 6.29 + array = newArray; 6.30 + setLength(newLength); 6.31 + } 6.32 + 6.33 + return returnValue; 6.34 + } 6.35 }
7.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Thu Oct 17 12:38:50 2013 +0200 7.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Thu Oct 17 17:33:16 2013 +0200 7.3 @@ -206,4 +206,32 @@ 7.4 final long newLength = to - start; 7.5 return new ObjectArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); 7.6 } 7.7 + 7.8 + @Override 7.9 + public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 7.10 + final long oldLength = length(); 7.11 + final long newLength = oldLength - removed + added; 7.12 + if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 7.13 + throw new UnsupportedOperationException(); 7.14 + } 7.15 + final ArrayData returnValue = (removed == 0) ? 7.16 + EMPTY_ARRAY : new ObjectArrayData(Arrays.copyOfRange(array, start, start + removed), removed); 7.17 + 7.18 + if (newLength != oldLength) { 7.19 + final Object[] newArray; 7.20 + 7.21 + if (newLength > array.length) { 7.22 + newArray = new Object[ArrayData.nextSize((int)newLength)]; 7.23 + System.arraycopy(array, 0, newArray, 0, start); 7.24 + } else { 7.25 + newArray = array; 7.26 + } 7.27 + 7.28 + System.arraycopy(array, start + removed, newArray, start + added, (int)(oldLength - start - removed)); 7.29 + array = newArray; 7.30 + setLength(newLength); 7.31 + } 7.32 + 7.33 + return returnValue; 7.34 + } 7.35 }
8.1 --- a/test/examples/array-micro.js Thu Oct 17 12:38:50 2013 +0200 8.2 +++ b/test/examples/array-micro.js Thu Oct 17 17:33:16 2013 +0200 8.3 @@ -90,6 +90,24 @@ 8.4 array[6] = 6; 8.5 }); 8.6 8.7 +bench("push", function() { 8.8 + var arr = [1, 2, 3]; 8.9 + arr.push(4); 8.10 + arr.push(5); 8.11 + arr.push(6); 8.12 +}); 8.13 + 8.14 +bench("pop", function() { 8.15 + var arr = [1, 2, 3]; 8.16 + arr.pop(); 8.17 + arr.pop(); 8.18 + arr.pop(); 8.19 +}); 8.20 + 8.21 +bench("splice", function() { 8.22 + [1, 2, 3].splice(0, 2, 5, 6, 7); 8.23 +}); 8.24 + 8.25 var all = function(e) { return true; }; 8.26 var none = function(e) { return false; }; 8.27
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/test/script/basic/JDK-8026701.js Thu Oct 17 17:33:16 2013 +0200 9.3 @@ -0,0 +1,72 @@ 9.4 +/* 9.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 9.7 + * 9.8 + * This code is free software; you can redistribute it and/or modify it 9.9 + * under the terms of the GNU General Public License version 2 only, as 9.10 + * published by the Free Software Foundation. 9.11 + * 9.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 9.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 9.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 9.15 + * version 2 for more details (a copy is included in the LICENSE file that 9.16 + * accompanied this code). 9.17 + * 9.18 + * You should have received a copy of the GNU General Public License version 9.19 + * 2 along with this work; if not, write to the Free Software Foundation, 9.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 9.21 + * 9.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 9.23 + * or visit www.oracle.com if you need additional information or have any 9.24 + * questions. 9.25 + */ 9.26 + 9.27 +/** 9.28 + * JDK-8026701: Array.prototype.splice is slow on dense arrays 9.29 + * 9.30 + * @test 9.31 + * @run 9.32 + */ 9.33 + 9.34 +function testSplice(arr, e1, e2, e3) { 9.35 + try { 9.36 + print(arr); 9.37 + print(arr.splice(3, 0, e1, e2, e3)); 9.38 + print(arr); 9.39 + print(arr.splice(2, 3)); 9.40 + print(arr); 9.41 + print(arr.splice(2, 3, arr[2], arr[3], arr[4])); 9.42 + print(arr); 9.43 + print(arr.splice(20, 10)); 9.44 + print(arr); 9.45 + print(arr.splice(arr.length, 0, e1, e2, e3)); 9.46 + print(arr); 9.47 + print(arr.splice(0, 2, arr[0], arr[1], arr[2], arr[3])); 9.48 + print(arr); 9.49 + } catch (error) { 9.50 + print(error); 9.51 + } 9.52 +} 9.53 + 9.54 +function convert(array, type) { 9.55 + return (typeof Java === "undefined") ? array : Java.from(Java.to(array, type)); 9.56 +} 9.57 + 9.58 +// run some splice tests on all dense array implementations 9.59 +testSplice([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], -1, -2, -3); 9.60 +testSplice(convert([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "long[]"), -1, -2, -3); 9.61 +testSplice(convert([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "double[]"), -1, -2, -3); 9.62 +testSplice(["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], -1, -2, -3); 9.63 + 9.64 +// test array conversion during splice 9.65 +testSplice([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], -1, "-2", "-3"); 9.66 +testSplice([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], -1, -2.5, -3.5); 9.67 +testSplice(convert([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "long[]"), -1, "-2", "-3"); 9.68 +testSplice(convert([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "long[]"), -1, -2.5, -3.5); 9.69 +testSplice(convert([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "double[]"), -1, "-2", "-3"); 9.70 + 9.71 +// test combination with defined elements 9.72 +testSplice(Object.defineProperty([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5, {value: 13}), -1, -2, -3); 9.73 +testSplice(Object.defineProperty([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5, {value: 13, writable: false}), -1, -2, -3); 9.74 +testSplice(Object.defineProperty([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5, {value: 13, configurable: false}), -1, -2, -3); 9.75 +testSplice(Object.defineProperty([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5, {value: 13, writable: false, configurable: false}), -1, -2, -3);
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/test/script/basic/JDK-8026701.js.EXPECTED Thu Oct 17 17:33:16 2013 +0200 10.3 @@ -0,0 +1,147 @@ 10.4 +1,2,3,4,5,6,7,8,9,10 10.5 + 10.6 +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 10.7 +3,-1,-2 10.8 +1,2,-3,4,5,6,7,8,9,10 10.9 +-3,4,5 10.10 +1,2,-3,4,5,6,7,8,9,10 10.11 + 10.12 +1,2,-3,4,5,6,7,8,9,10 10.13 + 10.14 +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 10.15 +1,2 10.16 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 10.17 +1,2,3,4,5,6,7,8,9,10 10.18 + 10.19 +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 10.20 +3,-1,-2 10.21 +1,2,-3,4,5,6,7,8,9,10 10.22 +-3,4,5 10.23 +1,2,-3,4,5,6,7,8,9,10 10.24 + 10.25 +1,2,-3,4,5,6,7,8,9,10 10.26 + 10.27 +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 10.28 +1,2 10.29 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 10.30 +1,2,3,4,5,6,7,8,9,10 10.31 + 10.32 +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 10.33 +3,-1,-2 10.34 +1,2,-3,4,5,6,7,8,9,10 10.35 +-3,4,5 10.36 +1,2,-3,4,5,6,7,8,9,10 10.37 + 10.38 +1,2,-3,4,5,6,7,8,9,10 10.39 + 10.40 +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 10.41 +1,2 10.42 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 10.43 +1,2,3,4,5,6,7,8,9,10 10.44 + 10.45 +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 10.46 +3,-1,-2 10.47 +1,2,-3,4,5,6,7,8,9,10 10.48 +-3,4,5 10.49 +1,2,-3,4,5,6,7,8,9,10 10.50 + 10.51 +1,2,-3,4,5,6,7,8,9,10 10.52 + 10.53 +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 10.54 +1,2 10.55 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 10.56 +1,2,3,4,5,6,7,8,9,10 10.57 + 10.58 +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 10.59 +3,-1,-2 10.60 +1,2,-3,4,5,6,7,8,9,10 10.61 +-3,4,5 10.62 +1,2,-3,4,5,6,7,8,9,10 10.63 + 10.64 +1,2,-3,4,5,6,7,8,9,10 10.65 + 10.66 +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 10.67 +1,2 10.68 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 10.69 +1,2,3,4,5,6,7,8,9,10 10.70 + 10.71 +1,2,3,-1,-2.5,-3.5,4,5,6,7,8,9,10 10.72 +3,-1,-2.5 10.73 +1,2,-3.5,4,5,6,7,8,9,10 10.74 +-3.5,4,5 10.75 +1,2,-3.5,4,5,6,7,8,9,10 10.76 + 10.77 +1,2,-3.5,4,5,6,7,8,9,10 10.78 + 10.79 +1,2,-3.5,4,5,6,7,8,9,10,-1,-2.5,-3.5 10.80 +1,2 10.81 +1,2,-3.5,4,-3.5,4,5,6,7,8,9,10,-1,-2.5,-3.5 10.82 +1,2,3,4,5,6,7,8,9,10 10.83 + 10.84 +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 10.85 +3,-1,-2 10.86 +1,2,-3,4,5,6,7,8,9,10 10.87 +-3,4,5 10.88 +1,2,-3,4,5,6,7,8,9,10 10.89 + 10.90 +1,2,-3,4,5,6,7,8,9,10 10.91 + 10.92 +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 10.93 +1,2 10.94 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 10.95 +1,2,3,4,5,6,7,8,9,10 10.96 + 10.97 +1,2,3,-1,-2.5,-3.5,4,5,6,7,8,9,10 10.98 +3,-1,-2.5 10.99 +1,2,-3.5,4,5,6,7,8,9,10 10.100 +-3.5,4,5 10.101 +1,2,-3.5,4,5,6,7,8,9,10 10.102 + 10.103 +1,2,-3.5,4,5,6,7,8,9,10 10.104 + 10.105 +1,2,-3.5,4,5,6,7,8,9,10,-1,-2.5,-3.5 10.106 +1,2 10.107 +1,2,-3.5,4,-3.5,4,5,6,7,8,9,10,-1,-2.5,-3.5 10.108 +1,2,3,4,5,6,7,8,9,10 10.109 + 10.110 +1,2,3,-1,-2,-3,4,5,6,7,8,9,10 10.111 +3,-1,-2 10.112 +1,2,-3,4,5,6,7,8,9,10 10.113 +-3,4,5 10.114 +1,2,-3,4,5,6,7,8,9,10 10.115 + 10.116 +1,2,-3,4,5,6,7,8,9,10 10.117 + 10.118 +1,2,-3,4,5,6,7,8,9,10,-1,-2,-3 10.119 +1,2 10.120 +1,2,-3,4,-3,4,5,6,7,8,9,10,-1,-2,-3 10.121 +1,2,3,4,5,13,7,8,9,10 10.122 + 10.123 +1,2,3,-1,-2,-3,4,5,13,7,8,9,10 10.124 +3,-1,-2 10.125 +1,2,-3,4,5,13,7,8,9,10 10.126 +-3,4,5 10.127 +1,2,-3,4,5,13,7,8,9,10 10.128 + 10.129 +1,2,-3,4,5,13,7,8,9,10 10.130 + 10.131 +1,2,-3,4,5,13,7,8,9,10,-1,-2,-3 10.132 +1,2 10.133 +1,2,-3,4,-3,4,5,13,7,8,9,10,-1,-2,-3 10.134 +1,2,3,4,5,13,7,8,9,10 10.135 +TypeError: "5" is not a writable property of [object Array] 10.136 +1,2,3,4,5,13,7,8,9,10 10.137 + 10.138 +1,2,3,-1,-2,-3,4,5,13,7,8,9,10 10.139 +3,-1,-2 10.140 +1,2,-3,4,5,13,7,8,9,10 10.141 +-3,4,5 10.142 +1,2,-3,4,5,13,7,8,9,10 10.143 + 10.144 +1,2,-3,4,5,13,7,8,9,10 10.145 + 10.146 +1,2,-3,4,5,13,7,8,9,10,-1,-2,-3 10.147 +1,2 10.148 +1,2,-3,4,-3,4,5,13,7,8,9,10,-1,-2,-3 10.149 +1,2,3,4,5,13,7,8,9,10 10.150 +TypeError: "5" is not a writable property of [object Array]