Changeset 266215 in webkit for trunk/Source/JavaScriptCore


Ignore:
Timestamp:
Aug 26, 2020, 6:55:08 PM (5 years ago)
Author:
Alexey Shvayka
Message:

Merge putLength() into setLength()
https://bugs.webkit.org/show_bug.cgi?id=211279

Reviewed by Darin Adler and Saam Barati.

JSTests:

  • microbenchmarks/array-shift-unshift-empty.js: Added.
  • stress/array-setLength-on-proxy-error.js: Added.

Source/JavaScriptCore:

This patch:

  1. Replaces all putLength() call sites with setLength(), saving two JSValue instantiations in arrayProtoFuncPop() and two in arrayProtoFuncShift().
  1. Merges putLength() into setLength(), removing superfluous put() call for JSArray. Also, performs put() in strict mode to preserve the original error messages, like ones in ProxyObject::performPut().
  1. Inlines performPop(), which avoided an extra index check and Identifier creation, as it was on the slow path anyway (note JSArray::pop() call).

This change advances provided setLength()-heavy microbenchmark by ~40%,
while existing Array tests are neutral.

  • runtime/ArrayPrototype.cpp:

(JSC::setLength):
(JSC::arrayProtoFuncPop):
(JSC::arrayProtoFuncPush):
(JSC::arrayProtoFuncShift):
(JSC::arrayProtoFuncUnShift):
(JSC::putLength): Deleted.

Location:
trunk/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r266213 r266215  
     12020-08-26  Alexey Shvayka  <[email protected]>
     2
     3        Merge putLength() into setLength()
     4        https://bugs.webkit.org/show_bug.cgi?id=211279
     5
     6        Reviewed by Darin Adler and Saam Barati.
     7
     8        This patch:
     9
     10        1. Replaces all putLength() call sites with setLength(), saving two JSValue
     11           instantiations in arrayProtoFuncPop() and two in arrayProtoFuncShift().
     12
     13        2. Merges putLength() into setLength(), removing superfluous put() call for
     14           JSArray. Also, performs put() in strict mode to preserve the original
     15           error messages, like ones in ProxyObject::performPut().
     16
     17        3. Inlines performPop(), which avoided an extra index check and Identifier
     18           creation, as it was on the slow path anyway (note JSArray::pop() call).
     19
     20        This change advances provided setLength()-heavy microbenchmark by ~40%,
     21        while existing Array tests are neutral.
     22
     23        * runtime/ArrayPrototype.cpp:
     24        (JSC::setLength):
     25        (JSC::arrayProtoFuncPop):
     26        (JSC::arrayProtoFuncPush):
     27        (JSC::arrayProtoFuncShift):
     28        (JSC::arrayProtoFuncUnShift):
     29        (JSC::putLength): Deleted.
     30
    1312020-08-26  Saam Barati  <[email protected]>
    232
  • trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp

    r263944 r266215  
    161161}
    162162
    163 static ALWAYS_INLINE void putLength(JSGlobalObject* globalObject, VM& vm, JSObject* obj, JSValue value)
    164 {
    165     auto scope = DECLARE_THROW_SCOPE(vm);
    166     PutPropertySlot slot(obj);
    167     bool success = obj->methodTable(vm)->put(obj, globalObject, vm.propertyNames->length, value, slot);
    168     RETURN_IF_EXCEPTION(scope, void());
    169     if (UNLIKELY(!success))
    170         throwTypeError(globalObject, scope, ReadonlyPropertyWriteError);
    171 }
    172 
    173163static ALWAYS_INLINE void setLength(JSGlobalObject* globalObject, VM& vm, JSObject* obj, uint64_t value)
    174164{
    175     auto scope = DECLARE_THROW_SCOPE(vm);
    176165    static constexpr bool throwException = true;
    177     if (isJSArray(obj)) {
     166    if (LIKELY(isJSArray(obj))) {
    178167        ASSERT(static_cast<uint32_t>(value) == value);
    179168        jsCast<JSArray*>(obj)->setLength(globalObject, static_cast<uint32_t>(value), throwException);
    180         RETURN_IF_EXCEPTION(scope, void());
    181     }
    182     scope.release();
    183     putLength(globalObject, vm, obj, jsNumber(value));
     169    } else {
     170        PutPropertySlot slot(obj, throwException);
     171        obj->methodTable(vm)->put(obj, globalObject, vm.propertyNames->length, jsNumber(value), slot);
     172    }
    184173}
    185174
     
    877866    if (length == 0) {
    878867        scope.release();
    879         putLength(globalObject, vm, thisObj, jsNumber(length));
     868        setLength(globalObject, vm, thisObj, length);
    880869        return JSValue::encode(jsUndefined());
    881870    }
    882871
    883     auto performPop = [&] (auto index, JSValue indexValue) {
    884         JSValue result = thisObj->get(globalObject, index);
    885         RETURN_IF_EXCEPTION(scope, encodedJSValue());
    886         bool success = thisObj->deleteProperty(globalObject, index);
    887         RETURN_IF_EXCEPTION(scope, encodedJSValue());
    888         if (UNLIKELY(!success)) {
    889             throwTypeError(globalObject, scope, UnableToDeletePropertyError);
    890             return encodedJSValue();
    891         }
    892         scope.release();
    893         putLength(globalObject, vm, thisObj, indexValue);
    894         return JSValue::encode(result);
    895     };
    896 
    897872    static_assert(MAX_ARRAY_INDEX + 1 > MAX_ARRAY_INDEX);
    898     if (LIKELY(length <= MAX_ARRAY_INDEX + 1))
    899         return performPop(static_cast<uint32_t>(length - 1), jsNumber(static_cast<uint32_t>(length - 1)));
    900     return performPop(Identifier::from(vm, length - 1), jsNumber(length - 1));
     873    uint64_t index = length - 1;
     874    JSValue result = thisObj->get(globalObject, index);
     875    RETURN_IF_EXCEPTION(scope, { });
     876    bool success = thisObj->deleteProperty(globalObject, index);
     877    RETURN_IF_EXCEPTION(scope, { });
     878    if (UNLIKELY(!success)) {
     879        throwTypeError(globalObject, scope, UnableToDeletePropertyError);
     880        return { };
     881    }
     882
     883    scope.release();
     884    setLength(globalObject, vm, thisObj, index);
     885    return JSValue::encode(result);
    901886}
    902887
     
    936921    }
    937922   
    938     JSValue newLength(static_cast<int64_t>(length) + static_cast<int64_t>(callFrame->argumentCount()));
     923    uint64_t newLength = length + argCount;
    939924    scope.release();
    940     putLength(globalObject, vm, thisObj, newLength);
    941     return JSValue::encode(newLength);
     925    setLength(globalObject, vm, thisObj, newLength);
     926    return JSValue::encode(jsNumber(newLength));
    942927}
    943928
     
    10581043    if (length == 0) {
    10591044        scope.release();
    1060         putLength(globalObject, vm, thisObj, jsNumber(length));
     1045        setLength(globalObject, vm, thisObj, length);
    10611046        return JSValue::encode(jsUndefined());
    10621047    }
     
    10671052    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    10681053    scope.release();
    1069     putLength(globalObject, vm, thisObj, jsNumber(length - 1));
     1054    setLength(globalObject, vm, thisObj, length - 1);
    10701055    return JSValue::encode(result);
    10711056}
     
    12641249        RETURN_IF_EXCEPTION(scope, encodedJSValue());
    12651250    }
    1266     JSValue result = jsNumber(length + nrArgs);
     1251    uint64_t newLength = length + nrArgs;
    12671252    scope.release();
    1268     putLength(globalObject, vm, thisObj, result);
    1269     return JSValue::encode(result);
     1253    setLength(globalObject, vm, thisObj, newLength);
     1254    return JSValue::encode(jsNumber(newLength));
    12701255}
    12711256
Note: See TracChangeset for help on using the changeset viewer.