- 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,