Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[JSC] Optimize ProxyObject's "ownKeys" trap
https://bugs.webkit.org/show_bug.cgi?id=257346 <rdar://problem/109850846> Reviewed by Yusuke Suzuki. It is a common JS pattern to mass-assign properties and clone / merge objects via Object.assign(), and since in Vue.js v3 front-end developers mostly operate on reactive objects (that are wrapped in a ProxyObject), optimizing its "ownKeys" trap and related operations is crucial. This change: 1. Enables [[ProxyHandler]] trap caching for "ownKeys" and "getOwnPropertyDescriptor" traps. 2. Introduces forwardsGetOwnPropertyNamesToTarget() fast path that expands existing property names caching (based on StructureRareData) to handle ProxyObjects which are missing "ownKeys" and "getOwnPropertyDescriptor" traps. This was made possible by [[ProxyHandler]] trap caching added in https://webkit.org/b/256554. 3. Leveraging Structure flags introduced in https://webkit.org/b/255661, skips "ownKeys" trap result validation in the common case of [[ProxyTarget]] being an ordinary extensible object without non-configurable properties. This results in nice speed-up given the spec requires [1] to enumerate all [[ProxyTarget]] properties and ensure that all non-configurable ones are listed by the userland trap code. [1]: https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys (step 16) ToT patch proxy-ownkeys-via-reflect-ownkeys 81.7443+-0.7848 ^ 46.7884+-0.4395 ^ definitely 1.7471x faster proxy-ownkeys-via-reflect-ownkeys-miss-handler 31.4378+-0.4010 ^ 2.2589+-0.0293 ^ definitely 13.9172x faster proxy-ownkeys-via-object-keys 215.2480+-1.1130 ^ 95.5261+-0.7659 ^ definitely 2.2533x faster proxy-ownkeys-via-object-keys-miss-handler 168.9327+-0.7422 ^ 2.2765+-0.0276 ^ definitely 74.2064x faster proxy-ownkeys-via-object-assign 233.9777+-2.1404 ^ 112.9695+-0.8461 ^ definitely 2.0712x faster proxy-ownkeys-via-object-assign-miss-handler 187.8766+-1.0055 ^ 93.1520+-0.1716 ^ definitely 2.0169x faster <geometric> 125.4813+-0.2685 ^ 24.8795+-0.1193 ^ definitely 5.0436x faster * JSTests/microbenchmarks/proxy-ownkeys-via-object-assign-miss-handler.js: Added. * JSTests/microbenchmarks/proxy-ownkeys-via-object-assign.js: Added. * JSTests/microbenchmarks/proxy-ownkeys-via-object-keys-miss-handler.js: Added. * JSTests/microbenchmarks/proxy-ownkeys-via-object-keys.js: Added. * JSTests/microbenchmarks/proxy-ownkeys-via-reflect-ownkeys-miss-handler.js: Added. * JSTests/microbenchmarks/proxy-ownkeys-via-reflect-ownkeys.js: Added. * Source/JavaScriptCore/runtime/CommonIdentifiers.h: * Source/JavaScriptCore/runtime/ObjectConstructor.cpp: (JSC::ownPropertyKeys): * Source/JavaScriptCore/runtime/ProxyObject.cpp: (JSC::ProxyObject::getHandlerTrap): (JSC::ProxyObject::performInternalMethodGetOwnProperty): (JSC::ProxyObject::forwardsGetOwnPropertyNamesToTarget): (JSC::ProxyObject::performGetOwnPropertyNames): * Source/JavaScriptCore/runtime/ProxyObject.h: (JSC::ProxyObject::isHandlerTrapsCacheValid): Canonical link: https://commits.webkit.org/265218@main
- Loading branch information
Alexey Shvayka
committed
Jun 15, 2023
1 parent
3dc8355
commit ef0e6f6
Showing
10 changed files
with
131 additions
and
8 deletions.
There are no files selected for viewing
12 changes: 12 additions & 0 deletions
12
JSTests/microbenchmarks/proxy-ownkeys-via-object-assign-miss-handler.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
(function() { | ||
var target = {k0: 0, k1: 1, k2: 2, k3: 3, k4: 4, k5: 5, k6: 6, k7: 7, k8: 8, k9: 9}; | ||
var targetKeys = Object.keys(target); | ||
var proxy = new Proxy(target, {}); | ||
|
||
var lastObj = {}; | ||
for (var i = 0; i < 2e5; ++i) | ||
lastObj = Object.assign({}, proxy); | ||
|
||
if (Object.keys(lastObj).join() !== targetKeys.join()) | ||
throw new Error("Bad assertion!"); | ||
})(); |
16 changes: 16 additions & 0 deletions
16
JSTests/microbenchmarks/proxy-ownkeys-via-object-assign.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
(function() { | ||
var target = {k0: 0, k1: 1, k2: 2, k3: 3, k4: 4, k5: 5, k6: 6, k7: 7, k8: 8, k9: 9}; | ||
var targetKeys = Object.keys(target); | ||
var proxy = new Proxy(target, { | ||
ownKeys() { | ||
return targetKeys; | ||
}, | ||
}); | ||
|
||
var lastObj = {}; | ||
for (var i = 0; i < 2e5; ++i) | ||
lastObj = Object.assign({}, proxy); | ||
|
||
if (Object.keys(lastObj).join() !== targetKeys.join()) | ||
throw new Error("Bad assertion!"); | ||
})(); |
12 changes: 12 additions & 0 deletions
12
JSTests/microbenchmarks/proxy-ownkeys-via-object-keys-miss-handler.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
(function() { | ||
var target = {k0: 0, k1: 1, k2: 2, k3: 3, k4: 4, k5: 5, k6: 6, k7: 7, k8: 8, k9: 9}; | ||
var targetKeys = Object.keys(target); | ||
var proxy = new Proxy(target, {}); | ||
|
||
var proxyKeys; | ||
for (var i = 0; i < 2e5; ++i) | ||
proxyKeys = Object.keys(proxy); | ||
|
||
if (proxyKeys.join() !== targetKeys.join()) | ||
throw new Error("Bad assertion!"); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
(function() { | ||
var target = {k0: 0, k1: 1, k2: 2, k3: 3, k4: 4, k5: 5, k6: 6, k7: 7, k8: 8, k9: 9}; | ||
var targetKeys = Object.keys(target); | ||
var proxy = new Proxy(target, { | ||
ownKeys() { | ||
return targetKeys; | ||
}, | ||
}); | ||
|
||
var proxyKeys; | ||
for (var i = 0; i < 2e5; ++i) | ||
proxyKeys = Object.keys(proxy); | ||
|
||
if (proxyKeys.join() !== targetKeys.join()) | ||
throw new Error("Bad assertion!"); | ||
})(); |
12 changes: 12 additions & 0 deletions
12
JSTests/microbenchmarks/proxy-ownkeys-via-reflect-ownkeys-miss-handler.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
(function() { | ||
var target = {k0: 0, k1: 1, k2: 2, k3: 3, k4: 4, k5: 5, k6: 6, k7: 7, k8: 8, k9: 9}; | ||
var targetKeys = Reflect.ownKeys(target); | ||
var proxy = new Proxy(target, {}); | ||
|
||
var proxyKeys; | ||
for (var i = 0; i < 2e5; ++i) | ||
proxyKeys = Reflect.ownKeys(proxy); | ||
|
||
if (proxyKeys.join() !== targetKeys.join()) | ||
throw new Error("Bad assertion!"); | ||
})(); |
16 changes: 16 additions & 0 deletions
16
JSTests/microbenchmarks/proxy-ownkeys-via-reflect-ownkeys.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
(function() { | ||
var target = {k0: 0, k1: 1, k2: 2, k3: 3, k4: 4, k5: 5, k6: 6, k7: 7, k8: 8, k9: 9}; | ||
var targetKeys = Reflect.ownKeys(target); | ||
var proxy = new Proxy(target, { | ||
ownKeys() { | ||
return targetKeys; | ||
}, | ||
}); | ||
|
||
var proxyKeys; | ||
for (var i = 0; i < 2e5; ++i) | ||
proxyKeys = Reflect.ownKeys(proxy); | ||
|
||
if (proxyKeys.join() !== targetKeys.join()) | ||
throw new Error("Bad assertion!"); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters