Title: [184767] trunk/Source/_javascript_Core
Revision
184767
Author
[email protected]
Date
2015-05-22 03:18:47 -0700 (Fri, 22 May 2015)

Log Message

[JSC] Speed up new array construction in Array.prototype.splice().
<https://webkit.org/b/145303>

Reviewed by Benjamin Poulain.

Give splice() a fast path just like slice(), for indexing types where the backing
store can be memcpy'd. I generalized JSArray::fastSlice() a little bit so it works
for this optimization as well.

7% progression on Kraken/stanford-crypto-pbkdf2.

* runtime/JSArray.h:
* runtime/JSArray.cpp:
(JSC::JSArray::fastSlice): Tweak this to return JSArray*, and don't bother throwing
out-of-memory exceptions. Let the caller worry about that.

* runtime/ArrayPrototype.cpp:
(JSC::arrayProtoFuncSlice): Update for fastSlice() changes.
(JSC::arrayProtoFuncSplice): If the object we're splicing out of is a bona fide
JSArray, use fastSlice() to create the returned array instead of doing a generic
get/put loop.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (184766 => 184767)


--- trunk/Source/_javascript_Core/ChangeLog	2015-05-22 08:15:34 UTC (rev 184766)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-05-22 10:18:47 UTC (rev 184767)
@@ -1,3 +1,27 @@
+2015-05-22  Andreas Kling  <[email protected]>
+
+        [JSC] Speed up new array construction in Array.prototype.splice().
+        <https://webkit.org/b/145303>
+
+        Reviewed by Benjamin Poulain.
+
+        Give splice() a fast path just like slice(), for indexing types where the backing
+        store can be memcpy'd. I generalized JSArray::fastSlice() a little bit so it works
+        for this optimization as well.
+
+        7% progression on Kraken/stanford-crypto-pbkdf2.
+
+        * runtime/JSArray.h:
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::fastSlice): Tweak this to return JSArray*, and don't bother throwing
+        out-of-memory exceptions. Let the caller worry about that.
+
+        * runtime/ArrayPrototype.cpp:
+        (JSC::arrayProtoFuncSlice): Update for fastSlice() changes.
+        (JSC::arrayProtoFuncSplice): If the object we're splicing out of is a bona fide
+        JSArray, use fastSlice() to create the returned array instead of doing a generic
+        get/put loop.
+
 2015-05-21  Filip Pizlo  <[email protected]>
 
         CPS rethreading should really get rid of GetLocals

Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (184766 => 184767)


--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2015-05-22 08:15:34 UTC (rev 184766)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2015-05-22 10:18:47 UTC (rev 184767)
@@ -602,9 +602,8 @@
     unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length);
 
     if (isJSArray(thisObj)) {
-        EncodedJSValue result;
-        if (asArray(thisObj)->fastSlice(*exec, begin, end - begin, result))
-            return result;
+        if (JSArray* result = asArray(thisObj)->fastSlice(*exec, begin, end - begin))
+            return JSValue::encode(result);
     }
 
     JSArray* result = constructEmptyArray(exec, nullptr, end - begin);
@@ -634,6 +633,8 @@
 {
     // 15.4.4.12
 
+    VM& vm = exec->vm();
+
     JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
     unsigned length = getLength(exec, thisObj);
     if (exec->hadException())
@@ -655,17 +656,22 @@
             deleteCount = static_cast<unsigned>(deleteDouble);
     }
 
-    JSArray* resObj = JSArray::tryCreateUninitialized(exec->vm(), exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), deleteCount);
-    if (!resObj)
-        return JSValue::encode(throwOutOfMemoryError(exec));
+    JSArray* result = nullptr;
 
-    JSValue result = resObj;
-    VM& vm = exec->vm();
-    for (unsigned k = 0; k < deleteCount; k++) {
-        JSValue v = getProperty(exec, thisObj, k + begin);
-        if (exec->hadException())
-            return JSValue::encode(jsUndefined());
-        resObj->initializeIndex(vm, k, v);
+    if (isJSArray(thisObj))
+        result = asArray(thisObj)->fastSlice(*exec, begin, deleteCount);
+
+    if (!result) {
+        result = JSArray::tryCreateUninitialized(vm, exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), deleteCount);
+        if (!result)
+            return JSValue::encode(throwOutOfMemoryError(exec));
+
+        for (unsigned k = 0; k < deleteCount; ++k) {
+            JSValue v = getProperty(exec, thisObj, k + begin);
+            if (exec->hadException())
+                return JSValue::encode(jsUndefined());
+            result->initializeIndex(vm, k, v);
+        }
     }
 
     unsigned additionalArgs = std::max<int>(exec->argumentCount() - 2, 0);

Modified: trunk/Source/_javascript_Core/runtime/JSArray.cpp (184766 => 184767)


--- trunk/Source/_javascript_Core/runtime/JSArray.cpp	2015-05-22 08:15:34 UTC (rev 184766)
+++ trunk/Source/_javascript_Core/runtime/JSArray.cpp	2015-05-22 10:18:47 UTC (rev 184767)
@@ -675,7 +675,7 @@
     }
 }
 
-bool JSArray::fastSlice(ExecState& exec, unsigned startIndex, unsigned count, EncodedJSValue& result)
+JSArray* JSArray::fastSlice(ExecState& exec, unsigned startIndex, unsigned count)
 {
     auto arrayType = indexingType();
     switch (arrayType) {
@@ -684,14 +684,12 @@
     case ArrayWithContiguous: {
         VM& vm = exec.vm();
         if (count >= MIN_SPARSE_ARRAY_INDEX || structure(vm)->holesMustForwardToPrototype(vm))
-            return false;
+            return nullptr;
 
         Structure* resultStructure = exec.lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(arrayType);
         JSArray* resultArray = JSArray::tryCreateUninitialized(vm, resultStructure, count);
-        if (!resultArray) {
-            result = JSValue::encode(throwOutOfMemoryError(&exec));
-            return true;
-        }
+        if (!resultArray)
+            return nullptr;
 
         auto& resultButterfly = *resultArray->butterfly();
         if (arrayType == ArrayWithDouble)
@@ -700,13 +698,11 @@
             memcpy(resultButterfly.contiguous().data(), m_butterfly->contiguous().data() + startIndex, sizeof(JSValue) * count);
         resultButterfly.setPublicLength(count);
 
-        result = JSValue::encode(resultArray);
-        return true;
+        return resultArray;
     }
     default:
-        break;
+        return nullptr;
     }
-    return false;
 }
 
 bool JSArray::shiftCountWithArrayStorage(VM& vm, unsigned startIndex, unsigned count, ArrayStorage* storage)

Modified: trunk/Source/_javascript_Core/runtime/JSArray.h (184766 => 184767)


--- trunk/Source/_javascript_Core/runtime/JSArray.h	2015-05-22 08:15:34 UTC (rev 184766)
+++ trunk/Source/_javascript_Core/runtime/JSArray.h	2015-05-22 10:18:47 UTC (rev 184767)
@@ -73,7 +73,7 @@
     JS_EXPORT_PRIVATE void push(ExecState*, JSValue);
     JS_EXPORT_PRIVATE JSValue pop(ExecState*);
 
-    bool fastSlice(ExecState&, unsigned startIndex, unsigned count, EncodedJSValue&);
+    JSArray* fastSlice(ExecState&, unsigned startIndex, unsigned count);
 
     enum ShiftCountMode {
         // This form of shift hints that we're doing queueing. With this assumption in hand,
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to