Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions changelog.d/10946-region-reads-across-statements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
**perf(codegen): guard a run of property reads spelled across statements once (#10884 step 4b, slice 2).** `const a = o.a; const b = o.b; const c = o.c;` is now one region with one shape guard instead of three separately guarded reads.

The guard itself (state word, R1/R2, bounded prime, miss edges) moves into the shared `expr/region_guard.rs`, so the within-expression slice and this one match over a single guard with a single soundness argument. Slice 1's measurements are unchanged by the move.

This slice can't duplicate the run into fast and slow copies: `Stmt::Let` would allocate an entry alloca per copy. It can't phi the loaded values either, because in the bail arm a generic read can reach a getter and move the heap. Instead each binding is declared once through the ordinary `Let` path. The fast arm stores each loaded slot into its binding immediately, so every value is rooted before the next read, and the bail arm assigns the same slots in source order.

Nothing is hoisted across an operator, so there is no type condition: string- and object-valued fields qualify too. The kill switch is `PERRY_REGION_READS=0`.
2 changes: 1 addition & 1 deletion crates/perry-codegen/src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ pub fn compile_module(hir: &HirModule, opts: CompileOptions) -> Result<Vec<u8>>
let triple = opts.target.clone().unwrap_or_else(default_target_triple);
// `PERRY_REGION_DIAG=1`: report step 4b's regions and the statement-level
// runs it does not reach, when this module's codegen ends.
let _region_diag = crate::expr::region_read_run::ModuleDiag::start(hir);
let _region_diag = crate::expr::region_guard::ModuleDiag::start(hir);
let fp_flags = crate::block::FpFlags::new(opts.fast_math, opts.fp_contract_mode);

// #5334 lever B: decide ONCE, up front, whether this module is large enough
Expand Down
1 change: 1 addition & 0 deletions crates/perry-codegen/src/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2995,6 +2995,7 @@ pub(crate) mod calls;
mod child_proc;
mod closure;
mod compare;
pub(crate) mod region_guard;
pub(crate) mod region_read_run;
pub(crate) use compare::lower_string_literal_strict_eq;
#[cfg(test)]
Expand Down
Loading
Loading