Title: [273766] trunk/Source/_javascript_Core
Revision
273766
Author
[email protected]
Date
2021-03-02 15:33:43 -0800 (Tue, 02 Mar 2021)

Log 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:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (273765 => 273766)


--- trunk/Source/_javascript_Core/ChangeLog	2021-03-02 23:27:06 UTC (rev 273765)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-03-02 23:33:43 UTC (rev 273766)
@@ -1,3 +1,32 @@
+2021-03-02  Yusuke Suzuki  <[email protected]>
+
+        [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:
+
 2021-03-02  BJ Burg  <[email protected]>
 
         [Cocoa] REGRESSION(r272752): fix some internal builds that use WTFString::WTFString(NSString *)

Modified: trunk/Source/_javascript_Core/runtime/ClassInfo.h (273765 => 273766)


--- trunk/Source/_javascript_Core/runtime/ClassInfo.h	2021-03-02 23:27:06 UTC (rev 273765)
+++ trunk/Source/_javascript_Core/runtime/ClassInfo.h	2021-03-02 23:33:43 UTC (rev 273766)
@@ -81,9 +81,6 @@
     GetOwnPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getOwnPropertyNames);
     GetOwnPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getOwnSpecialPropertyNames);
 
-    using GetEnumerableLengthFunctionPtr = uint32_t (*)(JSGlobalObject*, JSObject*);
-    GetEnumerableLengthFunctionPtr METHOD_TABLE_ENTRY(getEnumerableLength);
-
     using ClassNameFunctionPtr = String (*)(const JSObject*, VM&);
     ClassNameFunctionPtr METHOD_TABLE_ENTRY(className);
 
@@ -172,7 +169,6 @@
         &ClassName::defaultValue, \
         &ClassName::getOwnPropertyNames, \
         &ClassName::getOwnSpecialPropertyNames, \
-        &ClassName::getEnumerableLength, \
         &ClassName::className, \
         &ClassName::toStringName, \
         &ClassName::customHasInstance, \

Modified: trunk/Source/_javascript_Core/runtime/JSCast.h (273765 => 273766)


--- trunk/Source/_javascript_Core/runtime/JSCast.h	2021-03-02 23:27:06 UTC (rev 273765)
+++ trunk/Source/_javascript_Core/runtime/JSCast.h	2021-03-02 23:33:43 UTC (rev 273766)
@@ -79,6 +79,7 @@
     macro(JSArrayBuffer, JSType::ArrayBufferType, JSType::ArrayBufferType) \
     macro(JSArrayBufferView, FirstTypedArrayType, LastTypedArrayType) \
     macro(JSPromise, JSType::JSPromiseType, JSType::JSPromiseType) \
+    macro(JSProxy, JSType::PureForwardingProxyType, JSType::ImpureProxyType) \
     macro(JSSet, JSType::JSSetType, JSType::JSSetType) \
     macro(JSMap, JSType::JSMapType, JSType::JSMapType) \
     macro(JSWeakSet, JSType::JSWeakSetType, JSType::JSWeakSetType) \

Modified: trunk/Source/_javascript_Core/runtime/JSCell.cpp (273765 => 273766)


--- trunk/Source/_javascript_Core/runtime/JSCell.cpp	2021-03-02 23:27:06 UTC (rev 273765)
+++ trunk/Source/_javascript_Core/runtime/JSCell.cpp	2021-03-02 23:33:43 UTC (rev 273766)
@@ -245,12 +245,6 @@
     return false;
 }
 
-uint32_t JSCell::getEnumerableLength(JSGlobalObject*, JSObject*)
-{
-    RELEASE_ASSERT_NOT_REACHED();
-    return 0;
-}
-
 bool JSCell::preventExtensions(JSObject*, JSGlobalObject*)
 {
     RELEASE_ASSERT_NOT_REACHED();

Modified: trunk/Source/_javascript_Core/runtime/JSCell.h (273765 => 273766)


--- trunk/Source/_javascript_Core/runtime/JSCell.h	2021-03-02 23:27:06 UTC (rev 273765)
+++ trunk/Source/_javascript_Core/runtime/JSCell.h	2021-03-02 23:33:43 UTC (rev 273766)
@@ -248,7 +248,6 @@
     static NO_RETURN_DUE_TO_CRASH void getOwnPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, DontEnumPropertiesMode);
     static NO_RETURN_DUE_TO_CRASH void getOwnSpecialPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, DontEnumPropertiesMode);
 
-    static uint32_t getEnumerableLength(JSGlobalObject*, JSObject*);
     static NO_RETURN_DUE_TO_CRASH bool preventExtensions(JSObject*, JSGlobalObject*);
     static NO_RETURN_DUE_TO_CRASH bool isExtensible(JSObject*, JSGlobalObject*);
     static NO_RETURN_DUE_TO_CRASH bool setPrototype(JSObject*, JSGlobalObject*, JSValue, bool);

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (273765 => 273766)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2021-03-02 23:27:06 UTC (rev 273765)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2021-03-02 23:33:43 UTC (rev 273766)
@@ -3754,37 +3754,45 @@
     setButterfly(vm, newButterfly);
 }
 
-uint32_t JSObject::getEnumerableLength(JSGlobalObject* globalObject, JSObject* object)
+uint32_t JSObject::getEnumerableLength(JSGlobalObject* globalObject)
 {
     VM& vm = globalObject->vm();
-    Structure* structure = object->structure(vm);
-    if (structure->holesMustForwardToPrototype(vm, object))
-        return 0;
+    JSObject* object = this;
+
     switch (object->indexingType()) {
     case ALL_BLANK_INDEXING_TYPES:
     case ALL_UNDECIDED_INDEXING_TYPES:
+        // Regardless of holesMustForwardToPrototype condition, it returns zero.
         return 0;
         
     case ALL_INT32_INDEXING_TYPES:
     case ALL_CONTIGUOUS_INDEXING_TYPES: {
         Butterfly* butterfly = object->butterfly();
-        unsigned usedLength = butterfly->publicLength();
-        for (unsigned i = 0; i < usedLength; ++i) {
+        unsigned enumerableLength = butterfly->publicLength();
+        if (!enumerableLength)
+            return 0;
+        if (object->structure(vm)->holesMustForwardToPrototype(vm, object))
+            return 0;
+        for (unsigned i = 0; i < enumerableLength; ++i) {
             if (!butterfly->contiguous().at(object, i))
                 return 0;
         }
-        return usedLength;
+        return enumerableLength;
     }
         
     case ALL_DOUBLE_INDEXING_TYPES: {
         Butterfly* butterfly = object->butterfly();
-        unsigned usedLength = butterfly->publicLength();
-        for (unsigned i = 0; i < usedLength; ++i) {
+        unsigned enumerableLength = butterfly->publicLength();
+        if (!enumerableLength)
+            return 0;
+        if (object->structure(vm)->holesMustForwardToPrototype(vm, object))
+            return 0;
+        for (unsigned i = 0; i < enumerableLength; ++i) {
             double value = butterfly->contiguousDouble().at(object, i);
             if (value != value)
                 return 0;
         }
-        return usedLength;
+        return enumerableLength;
     }
         
     case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
@@ -3792,12 +3800,16 @@
         if (storage->m_sparseMap.get())
             return 0;
         
-        unsigned usedVectorLength = std::min(storage->length(), storage->vectorLength());
-        for (unsigned i = 0; i < usedVectorLength; ++i) {
+        unsigned enumerableLength = std::min(storage->length(), storage->vectorLength());
+        if (!enumerableLength)
+            return 0;
+        if (object->structure(vm)->holesMustForwardToPrototype(vm, object))
+            return 0;
+        for (unsigned i = 0; i < enumerableLength; ++i) {
             if (!storage->m_vector[i])
                 return 0;
         }
-        return usedVectorLength;
+        return enumerableLength;
     }
         
     default:

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (273765 => 273766)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2021-03-02 23:27:06 UTC (rev 273765)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2021-03-02 23:33:43 UTC (rev 273766)
@@ -685,7 +685,7 @@
     JS_EXPORT_PRIVATE void getOwnNonIndexPropertyNames(JSGlobalObject*, PropertyNameArray&, DontEnumPropertiesMode);
     void getNonReifiedStaticPropertyNames(VM&, PropertyNameArray&, DontEnumPropertiesMode);
 
-    JS_EXPORT_PRIVATE static uint32_t getEnumerableLength(JSGlobalObject*, JSObject*);
+    JS_EXPORT_PRIVATE uint32_t getEnumerableLength(JSGlobalObject*);
 
     JS_EXPORT_PRIVATE JSValue toPrimitive(JSGlobalObject*, PreferredPrimitiveType = NoPreference) const;
     JS_EXPORT_PRIVATE double toNumber(JSGlobalObject*) const;

Modified: trunk/Source/_javascript_Core/runtime/JSPropertyNameEnumerator.h (273765 => 273766)


--- trunk/Source/_javascript_Core/runtime/JSPropertyNameEnumerator.h	2021-03-02 23:27:06 UTC (rev 273765)
+++ trunk/Source/_javascript_Core/runtime/JSPropertyNameEnumerator.h	2021-03-02 23:33:43 UTC (rev 273766)
@@ -108,7 +108,7 @@
     VM& vm = getVM(globalObject);
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    uint32_t indexedLength = base->methodTable(vm)->getEnumerableLength(globalObject, base);
+    uint32_t indexedLength = base->getEnumerableLength(globalObject);
 
     JSPropertyNameEnumerator* enumerator = nullptr;
 

Modified: trunk/Source/_javascript_Core/runtime/JSProxy.cpp (273765 => 273766)


--- trunk/Source/_javascript_Core/runtime/JSProxy.cpp	2021-03-02 23:27:06 UTC (rev 273765)
+++ trunk/Source/_javascript_Core/runtime/JSProxy.cpp	2021-03-02 23:33:43 UTC (rev 273766)
@@ -118,12 +118,6 @@
     return thisObject->target()->methodTable(globalObject->vm())->deletePropertyByIndex(thisObject->target(), globalObject, propertyName);
 }
 
-uint32_t JSProxy::getEnumerableLength(JSGlobalObject* globalObject, JSObject* object)
-{
-    JSProxy* thisObject = jsCast<JSProxy*>(object);
-    return thisObject->target()->methodTable(globalObject->vm())->getEnumerableLength(globalObject, thisObject->target());
-}
-
 void JSProxy::getOwnPropertyNames(JSObject* object, JSGlobalObject* globalObject, PropertyNameArray& propertyNames, DontEnumPropertiesMode mode)
 {
     JSProxy* thisObject = jsCast<JSProxy*>(object);

Modified: trunk/Source/_javascript_Core/runtime/JSProxy.h (273765 => 273766)


--- trunk/Source/_javascript_Core/runtime/JSProxy.h	2021-03-02 23:27:06 UTC (rev 273765)
+++ trunk/Source/_javascript_Core/runtime/JSProxy.h	2021-03-02 23:33:43 UTC (rev 273766)
@@ -96,7 +96,6 @@
     JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, JSGlobalObject*, PropertyName, DeletePropertySlot&);
     JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, JSGlobalObject*, unsigned);
     JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, DontEnumPropertiesMode);
-    JS_EXPORT_PRIVATE static uint32_t getEnumerableLength(JSGlobalObject*, JSObject*);
     JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, JSGlobalObject*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
     JS_EXPORT_PRIVATE static bool setPrototype(JSObject*, JSGlobalObject*, JSValue, bool shouldThrowIfCantSet);
     JS_EXPORT_PRIVATE static JSValue getPrototype(JSObject*, JSGlobalObject*);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to