Skip to content

codegen: structured intra-function outlining of oversized generated functions (module-entry IIFE) #8595

Description

@proggeramlug

Summary

Perry compiles a module's entire top level into a single LLVM function (@main). For a large minified bundle that function is enormous — the Claude Code cli.js entry is ~68 MB of IR, 439k instructions, with ~13,170 GC-root slots. Essentially every backend algorithm is super-linear in single-function size, so one giant function is simultaneously pathological for:

#8583 works around the GC half by spilling the giant function's roots to the shadow frame so RS4GC skips it. That is a correct stopgap but a heuristic bandage: it leaves a threshold to calibrate, does nothing for the ISel/emit cost, and keeps producing the giant function that every other backend pass then struggles with. module.rs's own comment already flags this: the 68 MB IIFE is "irreducible without structured intra-function outlining."

Proposal

Outline the module-entry body (and, more generally, any oversized generated function) into many smaller functions in codegen, before LLVM sees it:

  • chunk the top-level statement stream (codegen/entry.rs::compile_module_entry) into ordered range-functions called in sequence;
  • promote every module-level let that crosses a chunk boundary to a global — the mechanism already exists (module_globals_emit.rs globalizes lets that escape into closures);
  • preserve evaluation order and TDZ semantics across the chunk boundaries.

Why this is the architecturally correct fix (not a workaround)

Scope / risk

Larger than #8583's series and touches GC root analysis, entry lowering, and global promotion — hence a separate tracker. The secret-tests/claude-code-build/split-bundle-modules.mjs / compose-bundle-entry.mjs tooling is a source-level approximation of the same idea and can inform chunk boundaries.

Follow-up to #8583. Related backend pathology context: #8421 (removed the oversized-function -O0 fallback), #4880, #8128.

Metadata

Metadata

Assignees

No one assigned

    Labels

    performanceRuntime, compile-time, build-size, or memory performance

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions