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

Reply via email to