Changeset 273766 in webkit


Ignore:
Timestamp:
Mar 2, 2021 3:33:43 PM (17 months ago)
Author:
ysuzuki@apple.com
Message:

[JSC] Optimize getEnumerableLength
https://bugs.webkit.org/show_bug.cgi?id=222539

Reviewed by Alexey Shvayka.

Now getEnumerableLength is only overridden by JSProxy. And this is called in the critical path of propertyNameEnumerator.
We should not use indirect call for getEnumerableLength. We remove indirect functions for getEnumerableLength. For JSProxy,
any results is OK since anyway JSProxy does not utilize the result of this function since it cannot use fast index enumerator.

We also avoid calling holesMustForwardToPrototype in getEnumerableLength when it is meaningless. For example,
if the object is ALL_BLANK_INDEXING_TYPES, then regardless of the condition of holesMustForwardToPrototype, the result of
getEnumerableLength is zero.

  • runtime/ClassInfo.h:
  • runtime/JSCast.h:
  • runtime/JSCell.cpp:

(JSC::JSCell::getEnumerableLength): Deleted.

  • runtime/JSCell.h:
  • runtime/JSObject.cpp:

(JSC::JSObject::getEnumerableLength):

  • runtime/JSObject.h:
  • runtime/JSPropertyNameEnumerator.h:

(JSC::propertyNameEnumerator):

  • runtime/JSProxy.cpp:

(JSC::JSProxy::getEnumerableLength): Deleted.

  • runtime/JSProxy.h:
Location:
trunk/Source/JavaScriptCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r273751 r273766  
     12021-03-02  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Optimize getEnumerableLength
     4        https://bugs.webkit.org/show_bug.cgi?id=222539
     5
     6        Reviewed by Alexey Shvayka.
     7
     8        Now getEnumerableLength is only overridden by JSProxy. And this is called in the critical path of propertyNameEnumerator.
     9        We should not use indirect call for getEnumerableLength. We remove indirect functions for getEnumerableLength. For JSProxy,
     10        any results is OK since anyway JSProxy does not utilize the result of this function since it cannot use fast index enumerator.
     11
     12        We also avoid calling holesMustForwardToPrototype in getEnumerableLength when it is meaningless. For example,
     13        if the object is ALL_BLANK_INDEXING_TYPES, then regardless of the condition of holesMustForwardToPrototype, the result of
     14        getEnumerableLength is zero.
     15
     16        * runtime/ClassInfo.h:
     17        * runtime/JSCast.h:
     18        * runtime/JSCell.cpp:
     19        (JSC::JSCell::getEnumerableLength): Deleted.
     20        * runtime/JSCell.h:
     21        * runtime/JSObject.cpp:
     22        (JSC::JSObject::getEnumerableLength):
     23        * runtime/JSObject.h:
     24        * runtime/JSPropertyNameEnumerator.h:
     25        (JSC::propertyNameEnumerator):
     26        * runtime/JSProxy.cpp:
     27        (JSC::JSProxy::getEnumerableLength): Deleted.
     28        * runtime/JSProxy.h:
     29
    1302021-03-02  BJ Burg  <bburg@apple.com>
    231
  • trunk/Source/JavaScriptCore/runtime/ClassInfo.h

    r273138 r273766  
    8181    GetOwnPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getOwnPropertyNames);
    8282    GetOwnPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getOwnSpecialPropertyNames);
    83 
    84     using GetEnumerableLengthFunctionPtr = uint32_t (*)(JSGlobalObject*, JSObject*);
    85     GetEnumerableLengthFunctionPtr METHOD_TABLE_ENTRY(getEnumerableLength);
    8683
    8784    using ClassNameFunctionPtr = String (*)(const JSObject*, VM&);
     
    173170        &ClassName::getOwnPropertyNames, \
    174171        &ClassName::getOwnSpecialPropertyNames, \
    175         &ClassName::getEnumerableLength, \
    176172        &ClassName::className, \
    177173        &ClassName::toStringName, \
  • trunk/Source/JavaScriptCore/runtime/JSCast.h

    r263134 r273766  
    8080    macro(JSArrayBufferView, FirstTypedArrayType, LastTypedArrayType) \
    8181    macro(JSPromise, JSType::JSPromiseType, JSType::JSPromiseType) \
     82    macro(JSProxy, JSType::PureForwardingProxyType, JSType::ImpureProxyType) \
    8283    macro(JSSet, JSType::JSSetType, JSType::JSSetType) \
    8384    macro(JSMap, JSType::JSMapType, JSType::JSMapType) \
  • trunk/Source/JavaScriptCore/runtime/JSCell.cpp

    r271269 r273766  
    246246}
    247247
    248 uint32_t JSCell::getEnumerableLength(JSGlobalObject*, JSObject*)
    249 {
    250     RELEASE_ASSERT_NOT_REACHED();
    251     return 0;
    252 }
    253 
    254248bool JSCell::preventExtensions(JSObject*, JSGlobalObject*)
    255249{
  • trunk/Source/JavaScriptCore/runtime/JSCell.h

    r273138 r273766  
    249249    static NO_RETURN_DUE_TO_CRASH void getOwnSpecialPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, DontEnumPropertiesMode);
    250250
    251     static uint32_t getEnumerableLength(JSGlobalObject*, JSObject*);
    252251    static NO_RETURN_DUE_TO_CRASH bool preventExtensions(JSObject*, JSGlobalObject*);
    253252    static NO_RETURN_DUE_TO_CRASH bool isExtensible(JSObject*, JSGlobalObject*);
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r273138 r273766  
    37553755}
    37563756
    3757 uint32_t JSObject::getEnumerableLength(JSGlobalObject* globalObject, JSObject* object)
     3757uint32_t JSObject::getEnumerableLength(JSGlobalObject* globalObject)
    37583758{
    37593759    VM& vm = globalObject->vm();
    3760     Structure* structure = object->structure(vm);
    3761     if (structure->holesMustForwardToPrototype(vm, object))
    3762         return 0;
     3760    JSObject* object = this;
     3761
    37633762    switch (object->indexingType()) {
    37643763    case ALL_BLANK_INDEXING_TYPES:
    37653764    case ALL_UNDECIDED_INDEXING_TYPES:
     3765        // Regardless of holesMustForwardToPrototype condition, it returns zero.
    37663766        return 0;
    37673767       
     
    37693769    case ALL_CONTIGUOUS_INDEXING_TYPES: {
    37703770        Butterfly* butterfly = object->butterfly();
    3771         unsigned usedLength = butterfly->publicLength();
    3772         for (unsigned i = 0; i < usedLength; ++i) {
     3771        unsigned enumerableLength = butterfly->publicLength();
     3772        if (!enumerableLength)
     3773            return 0;
     3774        if (object->structure(vm)->holesMustForwardToPrototype(vm, object))
     3775            return 0;
     3776        for (unsigned i = 0; i < enumerableLength; ++i) {
    37733777            if (!butterfly->contiguous().at(object, i))
    37743778                return 0;
    37753779        }
    3776         return usedLength;
     3780        return enumerableLength;
    37773781    }
    37783782       
    37793783    case ALL_DOUBLE_INDEXING_TYPES: {
    37803784        Butterfly* butterfly = object->butterfly();
    3781         unsigned usedLength = butterfly->publicLength();
    3782         for (unsigned i = 0; i < usedLength; ++i) {
     3785        unsigned enumerableLength = butterfly->publicLength();
     3786        if (!enumerableLength)
     3787            return 0;
     3788        if (object->structure(vm)->holesMustForwardToPrototype(vm, object))
     3789            return 0;
     3790        for (unsigned i = 0; i < enumerableLength; ++i) {
    37833791            double value = butterfly->contiguousDouble().at(object, i);
    37843792            if (value != value)
    37853793                return 0;
    37863794        }
    3787         return usedLength;
     3795        return enumerableLength;
    37883796    }
    37893797       
     
    37933801            return 0;
    37943802       
    3795         unsigned usedVectorLength = std::min(storage->length(), storage->vectorLength());
    3796         for (unsigned i = 0; i < usedVectorLength; ++i) {
     3803        unsigned enumerableLength = std::min(storage->length(), storage->vectorLength());
     3804        if (!enumerableLength)
     3805            return 0;
     3806        if (object->structure(vm)->holesMustForwardToPrototype(vm, object))
     3807            return 0;
     3808        for (unsigned i = 0; i < enumerableLength; ++i) {
    37973809            if (!storage->m_vector[i])
    37983810                return 0;
    37993811        }
    3800         return usedVectorLength;
     3812        return enumerableLength;
    38013813    }
    38023814       
  • trunk/Source/JavaScriptCore/runtime/JSObject.h

    r273138 r273766  
    686686    void getNonReifiedStaticPropertyNames(VM&, PropertyNameArray&, DontEnumPropertiesMode);
    687687
    688     JS_EXPORT_PRIVATE static uint32_t getEnumerableLength(JSGlobalObject*, JSObject*);
     688    JS_EXPORT_PRIVATE uint32_t getEnumerableLength(JSGlobalObject*);
    689689
    690690    JS_EXPORT_PRIVATE JSValue toPrimitive(JSGlobalObject*, PreferredPrimitiveType = NoPreference) const;
  • trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h

    r273138 r273766  
    109109    auto scope = DECLARE_THROW_SCOPE(vm);
    110110
    111     uint32_t indexedLength = base->methodTable(vm)->getEnumerableLength(globalObject, base);
     111    uint32_t indexedLength = base->getEnumerableLength(globalObject);
    112112
    113113    JSPropertyNameEnumerator* enumerator = nullptr;
  • trunk/Source/JavaScriptCore/runtime/JSProxy.cpp

    r273138 r273766  
    119119}
    120120
    121 uint32_t JSProxy::getEnumerableLength(JSGlobalObject* globalObject, JSObject* object)
    122 {
    123     JSProxy* thisObject = jsCast<JSProxy*>(object);
    124     return thisObject->target()->methodTable(globalObject->vm())->getEnumerableLength(globalObject, thisObject->target());
    125 }
    126 
    127121void JSProxy::getOwnPropertyNames(JSObject* object, JSGlobalObject* globalObject, PropertyNameArray& propertyNames, DontEnumPropertiesMode mode)
    128122{
  • trunk/Source/JavaScriptCore/runtime/JSProxy.h

    r273138 r273766  
    9797    JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, JSGlobalObject*, unsigned);
    9898    JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, DontEnumPropertiesMode);
    99     JS_EXPORT_PRIVATE static uint32_t getEnumerableLength(JSGlobalObject*, JSObject*);
    10099    JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, JSGlobalObject*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
    101100    JS_EXPORT_PRIVATE static bool setPrototype(JSObject*, JSGlobalObject*, JSValue, bool shouldThrowIfCantSet);
Note: See TracChangeset for help on using the changeset viewer.