Bound cumulative SpecConstr inlining - #10622
Conversation
Greptile SummaryThis PR adds a cumulative inlining budget to
Confidence Score: 5/5Safe to merge. The change adds a cumulative admission budget that fires only after all existing correctness guards pass, so ordinary call boundaries are preserved whenever the budget is spent — the program's observable semantics are unaffected. The budget is charged as the very last step before body substitution in both inlining paths, is scoped per-Cloner instance, and is consistently initialised in both init and initForRewrite. The refactored inlineBodySize helper cleanly avoids re-traversing already-computed body sizes. The regression test exercises the exponential-growth scenario end-to-end and asserts both the budget-exhaustion fallback (a retained call_proc) and the total growth bound. Files Needing Attention: No files require special attention.
|
| Filename | Overview |
|---|---|
| src/postcheck/monotype_lifted/spec_constr.zig | Adds inline_body_growth: CodeGrowthBudget to Cloner (budget 4096), refactors inlineBodyAdmission into inlineBodySize+admits(), and inserts admitInlineBodyGrowth checks as the final gate in both inlineCallableValue and inlineDirectCallValue. Logic is sound: budget is only charged after all other guards pass, is per-clone-instance, and the defensive orelse return false in admitInlineBodyGrowth correctly handles the (unreachable-in-practice) over_limit case. |
Reviews (2): Last reviewed commit: "Address SpecConstr review feedback" | Re-trigger Greptile
Summary
Root cause
SpecConstr already rejected any single source body larger than its per-function threshold, but it did not bound cumulative transitive inlining. A graph of small acyclic wrappers can call the preceding wrapper multiple times at every level, so every individual inline is admitted while the complete expansion grows exponentially.
In the basic-cli reproduction, the optimized test plan spent minutes in SpecConstr and grew past five million Monotype Lifted expressions and fifteen million inline scopes. This was compiler IR expansion rather than a process deadlock or platform download issue.
The new admission budget charges every accepted inline by the exact source-body size already computed by SpecConstr. Once the budget is spent, the pass preserves the existing ordinary call boundary. This keeps rewrite legality separate from code-growth admission and gives each clone a hard bound on transitive inline work.
Verification
Closes #10618