Bug 928917 - Use initDenseElements instead of NewDenseCopiedArray to speed up slice on arrays with holes. r=jandem
authormasaya iseki <iseki.m.aa@gmail.com>
Wed, 27 Nov 2013 12:29:40 +0100
changeset 157813 0e9832497387d0fbb9dbbcd89ac58fb11bb0ed40
parent 157812 61ff58ee03e5b42a2ad9a8496db1abb4149240de
child 157814 61bf4acd28efa9aa7d71e3735ae1a77ea84faba1
push id25726
push usercbook@mozilla.com
push dateThu, 28 Nov 2013 10:47:25 +0000
treeherdermozilla-central@cdca43b7657d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs928917
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 928917 - Use initDenseElements instead of NewDenseCopiedArray to speed up slice on arrays with holes. r=jandem
js/src/jit-test/tests/basic/array-slice.js
js/src/jsarray.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/array-slice.js
@@ -0,0 +1,32 @@
+function check_specified_range_zero_base_slice() {
+    var arr = new Array(32)
+    arr[0]=0, arr[1]=1, arr[7]=7;
+    var res = arr.slice(0,10);
+    assertEq(arr[0],res[0]);
+    assertEq(arr[1],res[1]);
+    assertEq(arr[7],res[7]);
+    assertEq(res.length,10);
+}
+
+function check_specified_range_slice() {
+    var arr = new Array(32)
+    arr[0]=0, arr[6]=1, arr[8]=3;
+    var res = arr.slice(5,9);
+    assertEq(arr[6],res[1]);
+    assertEq(arr[8],res[3]);
+    assertEq(res.length,4);
+}
+
+function check_all_range_slice() {
+    var arr = new Array(32)
+    arr[0]=0, arr[6]=1, arr[8]=3;
+    var res = arr.slice();
+    assertEq(arr[0],res[0]);
+    assertEq(arr[6],res[6]);
+    assertEq(arr[8],res[8]);
+    assertEq(res.length,32);
+}
+
+check_all_range_slice();
+check_specified_range_slice();
+check_specified_range_zero_base_slice();
\ No newline at end of file
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2720,33 +2720,32 @@ array_slice(JSContext *cx, unsigned argc
             end = (uint32_t)d;
         }
     }
 
     if (begin > end)
         begin = end;
 
     Rooted<ArrayObject*> narr(cx);
-
-    if (obj->is<ArrayObject>() && end <= obj->getDenseInitializedLength() &&
-        !ObjectMayHaveExtraIndexedProperties(obj))
-    {
-        narr = NewDenseCopiedArray(cx, end - begin, obj, begin);
-        if (!narr)
-            return false;
-        TryReuseArrayType(obj, narr);
-        args.rval().setObject(*narr);
-        return true;
-    }
-
     narr = NewDenseAllocatedArray(cx, end - begin);
     if (!narr)
         return false;
     TryReuseArrayType(obj, narr);
 
+    if (obj->is<ArrayObject>() && !ObjectMayHaveExtraIndexedProperties(obj)) {
+        if (obj->getDenseInitializedLength() > begin) {
+            uint32_t numSourceElements = obj->getDenseInitializedLength() - begin;
+            uint32_t initLength = Min(numSourceElements, end - begin);
+            narr->setDenseInitializedLength(initLength);
+            narr->initDenseElements(0, &obj->getDenseElement(begin), initLength);
+        }
+        args.rval().setObject(*narr);
+        return true;
+    }
+
     RootedValue value(cx);
     for (slot = begin; slot < end; slot++) {
         if (!JS_CHECK_OPERATION_LIMIT(cx) ||
             !GetElement(cx, obj, slot, &hole, &value)) {
             return false;
         }
         if (!hole && !SetArrayElement(cx, narr, slot - begin, value))
             return false;