Skip to main content

Module arena

Module arena 

Source
Expand description

Request-scope arena-eligibility analysis (#463 slice 1).

Per-allocation-site classification: is this MakeRecord / MakeTuple value safe to route through the active per-request arena (EffectHandler::enter_request_scope), instead of the global allocator?

§Relationship to escape::analyze_function (#464)

Same lattice, same worklist, same step rules — with one bit of policy flipped: Op::Return is not an escape op here, because the returned value goes to the caller’s stack and the caller is in the same request scope as us. Everything else (Call, CallClosure, TailCall, EffectCall, MakeClosure captures, aggregate-as-field, worker-pool ops, Dup, …) stays a hatch under the slice-1 intra-procedural conservative policy. The shared machinery is escape::analyze_function_with_policy(_, Policy::RequestScope); this module wraps it and inverts the per-site escapes bool into arena_eligible.

§Slice scope

Analysis only. No opcode lowering, no runtime behavior change, no bytecode-format change. Slice 2 (AllocArenaRecord / AllocArenaList / handle variants on Value) consults build_arena_index at codegen time.

§Soundness contract

Inherits #464’s contract verbatim (docs/design/escape-analysis.md § “Soundness contract”):

  • Over-approximation (arena_eligible = false when the value actually stays in-scope) costs a heap allocation — the status-quo baseline. Acceptable.
  • Under-approximation (arena_eligible = true when the value actually escapes the request) would let an arena handle outlive its slab and is UB. Slice 2 must pair this analysis with an unconditional runtime fallback (same shape as #464’s AllocStackRecord heap fallback), so a missed hatch costs correctness only if the analysis is wrong and the fallback is omitted — never both.

§Out of scope for slice 1

  • Inter-procedural escape (the scoping doc defers this until inlining lands with #465 phase 1; any Call is a hatch here).
  • Worker-handler lifetime split (spawn_for_worker clone-handlers get a fresh empty arena stack — values handed to workers must never become arena handles). Already covered by the conservative hatches on Call/ParallelMap/SortByKey; slice 2 must keep that invariant when routing.

Structs§

ArenaReport
Per-function arena-eligibility report. Mirrors EscapeReport’s shape with the per-site bool inverted (arena_eligible = !escapes_under_request_scope) and renamed to reflect what downstream codegen will use it for.
ArenaSite

Functions§

analyze_function
Analyze one function. Cheap on functions with no aggregate sites (early-exits in the underlying pass).
analyze_program
Analyze every function. Functions with no aggregate sites are omitted from the result, matching escape::analyze_program.
build_arena_index
Convenience map keyed by (fn_name, pc) for direct lookup during the slice-2 codegen pass. Mirrors escape::build_escape_index exactly so the codegen swap is structural.