WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
193618
Implement @copyDataProperties in C++ to optimize object rest / spread
https://bugs.webkit.org/show_bug.cgi?id=193618
Summary
Implement @copyDataProperties in C++ to optimize object rest / spread
Yusuke Suzuki
Reported
2019-01-20 03:19:26 PST
Let's move copyDataPropertiesNoExclusions, copyDataProperties to C++, since it is not beneficial to implement it in JS. Drop defineEnumerableWritableConfigurableDataProperty. Then, remove @Reflect reference. Then, make Reflect lazy-initialized in JSGlobalObject.
Attachments
Patch
(29.58 KB, patch)
2021-01-07 15:43 PST
,
Alexey Shvayka
no flags
Details
Formatted Diff
Diff
Patch
(30.29 KB, patch)
2021-01-07 17:10 PST
,
Alexey Shvayka
no flags
Details
Formatted Diff
Diff
Patch
(30.16 KB, patch)
2021-01-07 17:17 PST
,
Alexey Shvayka
ysuzuki
: review+
ews-feeder
: commit-queue-
Details
Formatted Diff
Diff
Show Obsolete
(2)
View All
Add attachment
proposed patch, testcase, etc.
Alexey Shvayka
Comment 1
2021-01-07 15:43:12 PST
Created
attachment 417220
[details]
Patch
Alexey Shvayka
Comment 2
2021-01-07 15:43:54 PST
(In reply to Alexey Shvayka from
comment #1
)
> Created
attachment 417220
[details]
> Patch
r271191
patch object-spread 178.7996+-2.7727 ^ 34.7401+-0.4879 ^ definitely 5.1468x faster object-rest-destructuring 124.6139+-2.3242 ^ 39.2901+-0.4814 ^ definitely 3.1716x faster <geometric> 149.1572+-1.7371 ^ 36.9301+-0.3394 ^ definitely 4.0389x faster
Saam Barati
Comment 3
2021-01-07 15:56:33 PST
Comment on
attachment 417220
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=417220&action=review
> Source/JavaScriptCore/ChangeLog:24 > + c) unlike Object.assign, properties are copied directly in Structure::forEachProperty(), > + because it's guaranteed that `target` and `source` are different objects. I suspect > + that crashes before
r234022
could be caused by code like `Object.assign(X, X)`.
what do the objects being different have to do with their structures being different? I don't follow the reasoning here. They can share the same structure, right? Also, if this is an invariant we're relying on, let's add an assert for it.
> Source/JavaScriptCore/ChangeLog:25 > + (+170%)
?
> Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:917 > + PropertySlot slot(source, PropertySlot::InternalMethodType::GetOwnProperty);
given we do get below (in tainted case), this shouldn't be HasOwnProperty?
> Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:929 > + value = source->get(globalObject, propertyName);
the spec calls for get twice?
Yusuke Suzuki
Comment 4
2021-01-07 15:58:05 PST
Comment on
attachment 417220
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=417220&action=review
> Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:907 > + source->structure(vm)->forEachProperty(vm, [&] (const PropertyMapEntry& entry) -> bool { > + PropertyName propertyName(entry.key); > + if (propertyName.isPrivateName()) > + return true; > + if (isPropertyNameExcluded(propertyName)) > + return true; > + if (entry.attributes & PropertyAttribute::DontEnum) > + return true; > + > + target->putDirect(vm, propertyName, source->getDirect(entry.offset)); > + return true; > + });
For now, let's first store values into buffer and iterate them later as is done in the Object.assign. See FIXME in Object.assign and
https://bugs.webkit.org/show_bug.cgi?id=187837
Alexey Shvayka
Comment 5
2021-01-07 17:09:47 PST
(In reply to Saam Barati from
comment #3
)
> what do the objects being different have to do with their structures being > different? I don't follow the reasoning here. They can share the same > structure, right?
They can, right. Aligned with Object.assign to copy via buffer (for now).
> > Source/JavaScriptCore/ChangeLog:25 > > + (+170%) > > ?
That was microbenchmark progression for each sub-change (I was curious). Removed it as outdated (and useless).
> > Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:917 > > + PropertySlot slot(source, PropertySlot::InternalMethodType::GetOwnProperty); > > given we do get below (in tainted case), this shouldn't be HasOwnProperty?
We don't have HasOwnProperty, only HasProperty for `in`.
> > Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:929 > > + value = source->get(globalObject, propertyName); > > the spec calls for get twice?
Yes, it does (step 6.c.ii.1 of
https://tc39.es/ecma262/#sec-copydataproperties
), and it follows this pattern in a few other ops/built-ins, even WebIDL.
Alexey Shvayka
Comment 6
2021-01-07 17:10:01 PST
Created
attachment 417227
[details]
Patch Put properties via buffer and tweak ASSERTs.
Alexey Shvayka
Comment 7
2021-01-07 17:12:57 PST
(In reply to Alexey Shvayka from
comment #6
)
> Created
attachment 417227
[details]
> Patch > > Put properties via buffer and tweak ASSERTs.
r271191
patch object-spread 181.2128+-1.8450 ^ 54.3278+-0.8577 ^ definitely 3.3355x faster object-rest-destructuring 129.6295+-1.8733 ^ 44.5497+-0.7565 ^ definitely 2.9098x faster <geometric> 153.1926+-1.0826 ^ 49.1639+-0.5471 ^ definitely 3.1160x faster === ~22% slower.
Alexey Shvayka
Comment 8
2021-01-07 17:17:05 PST
Created
attachment 417229
[details]
Patch We don't need to clear vectors.
Yusuke Suzuki
Comment 9
2021-01-07 19:15:45 PST
Comment on
attachment 417229
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=417229&action=review
Looking, early comments. I'll look more.
> Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:868 > + JSObject* target = asObject(callFrame->uncheckedArgument(0)); > + ASSERT(jsDynamicCast<JSFinalObject*>(vm, target));
Let's do JSFinalObject* target = jsCast<JSFinalObject*>(allFrame->uncheckedArgument(0)); jsCast also has assert.
> Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:873 > + return { };
Let's return `JSValue::encode(jsUndefined())` for non-exception path for robustness.
> Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:954 > + return { };
Let's return `JSValue::encode(jsUndefined())` for non-exception path for robustness.
Yusuke Suzuki
Comment 10
2021-01-08 14:20:55 PST
Comment on
attachment 417229
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=417229&action=review
> Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:889 > + auto isPropertyNameExcluded = [&] (PropertyName propertyName) { > + ASSERT(!propertyName.isPrivateName()); > + if (!excludedSet) > + return false; > + > + JSValue propertyNameValue = identifierToJSValue(vm, Identifier::fromUid(vm, propertyName.uid())); > + return excludedSet->has(globalObject, propertyNameValue); > + };
Let's take `JSGlobalObject*` as a parameter in this function to make it explicit that this can throw an error.
> Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:912 > + if (isPropertyNameExcluded(propertyName)) > + return true;
We need to do an error check since this can throw an error. And if an error is thrown, we should stop iteration.
> Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:933 > + if (isPropertyNameExcluded(propertyName)) > + continue;
Ditto.
Yusuke Suzuki
Comment 11
2021-01-08 14:22:11 PST
Comment on
attachment 417229
[details]
Patch r=me with some comments.
Alexey Shvayka
Comment 12
2021-01-08 20:31:17 PST
Committed
r271343
: <
https://trac.webkit.org/changeset/271343
>
Radar WebKit Bug Importer
Comment 13
2021-01-08 20:32:21 PST
<
rdar://problem/72954769
>
Alexey Shvayka
Comment 14
2021-01-08 20:33:07 PST
(In reply to Alexey Shvayka from
comment #12
)
> Committed
r271343
: <
https://trac.webkit.org/changeset/271343
>
Landed accounting the comments. test262 coverage:
https://github.com/tc39/test262/pull/2930
.
Radar WebKit Bug Importer
Comment 15
2021-01-08 20:33:19 PST
<
rdar://problem/72954785
>
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug