merge: land #8652, #8651, #8647, #8646, #8650 - #8657
Merged
Conversation
added 15 commits
August 23, 2026 12:06
…c descriptor + one bulk call (#8583 follow-up) A minified bundle data table is a giant nested constant array literal. The default lowering builds it procedurally — one `js_array_from_values` per sub-array plus the inline element stores — so the Claude Code bundle's `__33499` (a constant numeric array-of-arrays) lowered to 11,104 allocations and a 245k- instruction body that made `rewrite-statepoints-for-gc` fan out. This adds a codegen path that recognizes a LARGE, fully-constant array literal (number/int/bool/null/undefined, recursively nested arrays) and instead: * serializes the constant tree into a compact tagged blob emitted as module- private rodata, and * emits ONE call to a new runtime helper `js_value_from_const_descriptor` that materializes the whole nested structure in a single pass. The runtime builds a FRESH, mutable array each call (JS array literals are mutable, so the descriptor is a template, never a shared constant), under `GcSuppressScope` so the partially-built parents held across nested child allocations cannot be collected or moved — the same discipline `js_json_parse` and the lazy-array materializer use. All-number rows keep the raw-f64 layout; any pointer element downgrades the row via `store_array_slot`. Gated on a 256-node minimum, so small literals keep the fast inline bump-alloc path (no regression). `PERRY_CONST_ARRAY_DESCRIPTOR=0` reverts to the procedural path (A/B bisection + escape hatch). On a 3,000-row nested-array synthetic: the 3,000+ `js_array_from_values` calls collapse to one `js_value_from_const_descriptor` + a rodata blob; the compile drops from not-finishing-in-2min to 1.46s; output is byte-identical to the procedural build across the moving-GC matrix, with mutation-after-materialize and bool/null rows verified. Claude-Session: https://claude.ai/code/session_01TwxRkALrR9HKSF1zKLSTAF
A flat constant scalar array (e.g. `[0; 2050]`) is already a single `js_array_alloc_literal` + inline stores — not the per-subarray fan-out the descriptor targets — and its inline path carries the precise per-slot write barriers a later push/store depends on (large_object_barriers). Gate the descriptor path on the literal containing at least one nested array element, so only genuine nested data tables (the __33499 shape) take it; flat arrays keep their existing path. Verified: the nested 3,000-row synthetic still collapses to one js_value_from_const_descriptor call, and large_object_barriers passes. Claude-Session: https://claude.ai/code/session_01TwxRkALrR9HKSF1zKLSTAF
…ated) blocks (#8583) When a sub-expression provably diverges — a throwing operand (e.g. a captured TDZ access or const-reassignment) emits `js_throw_error_with_code` + `unreachable` — the current block is terminated. `LlBlock` silently drops any instruction emitted after a terminator (block.rs), so the setup instructions for the surrounding operation are discarded; but block-creating lowerings still emit fresh blocks that reference those dropped `%rN` registers, which the dialect builder rejects with "register %rN used but never defined" (dialect/mod.rs). The whole surrounding operation is unreachable on that path, so the fix is to emit nothing once the block is terminated. Two sites hit this in the Claude Code 2.1.112 bundle (both dead code after a proven-throwing operand): `lower_index_set_fast` (`a[i] = v`, closure `__44845`) and `emit_persistent_shadow_root_barrier` (a pointer root store, closure `__44449`). Each now returns early when `ctx.block().is_terminated()`. Also adds a `PERRY_DIALECT_DUMP=<dir>` diagnostic: on a dialect construction failure, `render_units_from_frozen` names the offending function and writes its full IR (typed insts rendered via `render_into`) — the failing unit never parses, so the normal `PERRY_SAVE_LL` post-parse dump cannot capture it. This is how the two sites above were located. Validated end-to-end: with these guards, the cli.js bundle codegens ALL 84 units with zero "used but never defined" errors (it previously failed at unit 25); the remaining blocker to a final binary is unrelated (host disk). Claude-Session: https://claude.ai/code/session_01TwxRkALrR9HKSF1zKLSTAF
This was referenced Aug 23, 2026
Closed
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (96)
📝 WalkthroughWalkthroughThis change adds descriptor-based lowering for large constant arrays and updates runtime handling for reflection, built-ins, iterators, typed arrays, buffers, promises, generators, GC rooting, and related semantic regression tests. ChangesRuntime and codegen behavior
Estimated code review effort: 5 (Critical) | ~120 minutes Suggested reviewers: ✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
This was referenced Aug 23, 2026
proggeramlug
added a commit
that referenced
this pull request
Aug 23, 2026
…ash (#8669) #8650 changed `UnaryOp::Pos` on a non-numeric operand from `js_number_coerce` to `js_dynamic_pos` and updated the three computed_store_rooting_tests that assert on it. The #8657 squash kept the emission change and lost the test edit, leaving the assertions naming a helper the compiler no longer emits there. They failed 4/4 on main; 0/3 with this. Refs #8658. Co-authored-by: Ralph Küpper <ralph@skelpo.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lands five PRs together: #8652, #8651, #8647, #8646, #8650.
(#8645 is held back — it conflicts with #8650 in
class_registry/constructand both lower the same raw-handle baseline from 925. It goes in a second pass
rebased on this.)
Contents
register %rN was used but never definedat unit 25 of the Claude Code bundleValidation
cargo fmt --all -- --check: pass (I reformatted one test file the stack left unformatted)cargo check --workspace --all-targets: exit 0, no warnings in touched cratesperry-codegenlib: 1189 passed, 0 failedperry-runtimelib (RUST_TEST_THREADS=1): 2641 passed, 0 failedBoth large PRs lower the raw-handle ratchet rather than re-baselining it
(#8650 takes it 925 -> 923), which is the correct direction — debt paid down by
the change that earns it.
I added the two missing changelog fragments (#8646, #8650).
One thing recorded, not hidden
Running
-p perry-runtime -p perry-codegen --libtogether underRUST_TEST_THREADS=1intermittently fails threeexpr::computed_store_rooting_testscases on this branch — roughly 3 in 12runs. Clean
mainis 0 in 12 under the same command at comparable load(52-68), so the asymmetry is real and I am not claiming it is pre-existing.
What it is not: each of the three codegen-touching PRs is 0/4 alone; the full
codegen suite passes on this branch both filtered and unfiltered, repeatedly;
and the failing assertions are about which optimization tier codegen chose,
not about emitted semantics. A tier selection that flips with machine load
points at codegen nondeterminism, which would be a pre-existing property this
stack merely exposes more often.
Filed separately with the full run-by-run evidence. Flagging it here because a
future bisect will otherwise rediscover it the hard way.
Summary by CodeRabbit
New Features
for await...of.Argumentsiteration and customizednextmethods.ArrayBuffer.prototype.slice, typed-array inheritance, and buffer property handling.Date.prototype.toTemporalInstantsupport where available.Bug Fixes