You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Scoping for the repsel stack's next gap after 3b/4a: shape proofs do not survive an array element read.keep[j] yields an untyped JSValue, so .v re-enters the field-read diamond that 3b deleted for proven locals. This is the churn-probe access shape and the blocker named in the phase sequencing ("element-shape proof through arrays").
Kernel: keep: {v,w}[] of 200k, sum += keep[j].v × 50 sweeps:
runtime
ms
node
15
bun
23
perry
93
6.2× vs node / 4× vs bun on the pure shape. IR inspection: the loop body carries no out-of-line guard calls (4a's inline element tier + the #5093-family inline field precheck are doing their job) — the cost is the stacked inline diamonds: element-read tier (tag/handle-band/header/layout tests) feeding a field-read precheck (gate load + tag + handle-band + 7 dependent header loads), per iteration. Exactly the 3b recon's "the guard is the cost", now twice per access.
The route decision: both candidate routes share one prerequisite
Route A — element representation (phase-4c style): prove keep : Array<Ptr<__AnonShape_…>> from construction flow, so element reads yield proven Ptr<Shape> and field reads emit bare gep+load. Full fix; helps non-loop access too.
Route B — extend the #5093 versioned-loop clone (machinery just revived by #7425; 3b's recon calls the clone "the only unguarded form today"): hoist ONE whole-array element-shape guard into the preheader, clone the body with bare reads.
The scoping finding is that B is not actually cheaper on the load-bearing part: a preheader "all elements are shape X" test needs a per-array homogeneous-element-shape invariant that does not exist today (the only array-level invariants are the numeric-layout bits, GC_ARRAY_RAW_F64_LAYOUT/_HOLES). Maintaining that invariant — set at construction, updated/cleared at every store site, self-healing like 4a's dense bit — is the same core mechanism Route A needs. Once it exists:
B consumes it first (small codegen change: preheader guard + cloned body via the existing versioned-loop machinery) — fast win on loop-shaped access, which is where the churn probes live.
A consumes it fully (element reads yield Ptr<Shape>, composing with 3b's proven-local machinery) — the durable fix.
So the sequencing is: invariant bit → B → A, not "A vs B".
Constraints carried from the stack
Construction-flow proofs only — TS annotations are hints, never layout (docs/src/internals/…, RFC §9's "typing an array makes it slower today" trap is the cautionary case).
Anon-shape literals are already classes (3b recon: closed-shape {k:v} lowers to __AnonShape_<hash> with a synthesized ctor), so the invariant's shape id exists for free at the allocation site.
Arrays are movable and growth installs forwarding pointers; the invariant bit lives in the header the collector already maintains, and any cached raw base/length stays region-local SSA, re-derived after safepoints (same rule 4a followed).
Scoping for the repsel stack's next gap after 3b/4a: shape proofs do not survive an array element read.
keep[j]yields an untyped JSValue, so.vre-enters the field-read diamond that 3b deleted for proven locals. This is the churn-probe access shape and the blocker named in the phase sequencing ("element-shape proof through arrays").Measured (2026-08-06, release build @ main, checksums equal everywhere)
Kernel:
keep: {v,w}[]of 200k,sum += keep[j].v× 50 sweeps:6.2× vs node / 4× vs bun on the pure shape. IR inspection: the loop body carries no out-of-line guard calls (4a's inline element tier + the #5093-family inline field precheck are doing their job) — the cost is the stacked inline diamonds: element-read tier (tag/handle-band/header/layout tests) feeding a field-read precheck (gate load + tag + handle-band + 7 dependent header loads), per iteration. Exactly the 3b recon's "the guard is the cost", now twice per access.
The route decision: both candidate routes share one prerequisite
Route A — element representation (phase-4c style): prove
keep : Array<Ptr<__AnonShape_…>>from construction flow, so element reads yield provenPtr<Shape>and field reads emit baregep+load. Full fix; helps non-loop access too.Route B — extend the #5093 versioned-loop clone (machinery just revived by #7425; 3b's recon calls the clone "the only unguarded form today"): hoist ONE whole-array element-shape guard into the preheader, clone the body with bare reads.
The scoping finding is that B is not actually cheaper on the load-bearing part: a preheader "all elements are shape X" test needs a per-array homogeneous-element-shape invariant that does not exist today (the only array-level invariants are the numeric-layout bits,
GC_ARRAY_RAW_F64_LAYOUT/_HOLES). Maintaining that invariant — set at construction, updated/cleared at every store site, self-healing like 4a's dense bit — is the same core mechanism Route A needs. Once it exists:Ptr<Shape>, composing with 3b's proven-local machinery) — the durable fix.So the sequencing is: invariant bit → B → A, not "A vs B".
Constraints carried from the stack
docs/src/internals/…, RFC §9's "typing an array makes it slower today" trap is the cautionary case).{k:v}lowers to__AnonShape_<hash>with a synthesized ctor), so the invariant's shape id exists for free at the allocation site.