Bug 1364345 - Optimize splice to shift the elements header when deleting from the start of the array. r=anba
authorJan de Mooij <jdemooij@mozilla.com>
Mon, 22 May 2017 12:52:10 +0200
changeset 359976 fe4dbfcf932825e4d1595769106a7e62651f4c61
parent 359975 f156ae867392eb03b562ef5a9de1dfb49c956d2e
child 359977 0d91cc7f99eb9a0d82736b2890c635131afd6436
push id31866
push userkwierso@gmail.com
push dateMon, 22 May 2017 23:26:23 +0000
treeherdermozilla-central@5bc1c758ab57 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersanba
bugs1364345
milestone55.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 1364345 - Optimize splice to shift the elements header when deleting from the start of the array. r=anba
js/src/jsarray.cpp
js/src/vm/NativeObject-inl.h
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2849,23 +2849,28 @@ array_splice_impl(JSContext* cx, unsigne
         uint64_t targetIndex = actualStart + itemCount;
 
         if (CanOptimizeForDenseStorage<ArrayAccess::Write>(obj, len, cx)) {
             MOZ_ASSERT(sourceIndex <= len && targetIndex <= len && len <= UINT32_MAX,
                        "sourceIndex and targetIndex are uint32 array indices");
             MOZ_ASSERT(finalLength < len, "finalLength is strictly less than len");
 
             /* Steps 15.a-b. */
-            DenseElementResult result =
-                MoveAnyBoxedOrUnboxedDenseElements(cx, obj, uint32_t(targetIndex),
-                                                   uint32_t(sourceIndex),
-                                                   uint32_t(len - sourceIndex));
-            MOZ_ASSERT(result != DenseElementResult::Incomplete);
-            if (result == DenseElementResult::Failure)
-                return false;
+            if (targetIndex != 0 ||
+                !obj->is<NativeObject>() ||
+                !obj->as<NativeObject>().tryShiftDenseElements(sourceIndex))
+            {
+                DenseElementResult result =
+                    MoveAnyBoxedOrUnboxedDenseElements(cx, obj, uint32_t(targetIndex),
+                                                       uint32_t(sourceIndex),
+                                                       uint32_t(len - sourceIndex));
+                MOZ_ASSERT(result != DenseElementResult::Incomplete);
+                if (result == DenseElementResult::Failure)
+                    return false;
+            }
 
             /* Steps 15.c-d. */
             SetAnyBoxedOrUnboxedInitializedLength(cx, obj, uint32_t(finalLength));
         } else {
             /*
              * This is all very slow if the length is very large. We don't yet
              * have the ability to iterate in sorted order, so we just do the
              * pessimistic thing and let CheckForInterrupt handle the
--- a/js/src/vm/NativeObject-inl.h
+++ b/js/src/vm/NativeObject-inl.h
@@ -167,27 +167,27 @@ NativeObject::initDenseElements(uint32_t
     memcpy(&elements_[dstStart], src, count * sizeof(HeapSlot));
     elementsRangeWriteBarrierPost(dstStart, count);
 }
 
 inline bool
 NativeObject::tryShiftDenseElements(uint32_t count)
 {
     ObjectElements* header = getElementsHeader();
-    if (header->isCopyOnWrite() ||
+    if (header->initializedLength == count ||
+        count > ObjectElements::MaxShiftedElements ||
+        header->isCopyOnWrite() ||
         header->isFrozen() ||
-        header->hasNonwritableArrayLength() ||
-        header->initializedLength == count)
+        header->hasNonwritableArrayLength())
     {
         return false;
     }
 
     MOZ_ASSERT(count > 0);
     MOZ_ASSERT(count < header->initializedLength);
-    MOZ_ASSERT(count <= ObjectElements::MaxShiftedElements);
 
     if (MOZ_UNLIKELY(header->numShiftedElements() + count > ObjectElements::MaxShiftedElements)) {
         unshiftElements();
         header = getElementsHeader();
     }
 
     prepareElementRangeForOverwrite(0, count);
     header->addShiftedElements(count);