Skip to content

codegen: reconcile the root-spill threshold (#8623, 32M) with the RS4GC instruction budget (#8586, 1.57M) — budget-gap functions get refused instead of spilled #8679

Description

@proggeramlug

Problem

Two #8583 mechanisms disagree on where a function is "too big for RS4GC":

Since a function's added instructions ≈ its relocation estimate, a function whose estimate lands in (1.57M, 32M) does not spill (estimate < 32M) yet overruns the budget (post-rewrite > 1.57M) → the budget assertion hard-refuses the whole module.

Concrete case

Compiling the Claude Code cli.js 2.1.112 bundle, __AnonShape_ec12be8bd7b0a2b9_constructor (a large closed-shape object-literal constructor) grew 34,009 → 2,280,128 instructions under RS4GC — above the 1.57M budget, below the 32M spill threshold — and was refused. It only compiled with PERRY_ROOT_SPILL_RELOCATIONS=1500000. (Estimate accuracy for this shape is fixed by #8678, which counts property/index stores; but even with an accurate ~2.25M estimate it still won't spill at the 32M default.)

Options

  1. Align the spill default with the budget — set DEFAULT_ROOT_SPILL_RELOCATIONS at/below PERRY_LL_RS4GC_MAX_INSTRS so anything that would overrun the budget spills first. (Note this revisits perf(codegen): raise root-spill default to the measured RS4GC fan-out cliff (#8620) #8623/codegen: #8589 root-spill default threshold (4M) too low — spills moderate-fan-out functions and slows their compile #8620: the "8M fans-out-fine" cases codegen: #8589 root-spill default threshold (4M) too low — spills moderate-fan-out functions and slows their compile #8620 measured would also overrun the 1.57M budget, so they should spill — RS4GC finishing ≠ the optimizer handling the result.)
  2. Preferred: make the budget trigger a spill-retry, not a hard refusal — when a function overruns the budget post-rewrite, re-lower it with request_shadow_frame_spill() (roots to the shadow frame, RS4GC skips it) instead of refusing the module. This is the "fix: make compile output TypeScript-developer friendly #8421/fix(codegen): unbreak in-process RS4GC on inline asm and relocation-grown functions #8128 root-lowering choice, never refuse" principle applied to the budget, and it needs no threshold tuning at all.

Option 2 is the durable fix. Found while getting the cli.js bundle to a working native binary (#8583).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions