Skip to content

perf(runtime): a latched-megamorphic read is answered from the receiver's shape key list - #11438

Merged
proggeramlug merged 3 commits into
mainfrom
perf-megamorphic-read-s3
Sep 26, 2026
Merged

proggeramlug merged 3 commits into
mainfrom
perf-megamorphic-read-s3

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

What

A read site that has latched megamorphic sees 33+ shapes. It used to miss into the generic by-name machinery on every access, at about 713–731 instructions per read (node: ~51–60).

It is now answered from the receiver's own shape key list: find the key in the list the receiver's ShapeId names, then load that slot. The site holds nothing beyond the latch. The shape is the authority for which slot holds the key, and there is no side table.

  • The read path stays gated by the receiver's descriptor flag. Receivers with accessors or attributes keep the generic path.
  • Receivers with dictionary, class-typed-layout or tombstoned shapes decline to the generic path.

tsc's AST sites are the main customer: 49% of its object reads miss the IC, because its node-kind sites see 33+ shapes.

This is the first stage of the megamorphic plan. Global key interning ("atoms") and an inline shape-confirmed slot guess were measured too. Together they took tsc to −5.1%, but they cost Zod +1.4% and tsc +15 MB RSS for reasons not yet explained. They are held for a follow-up that must meet a Zod-flat bar.

Numbers

Dedicated Linux host, both arms with matched build settings, each linking its own runtime. 5 interleaved rounds, identical output every round.

base this PR
40-shape o.kind fixture, instructions per read 731 315 (node: 60)
tsc transpileModule 97.71 G 95.99 G (−1.8%)
Zod 1680.0 M 1681.9 M (+0.11%, flat)
tsc peak RSS ~342 MB ~342 MB
.text size flat

Verification

  • RUSTFLAGS=-D warnings on runtime and codegen (lib and all targets): 0 diagnostics. cargo fmt is clean.
  • The shape-descriptor census gate passes.
  • Runtime suite 4625/0 and codegen suite 2246/0 (--test-threads=1).
  • GC root-dominance passes. The only failure is the macOS-only verify_symbols.
  • run_lint_gates passes 100/102. The two failures are host-only (cargo xwin, and public-baseline freshness, which also fails on main).
  • Gap suite, all 1070 tests on both arms with node 26.5.1 pinned, compared by id: no regressions. Two timing tests that fail on base pass here.
  • The commits were cherry-picked cleanly onto current main (which includes perf(runtime): property attributes live with the keys (descriptor arrays); no per-object attribute tables #11411). An accessor fixture on the rebased build matches node: literal getter, defineProperty getter, __defineGetter__, and a non-writable value.

Ralph Küpper added 3 commits September 26, 2026 17:02
…shape key list

A site whose way state is latched megamorphic re-ran the whole generic miss
machinery on every read: ~730 instructions on a 40-shape `o.kind` site
(node: ~60), dominated by the receiver re-classification, the
inherited-read-cache probe, the re-priming of a site that will not prime,
and a by-name scan.

Before that, the slow entry now asks the receiver's own shape record: an
Ordinary, generation-0, hole-free shape stores an own inline key at its
position in its canonical key list, so the key's position below the key
count and the live inline slot count IS its inline slot, and the value is
loaded from there. The site's compact word keeps an unmatchable low half
and carries the last answered slot in its high half as the next guess,
which the receiver's key list confirms before any scan. Dictionary,
generation > 0, tombstones, spill, inherited keys, descriptors and `length`
fall through unchanged.
@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 3 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 8 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 30e9088e-5e69-4c7b-afde-b6771b792cf4

📥 Commits

Reviewing files that changed from the base of the PR and between 2c90f29 and 0cae43d.

📒 Files selected for processing (3)
  • changelog.d/11438-megamorphic-read-shape-key-list.md
  • crates/perry-runtime/src/object/field_get_set/ic_miss/ic_slow.rs
  • crates/perry-runtime/src/object/shapes.rs

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.

@proggeramlug

Copy link
Copy Markdown
Contributor Author

Review note: the suites, gap suite and A/B numbers in the description were measured on base 3463ca30b. The commits were then cherry-picked cleanly onto current main, which includes #11411 (attributes live with the keys). On the rebased build only an accessor fixture was re-checked, and it matches node. CI's suites are the verification of the rebased head.

Accessor safety: the new read path is kept away from accessors by the receiver's descriptor flag, which main still sets on every descriptor install. If that flag is ever removed, this path would also need to check the shape's accessor summary.

@proggeramlug
proggeramlug merged commit 0f029e5 into main Sep 26, 2026
54 of 56 checks passed
@proggeramlug
proggeramlug deleted the perf-megamorphic-read-s3 branch September 26, 2026 23:54
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