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*);