Title: [272364] trunk/Source/_javascript_Core
Revision
272364
Author
ysuz...@apple.com
Date
2021-02-04 02:42:19 -0800 (Thu, 04 Feb 2021)

Log Message

[JSC] Implement Object.entries in C++
https://bugs.webkit.org/show_bug.cgi?id=221380

Reviewed by Alexey Shvayka.

This patch implements Object.entries in C++ because it is more efficient.
It is not using dynamic feature (like, calling a callback). And in C++,
we can avoid JSArray allocations for @Object.@getOwnPropertyNames.

This patch also removes unnecessary JS private functions, @propertyIsEnumerable,
and @getOwnPropertyNames.

* builtins/BuiltinNames.h:
* builtins/ObjectConstructor.js:
(entries): Deleted.
* bytecode/LinkTimeConstant.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* runtime/JSGlobalObjectFunctions.cpp:
* runtime/JSGlobalObjectFunctions.h:
* runtime/ObjectConstructor.cpp:
(JSC::ObjectConstructor::finishCreation):
(JSC::JSC_DEFINE_HOST_FUNCTION):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (272363 => 272364)


--- trunk/Source/_javascript_Core/ChangeLog	2021-02-04 09:11:28 UTC (rev 272363)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-02-04 10:42:19 UTC (rev 272364)
@@ -1,3 +1,29 @@
+2021-02-04  Yusuke Suzuki  <ysuz...@apple.com>
+
+        [JSC] Implement Object.entries in C++
+        https://bugs.webkit.org/show_bug.cgi?id=221380
+
+        Reviewed by Alexey Shvayka.
+
+        This patch implements Object.entries in C++ because it is more efficient.
+        It is not using dynamic feature (like, calling a callback). And in C++,
+        we can avoid JSArray allocations for @Object.@getOwnPropertyNames.
+
+        This patch also removes unnecessary JS private functions, @propertyIsEnumerable,
+        and @getOwnPropertyNames.
+
+        * builtins/BuiltinNames.h:
+        * builtins/ObjectConstructor.js:
+        (entries): Deleted.
+        * bytecode/LinkTimeConstant.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        * runtime/JSGlobalObjectFunctions.cpp:
+        * runtime/JSGlobalObjectFunctions.h:
+        * runtime/ObjectConstructor.cpp:
+        (JSC::ObjectConstructor::finishCreation):
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+
 2021-02-03  Yusuke Suzuki  <ysuz...@apple.com>
 
         [JSC] Insert PhantomLocal just before SetLocal for |this| to ensure liveness

Modified: trunk/Source/_javascript_Core/builtins/BuiltinNames.h (272363 => 272364)


--- trunk/Source/_javascript_Core/builtins/BuiltinNames.h	2021-02-04 09:11:28 UTC (rev 272363)
+++ trunk/Source/_javascript_Core/builtins/BuiltinNames.h	2021-02-04 10:42:19 UTC (rev 272364)
@@ -66,7 +66,6 @@
     macro(create) \
     macro(defineProperty) \
     macro(defaultPromiseThen) \
-    macro(getOwnPropertyNames) \
     macro(Set) \
     macro(throwTypeErrorFunction) \
     macro(typedArrayLength) \
@@ -169,7 +168,6 @@
     macro(makeBoundFunction) \
     macro(hasOwnLengthProperty) \
     macro(importModule) \
-    macro(propertyIsEnumerable) \
     macro(copyDataProperties) \
     macro(meta) \
     macro(webAssemblyCompileStreamingInternal) \
@@ -177,6 +175,7 @@
     macro(instanceFieldInitializer) \
     macro(hasOwnPropertyFunction) \
     macro(createPrivateSymbol) \
+    macro(entries) \
 
 
 namespace Symbols {

Modified: trunk/Source/_javascript_Core/builtins/ObjectConstructor.js (272363 => 272364)


--- trunk/Source/_javascript_Core/builtins/ObjectConstructor.js	2021-02-04 09:11:28 UTC (rev 272363)
+++ trunk/Source/_javascript_Core/builtins/ObjectConstructor.js	2021-02-04 10:42:19 UTC (rev 272364)
@@ -25,22 +25,6 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-function entries(object)
-{
-    "use strict";
-
-    var obj = @toObject(object, "Object.entries requires that input parameter not be null or undefined");
-    var names = @Object.@getOwnPropertyNames(obj);
-    var properties = [];
-    for (var i = 0, length = names.length; i < length; ++i) {
-        var name = names[i];
-        if (@propertyIsEnumerable(obj, name))
-            @arrayPush(properties, [name, obj[name]]);
-    }
-
-    return properties;
-}
-
 function fromEntries(iterable)
 {
     "use strict";

Modified: trunk/Source/_javascript_Core/bytecode/LinkTimeConstant.h (272363 => 272364)


--- trunk/Source/_javascript_Core/bytecode/LinkTimeConstant.h	2021-02-04 09:11:28 UTC (rev 272363)
+++ trunk/Source/_javascript_Core/bytecode/LinkTimeConstant.h	2021-02-04 10:42:19 UTC (rev 272364)
@@ -44,7 +44,6 @@
     v(setBucketNext, nullptr) \
     v(setBucketKey, nullptr) \
     v(setPrototypeDirect, nullptr) \
-    v(propertyIsEnumerable, nullptr) \
     v(copyDataProperties, nullptr) \
     v(enqueueJob, nullptr) \
     v(makeTypeError, nullptr) \

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (272363 => 272364)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2021-02-04 09:11:28 UTC (rev 272363)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2021-02-04 10:42:19 UTC (rev 272364)
@@ -1187,9 +1187,6 @@
     m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::importModule)].initLater([] (const Initializer<JSCell>& init) {
             init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), globalFuncImportModule));
         });
-    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::propertyIsEnumerable)].initLater([] (const Initializer<JSCell>& init) {
-            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), globalFuncPropertyIsEnumerable));
-        });
     m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::copyDataProperties)].initLater([] (const Initializer<JSCell>& init) {
             init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 2, String(), globalFuncCopyDataProperties));
         });

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (272363 => 272364)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2021-02-04 09:11:28 UTC (rev 272363)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2021-02-04 10:42:19 UTC (rev 272364)
@@ -815,22 +815,6 @@
     return JSValue::encode(promise);
 }
 
-JSC_DEFINE_HOST_FUNCTION(globalFuncPropertyIsEnumerable, (JSGlobalObject* globalObject, CallFrame* callFrame))
-{
-    VM& vm = globalObject->vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    RELEASE_ASSERT(callFrame->argumentCount() == 2);
-    JSObject* object = jsCast<JSObject*>(callFrame->uncheckedArgument(0));
-    auto propertyName = callFrame->uncheckedArgument(1).toPropertyKey(globalObject);
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
-
-    scope.release();
-    PropertyDescriptor descriptor;
-    bool enumerable = object->getOwnPropertyDescriptor(globalObject, propertyName, descriptor) && descriptor.enumerable();
-    return JSValue::encode(jsBoolean(enumerable));
-}
-
 static bool canPerformFastPropertyEnumerationForCopyDataProperties(Structure* structure)
 {
     if (structure->typeInfo().overridesGetOwnPropertySlot())

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.h (272363 => 272364)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.h	2021-02-04 09:11:28 UTC (rev 272363)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.h	2021-02-04 10:42:19 UTC (rev 272364)
@@ -56,7 +56,6 @@
 JSC_DECLARE_HOST_FUNCTION(globalFuncBuiltinLog);
 JSC_DECLARE_HOST_FUNCTION(globalFuncBuiltinDescribe);
 JSC_DECLARE_HOST_FUNCTION(globalFuncImportModule);
-JSC_DECLARE_HOST_FUNCTION(globalFuncPropertyIsEnumerable);
 JSC_DECLARE_HOST_FUNCTION(globalFuncCopyDataProperties);
 JSC_DECLARE_HOST_FUNCTION(globalFuncDateTimeFormat);
 

Modified: trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp (272363 => 272364)


--- trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp	2021-02-04 09:11:28 UTC (rev 272363)
+++ trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp	2021-02-04 10:42:19 UTC (rev 272364)
@@ -32,6 +32,7 @@
 namespace JSC {
 
 static JSC_DECLARE_HOST_FUNCTION(objectConstructorAssign);
+static JSC_DECLARE_HOST_FUNCTION(objectConstructorEntries);
 static JSC_DECLARE_HOST_FUNCTION(objectConstructorValues);
 static JSC_DECLARE_HOST_FUNCTION(objectConstructorGetPrototypeOf);
 static JSC_DECLARE_HOST_FUNCTION(objectConstructorSetPrototypeOf);
@@ -76,7 +77,7 @@
   is                        objectConstructorIs                         DontEnum|Function 2 ObjectIsIntrinsic
   assign                    objectConstructorAssign                     DontEnum|Function 2
   values                    objectConstructorValues                     DontEnum|Function 1
-  entries                   JSBuiltin                                   DontEnum|Function 1
+  entries                   objectConstructorEntries                    DontEnum|Function 1
   fromEntries               JSBuiltin                                   DontEnum|Function 1
 @end
 */
@@ -98,7 +99,6 @@
 
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().createPrivateName(), objectConstructorCreate, static_cast<unsigned>(PropertyAttribute::DontEnum), 2);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().definePropertyPrivateName(), objectConstructorDefineProperty, static_cast<unsigned>(PropertyAttribute::DontEnum), 3);
-    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getOwnPropertyNamesPrivateName(), objectConstructorGetOwnPropertyNames, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
 }
 
 // ES 19.1.1.1 Object([value])
@@ -388,6 +388,65 @@
     return JSValue::encode(target);
 }
 
+JSC_DEFINE_HOST_FUNCTION(objectConstructorEntries, (JSGlobalObject* globalObject, CallFrame* callFrame))
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSValue targetValue = callFrame->argument(0);
+    if (targetValue.isUndefinedOrNull())
+        return throwVMTypeError(globalObject, scope, "Object.entries requires that input parameter not be null or undefined"_s);
+    JSObject* target = targetValue.toObject(globalObject);
+    RETURN_IF_EXCEPTION(scope, { });
+
+    JSArray* entries = constructEmptyArray(globalObject, nullptr);
+    RETURN_IF_EXCEPTION(scope, { });
+
+    PropertyNameArray properties(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude);
+    target->methodTable(vm)->getOwnPropertyNames(target, globalObject, properties, DontEnumPropertiesMode::Include);
+    RETURN_IF_EXCEPTION(scope, { });
+
+    unsigned index = 0;
+    auto append = [&] (JSGlobalObject* globalObject, PropertyName propertyName) {
+        PropertySlot slot(target, PropertySlot::InternalMethodType::GetOwnProperty);
+        bool hasProperty = target->methodTable(vm)->getOwnPropertySlot(target, globalObject, propertyName, slot);
+        RETURN_IF_EXCEPTION(scope, void());
+        if (!hasProperty)
+            return;
+        if (slot.attributes() & PropertyAttribute::DontEnum)
+            return;
+
+        JSValue value;
+        if (LIKELY(!slot.isTaintedByOpaqueObject()))
+            value = slot.getValue(globalObject, propertyName);
+        else
+            value = target->get(globalObject, propertyName);
+        RETURN_IF_EXCEPTION(scope, void());
+
+        JSString* key = jsOwnedString(vm, propertyName.uid());
+        JSArray* entry = nullptr;
+        {
+            ObjectInitializationScope initializationScope(vm);
+            if ((entry = JSArray::tryCreateUninitializedRestricted(initializationScope, nullptr, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 2))) {
+                entry->initializeIndex(initializationScope, 0, key);
+                entry->initializeIndex(initializationScope, 1, value);
+            }
+        }
+        if (!entry) {
+            throwOutOfMemoryError(globalObject, scope);
+            return;
+        }
+        entries->putDirectIndex(globalObject, index++, entry);
+    };
+
+    for (const auto& propertyName : properties) {
+        append(globalObject, propertyName);
+        RETURN_IF_EXCEPTION(scope, { });
+    }
+
+    return JSValue::encode(entries);
+}
+
 JSC_DEFINE_HOST_FUNCTION(objectConstructorValues, (JSGlobalObject* globalObject, CallFrame* callFrame))
 {
     VM& vm = globalObject->vm();
@@ -407,7 +466,7 @@
     RETURN_IF_EXCEPTION(scope, { });
 
     unsigned index = 0;
-    auto addValue = [&] (PropertyName propertyName) {
+    auto append = [&] (JSGlobalObject* globalObject, PropertyName propertyName) {
         PropertySlot slot(target, PropertySlot::InternalMethodType::GetOwnProperty);
         bool hasProperty = target->methodTable(vm)->getOwnPropertySlot(target, globalObject, propertyName, slot);
         RETURN_IF_EXCEPTION(scope, void());
@@ -426,12 +485,8 @@
         values->putDirectIndex(globalObject, index++, value);
     };
 
-    for (unsigned i = 0, numProperties = properties.size(); i < numProperties; i++) {
-        const auto& propertyName = properties[i];
-        if (propertyName.isSymbol())
-            continue;
-
-        addValue(propertyName);
+    for (const auto& propertyName : properties) {
+        append(globalObject, propertyName);
         RETURN_IF_EXCEPTION(scope, { });
     }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to