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
8 changes: 8 additions & 0 deletions changelog.d/7951-float64array-spec-abi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
### Performance

- **Monomorphic typed-array helpers now preserve raw arguments through their
specialized ABI (#7221).** An immutable numeric local used as a typed-array
constructor length now proves the same non-view shape as a direct literal,
and integer locals with complete write-set proofs cross direct calls as raw
`i32` values. This lets derived indices remain native inside the helper and
lowers `Float64Array` writes to direct stores instead of the dynamic setter.
14 changes: 13 additions & 1 deletion crates/perry-codegen/src/codegen/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,17 @@ pub(super) fn compile_function(
.collect()
})
.unwrap_or_default();
let spec_i32_params: HashSet<u32> = spec_entry
.map(|plan| {
f.params
.iter()
.zip(plan.reps.iter())
.filter_map(|(p, rep)| {
matches!(rep, crate::collectors::SpecParamRep::I32).then_some(p.id)
})
.collect()
})
.unwrap_or_default();
// `--opt-report` (#6952): attribute every representation decision the
// collectors below make to this function. No-op when the report is off.
//
Expand All @@ -618,7 +629,7 @@ pub(super) fn compile_function(
.return_shape_class(f.id)
.is_some(),
);
let native_facts = crate::collectors::collect_native_region_fact_graph_with_spec_lens(
let native_facts = crate::collectors::collect_native_region_fact_graph_with_spec_params(
&f.body,
&f.params,
&flat_const_ids,
Expand All @@ -632,6 +643,7 @@ pub(super) fn compile_function(
&cross_module.compile_time_constants,
&cross_module.module_dispatch,
&spec_ta_lens,
&spec_i32_params,
);

if let Some(plan) = spec_entry {
Expand Down
19 changes: 12 additions & 7 deletions crates/perry-codegen/src/collectors/hir_facts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,19 +409,21 @@ pub(crate) fn collect_type_facts(
compile_time_constants: &HashMap<u32, f64>,
module_dispatch: &super::ModuleDispatchFacts,
spec_ta_lens: &HashMap<u32, i64>,
spec_i32_params: &HashSet<u32>,
) -> TypeFacts {
// #7700: which locals hold a NUMBER, so a `u8[k]` keyed on one is a byte
// read rather than a property read. Computed once here because
// `binding_types` covers only params and module globals — the body `let`s,
// above all the counter in `for (let i = …) sum += buf[i]`, have to be
// walked for or the hottest buffer shape loses its i32 representation.
let numeric_locals = super::collect_numeric_typed_locals(stmts, params, binding_types);
let mut integer_locals = super::integer_locals::collect_integer_locals(
let mut integer_locals = super::integer_locals::collect_integer_locals_with_seeds(
stmts,
flat_const_ids,
clamp_fn_ids,
arg_dependent_clamp_fn_ids,
&numeric_locals,
spec_i32_params,
);
// Native-i32 residency for integer-valued locals whose init/writes include a
// possibly-out-of-bounds INT typed-array element read (bcryptjs `_encipher`
Expand Down Expand Up @@ -679,7 +681,7 @@ pub(crate) fn collect_native_region_fact_graph(
compile_time_constants: &HashMap<u32, f64>,
module_dispatch: &super::ModuleDispatchFacts,
) -> NativeRegionFactGraph {
collect_native_region_fact_graph_with_spec_lens(
collect_native_region_fact_graph_with_spec_params(
stmts,
params,
flat_const_ids,
Expand All @@ -692,15 +694,15 @@ pub(crate) fn collect_native_region_fact_graph(
compile_time_constants,
module_dispatch,
&HashMap::new(),
&HashSet::new(),
)
}

/// Variant carrying spec-ABI `TaPtr` parameter lengths (representation-
/// selection Phase 2): the call-site pre-pass proved these params hold
/// non-view typed arrays with these constant element counts, which unlocks
/// the wrap-i32 additive admission's in-bounds operand proof.
/// Variant carrying spec-ABI parameter facts (representation-selection Phase
/// 2): `TaPtr` lengths unlock in-bounds proofs, while raw-i32 params seed the
/// ordinary integer-local fixed point so derived index temps stay native.
#[allow(clippy::too_many_arguments)]
pub(crate) fn collect_native_region_fact_graph_with_spec_lens(
pub(crate) fn collect_native_region_fact_graph_with_spec_params(
stmts: &[Stmt],
params: &[perry_hir::Param],
flat_const_ids: &HashSet<u32>,
Expand All @@ -713,6 +715,7 @@ pub(crate) fn collect_native_region_fact_graph_with_spec_lens(
compile_time_constants: &HashMap<u32, f64>,
module_dispatch: &super::ModuleDispatchFacts,
spec_ta_lens: &HashMap<u32, i64>,
spec_i32_params: &HashSet<u32>,
) -> NativeRegionFactGraph {
collect_type_facts(
stmts,
Expand All @@ -727,6 +730,7 @@ pub(crate) fn collect_native_region_fact_graph_with_spec_lens(
compile_time_constants,
module_dispatch,
spec_ta_lens,
spec_i32_params,
)
}

Expand All @@ -753,6 +757,7 @@ pub(crate) fn collect_hir_facts(
// conservative default keeps it that way if one ever could.
&super::ModuleDispatchFacts::default(),
&HashMap::new(),
&HashSet::new(),
)
}

Expand Down
24 changes: 23 additions & 1 deletion crates/perry-codegen/src/collectors/integer_locals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,29 @@ pub fn collect_integer_locals(
// key is one of those, or is numeric by construction.
numeric_locals: &HashSet<u32>,
) -> HashSet<u32> {
let mut candidates: HashSet<u32> = HashSet::new();
collect_integer_locals_with_seeds(
stmts,
flat_const_ids,
clamp_fn_ids,
arg_dependent_clamp_fn_ids,
numeric_locals,
&HashSet::new(),
)
}

/// The ordinary integer-local proof with already-proven i32 locals seeded
/// into its transitive closure. Specialized-ABI raw-i32 parameters use this:
/// plan selection has already rejected reassigned/captured parameters, so the
/// seed is a construction proof rather than a declared-type assumption.
pub(crate) fn collect_integer_locals_with_seeds(
stmts: &[perry_hir::Stmt],
flat_const_ids: &HashSet<u32>,
clamp_fn_ids: &HashSet<u32>,
arg_dependent_clamp_fn_ids: &HashSet<u32>,
numeric_locals: &HashSet<u32>,
seed_locals: &HashSet<u32>,
) -> HashSet<u32> {
let mut candidates: HashSet<u32> = seed_locals.clone();

// Issue #50 bridge: pre-compute which locals are row-aliases of
// flat-const 2D int arrays BEFORE collecting integer let ids, since
Expand Down
2 changes: 1 addition & 1 deletion crates/perry-codegen/src/collectors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub(crate) use escape_arrays::{const_index, MAX_SCALAR_OBJECT_FIELDS};
pub(crate) use escape_check::{check_escapes_in_stmts, find_new_candidates};
pub(crate) use escape_news::MAX_SCALAR_ARRAY_LEN;
pub(crate) use hir_facts::{
collect_native_region_fact_graph, collect_native_region_fact_graph_with_spec_lens,
collect_native_region_fact_graph, collect_native_region_fact_graph_with_spec_params,
NativeRegionFactGraph,
};
pub(crate) use hot_callees::{collect_alloc_hot_functions, collect_hot_loop_callees};
Expand Down
Loading
Loading