Skip to content

perf: inherited reads answered from the holder's shape (A1) - #11681

Merged
proggeramlug merged 7 commits into
mainfrom
perf-inherited-read-holder
Sep 29, 2026
Merged

proggeramlug merged 7 commits into
mainfrom
perf-inherited-read-holder

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

perf: an inherited read is answered from its holder's shape (A1).

A read site that misses on the receiver's own keys now remembers the holder: the prototype object that owns the key, with its shape and the slot. On a later miss, the GC-leaf read front checks the holder entry after the ways, the spill entry and a latched site's confirm. An own-key read pays nothing for this.

Instructions per loop iteration (base is main ed0d5b5)

Case base this PR
inherited param / local / modconst / captured 255–268 132–143
inherited varying 306 180
inherited this 283 192
hoisted param / local / modconst / captured 222–231 99–105
hoisted this 254 163
absent, literal only 234 123
absent, literal + class (2 reads) 441 336

tsc and Zod (interleaved medians, n=7; output matches node)

base this PR Change Full collections
tsc 74,398M 74,442M +0.06% 79 / 79
Zod 1,043.0M 1,041.2M −0.18% 0 / 0

Local verification at 4dbeb78

Check Result
runtime --test-threads=1 4803/0
codegen 1826/0
read_holder_entry pass
gap proto / inherit / prototype / getter 82/85, 26/26, 49/51, 14/14; identical per test to base
gc-root-dominance 0 violations; 40/40 seeded violations caught
gc_call_effects, fmt, file size, ABI, root holders pass

Sabotage: removing the holder compare, removing the receiver compare, or skipping the hop words each turns the fixture red. Two sabotages don't yet: not rooting the holder, and admitting class proto ids. Fixture cases for them are follow-up work in A2/A3.

Ralph Küpper added 7 commits September 29, 2026 15:16
…r-shape facts (A1, WIP)

The read site cache gains a holder entry (receiver ShapeId, holder root,
holder ShapeId, slot or absent, up to three hop roots and their ShapeIds),
primed from get_field_ic_miss_impl after the generic getter confirms it and
checked by the emitted tower where the MRU word and the ways miss: depth 1
inline, depth 2-4 through the GC-leaf stub js_read_site_holder_hit. Exotic
read receivers now carry a per-object prototype identity in their shape.
The emitted call to js_inherited_read_cache_hit_f64 is gone; the table itself
stays until A2.
…e inherited-read hook

- The class-field read miss arm (`this.k` in a literal method) asks the
  site holder entry after the MRU word, and a miss the live entry answers
  primes nothing: the `this` cells re-primed on every read (292 -> 4383).
- The inherited-read hook is kept on the never-primed edge and on a miss at
  a site whose ways never primed, for receivers the entry does not describe
  (a compiled-class instance: absent 334 -> 434).
- A site that refused once, or was re-primed for four receiver shapes, is
  latched in its cache state word and never walks or primes again.
- The emitted tower asks the holder entry first on the MRU miss edge, before
  the way state and the ways; the absent kind is a bit test and the holder
  load has no TAG_HOLE compare (a delete is a shape transition, #10826).
- Codegen tests follow the new block graph.
- gc_runtime_root_holders: PASS1_MARKED re-audited and re-pinned for the new
  reg_scanner!; thread_exit_address_globals: HOLDER_SITES holds PIC-arena
  addresses (process_global_allocation).
…ched site asks the inherited-read hook

Asking the holder before the way-state branch cost every polymorphic way hit
a load and a compare, and sending every fresh-ways miss to the hook cost
sites whose receivers the miss handler never learns an extra lookup: Zod
+0.66% median. Now a fresh site asks the holder, a way miss asks it, a
megamorphic site goes straight to the call, and a holder miss asks the hook
only when the site's state word says LATCHED (perry-abi
PIC_HOLDER_STATE_WORD / PIC_HOLDER_STATE_LATCHED). Codegen tests follow.
The holder entry is answered by the read site GC-leaf front (step 4 after the
ways, the spill entry and a latched confirm) instead of an inline block, since
main moved the polymorphic and latched arms out of the emitted tower.
…pre-walk

Since function objects stopped materializing the realm, a never-primed site
whose chain ends at the default link walked before %Object.prototype% existed,
refused, and stayed with the inherited-read cache for good. The walk after the
getter (which resolves it) decides instead.
Object.prototype is minted OrdinaryUnmarked; reads treat it as Ordinary, so the
walk admits every ordinary-layout kind.
@proggeramlug
proggeramlug merged commit 7fa094c into main Sep 29, 2026
21 of 23 checks passed
@proggeramlug
proggeramlug deleted the perf-inherited-read-holder branch September 29, 2026 21:26
@coderabbitai

coderabbitai Bot commented Sep 29, 2026

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: c3b7b890-51b3-4da6-adca-3c0fdfa454ac

📥 Commits

Reviewing files that changed from the base of the PR and between ed0d5b5 and 4dbeb78.

📒 Files selected for processing (16)
  • changelog.d/inherited-read-holder-entry.md
  • crates/perry-abi/src/lib.rs
  • crates/perry-codegen/src/expr/property_get/generic_dispatch.rs
  • crates/perry-codegen/src/expr/property_get/tests.rs
  • crates/perry-runtime/src/gc/mod.rs
  • crates/perry-runtime/src/gc/tests/arguments_objects.rs
  • crates/perry-runtime/src/object/field_get_set/ic_miss.rs
  • crates/perry-runtime/src/object/field_get_set/ic_miss/read_confirm.rs
  • crates/perry-runtime/src/object/method_site.rs
  • crates/perry-runtime/src/object/method_site/read_holder.rs
  • crates/perry-runtime/src/object/proto_validity.rs
  • crates/perry-runtime/src/object/shapes.rs
  • crates/perry-runtime/src/typed_feedback/guards.rs
  • crates/perry/tests/read_holder_entry.rs
  • scripts/gc_runtime_root_holders.json
  • scripts/thread_exit_address_globals.json
 _________________________________________________________________________________________________
< I reached into your code and found nothing there to ease the pressure on my ever-worrying mind. >
 -------------------------------------------------------------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant