Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 3b6fd3f42e2bcfd7f2107b036ab41ea55f2a4d94
https://github.com/WebKit/WebKit/commit/3b6fd3f42e2bcfd7f2107b036ab41ea55f2a4d94
Author: Sosuke Suzuki <[email protected]>
Date: 2026-09-01 (Tue, 01 Sep 2026)
Changed paths:
A JSTests/stress/megamorphic-store-unrelated-accessor.js
M Source/JavaScriptCore/bytecode/InlineCacheCompiler.cpp
M Source/JavaScriptCore/bytecode/InlineCacheCompiler.h
M Source/JavaScriptCore/jit/JITOperations.cpp
Log Message:
-----------
[JSC] One accessor on a prototype disables the megamorphic store cache
https://bugs.webkit.org/show_bug.cgi?id=322708
Reviewed by Yusuke Suzuki.
canUseMegamorphicPutFastPath rejects a prototype chain if any Structure on
it has hasReadOnlyOrGetterSetterPropertiesExcludingProto. That flag covers
every property of the object, so one getter on a class prototype keeps
stores of every other name to its instances out of the megamorphic store
cache. In JetStream3, `node.pos = ...` in TypeScript (Identifier.prototype
has `get text()`) and `node.lastEach = ...` in postcss (Rule.prototype has
`get selectors()`) gave up after 8 structures this way, 1.1M calls of
operationPutByIdStrictGaveUp between them.
What [[Set]] actually depends on is whether the stored name meets a setter
or a read-only property on the chain, and JSObject::putInline already
resolves that: the slot it fills is cacheable only when the store landed
as a plain data property on the receiver. So the megamorphic slow paths
now call putInline and record the entry when the slot is cacheable, and
the chain walk keeps only what the cache epoch cannot express:
overridesPut, overridesGetPrototype and polyProto.
The hit path is unchanged. A miss now walks the chain twice, 3 ns to 6 ns
more on a 25 ns path.
Running JetStream3 locally with --useICStats=1, put_by_id gave-up calls go
from 1.24M to 29K over the whole suite and put_by_val from 692K to 632K,
and no benchmark reports more gave-ups than before, so no newly folded
site is thrashing the cache. Local scores did not show a difference, but
the gave-up path for an existing property is only about 12 ns, so the
change is expected to be within noise there either way.
Test: JSTests/stress/megamorphic-store-unrelated-accessor.js
* JSTests/stress/megamorphic-store-unrelated-accessor.js: Added.
(shouldBe):
(makeShape):
(const.proto.get other):
(put):
(shouldBe.Object.getOwnPropertyDescriptor):
(const.plain.get other):
(const.withSetter.get other):
(const.withSetter.set x):
(const.withReadOnly.get other):
(shouldBe.Object.getOwnPropertyDescriptor.get put):
(set for):
(shouldBe.const.proto.get other):
(shouldBe.put):
* Source/JavaScriptCore/bytecode/InlineCacheCompiler.cpp:
(JSC::canUseMegamorphicPutFastPath): Deleted.
* Source/JavaScriptCore/bytecode/InlineCacheCompiler.h:
(JSC::canUseMegamorphicPutFastPath):
* Source/JavaScriptCore/jit/JITOperations.cpp:
(JSC::putMegamorphic):
(JSC::putByIdMegamorphic):
(JSC::putByValMegamorphic):
Canonical link: https://commits.webkit.org/320236@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications