Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 96fed6d5b49676711c6165a4e20d76b0667dcf3f
https://github.com/WebKit/WebKit/commit/96fed6d5b49676711c6165a4e20d76b0667dcf3f
Author: Sosuke Suzuki <[email protected]>
Date: 2026-09-29 (Tue, 29 Sep 2026)
Changed paths:
A JSTests/microbenchmarks/getter-on-uncacheable-dictionary.js
A JSTests/stress/get-by-id-getter-on-uncacheable-dictionary.js
M Source/JavaScriptCore/runtime/JSObject.cpp
M Source/JavaScriptCore/runtime/JSObject.h
M Source/JavaScriptCore/runtime/PropertySlot.h
Log Message:
-----------
[JSC] Flatten an uncacheable dictionary when ICs see a getter on it
https://bugs.webkit.org/show_bug.cgi?id=325245
Reviewed by Yusuke Suzuki.
TypeScript compiles `export { X } from "./x"` to CommonJS by assigning every
name as a
data property and then redefining each one as a getter with
Object.defineProperty. With
64 or more names, the exports object becomes an uncacheable dictionary. rxjs,
mongodb and
graphql ship such files. Reading a getter from such an object was never cached,
so every
read took the generic slow path in all tiers.
When a read misses the IC, the slow path looks up the property, fills a
PropertySlot and
passes it to tryCacheGetBy. tryCacheGetBy first gives up if the slot is not
cacheable, and
only after that looks at the Structure: if it is an uncacheable dictionary, it
flattens
the object once and caches the property on the next read (151751@main). For a
data
property the slot is always cacheable, so the object gets flattened. For a
getter,
JSObject::fillGetterPropertySlot made the slot uncacheable when the structure
is an
uncacheable dictionary, so tryCacheGetBy gave up at the first check and the
object was
never flattened.
This patch removes that check so that getters take the same path as data
properties.
This is safe because no reader of PropertySlot relies on the check.
tryCacheGetBy and
tryCacheInBy flatten or give up on an uncacheable dictionary by looking at the
Structure,
the megamorphic paths and HasOwnPropertyCache check
Structure::propertyAccessesAreCacheable,
and LLInt and StructureRareData only cache values. Data properties have always
been
reported as cacheable on an uncacheable dictionary and rely on the same checks.
The cost is that ICs now flatten an uncacheable dictionary when they see a
getter on it,
as they already do for data properties. When running JetStream 3 locally, only
jsdom-d3-startup looked up a getter on an uncacheable dictionary, and none of
those
lookups came from ICs, so this patch did not change what ICs do in any of its
tests.
The custom-accessor-thin-air* benchmarks below never look up a getter on an
uncacheable
dictionary. Their difference went away when fillGetterPropertySlot was padded
back to its
original size, so it comes from code placement.
Baseline Patched
custom-accessor-thin-air-setter 3.9738+-0.0476 !
4.1397+-0.0798 ! definitely 1.0417x slower
custom-accessor-thin-air 11.9587+-0.1283 !
12.4227+-0.2783 ! definitely 1.0388x slower
getter-on-uncacheable-dictionary 32.5765+-1.5247 ^
1.3379+-0.1939 ^ definitely 24.3484x faster
Tests: JSTests/microbenchmarks/getter-on-uncacheable-dictionary.js
JSTests/stress/get-by-id-getter-on-uncacheable-dictionary.js
* JSTests/microbenchmarks/getter-on-uncacheable-dictionary.js: Added.
(i.inner.string_appeared_here.i):
(get return):
(test):
* JSTests/stress/get-by-id-getter-on-uncacheable-dictionary.js: Added.
(shouldBe):
(own):
(inherited):
(ownByVal):
(makeExports.get return):
(get for):
(makeExports):
* Source/JavaScriptCore/runtime/JSObject.cpp:
(JSC::JSObject::fillGetterPropertySlot):
Canonical link: https://commits.webkit.org/322154@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications