Skip to content
Closed
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
14 changes: 14 additions & 0 deletions changelog.d/10218-dynamic-index-get-one-exit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Collapse the inline guarded element read for a dynamically typed receiver
(`a[i]` on an erased or union type) from ~51 basic blocks and two runtime call
sites per site to 21 blocks and one call. The dense-Array arm and the
elements-backed Array-subclass probe stay inline and byte-identical; the
shape-carried subclass IC tower (which never fired in the shipped
configuration), the lazy-JSON probe and the spill paths move behind the
existing `js_packed_arraylike_index_get` dispatcher; the typed-array ladder
collapses from eight element kinds onto four element widths, with the brand
test decided on the tag alone. Per site 345 → 173 IR instructions. On
prettier/plugins/flow.mjs `.text` shrinks a further 15.8 % on top of the
budget and property-get changes, ordinary workloads keep their instruction
counts and RSS, and dynamic-receiver typed-array and plain-array reads run
10–32 % fewer instructions. The dispatcher now checks `GC_FLAG_FORWARDED`
before probing a lazy JSON array, which #10098 made movable.
18 changes: 18 additions & 0 deletions crates/perry-codegen/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,24 @@ impl LlBlock {
r
}

/// Reinterpret a 32-bit integer lane as an IEEE-754 single.
///
/// The dynamic `obj[i]` typed-array arm loads a 4-byte lane ONCE and
/// resolves `Int32Array` / `Uint32Array` / `Float32Array` from it with
/// `select`s instead of three loads behind three branches, so the
/// `Float32Array` form needs this reinterpretation of the same register.
pub fn bitcast_i32_to_float(&mut self, val: &str) -> String {
let r = self.reg();
self.push_inst(crate::inst::LlInst::Cast {
dst: r.clone(),
op: "bitcast",
from: "i32",
v: val.to_string(),
to: "float",
});
r
}

pub fn sitofp(&mut self, from_ty: LlvmType, val: &str, to_ty: LlvmType) -> String {
let r = self.reg();
self.push_inst(crate::inst::LlInst::Cast {
Expand Down
13 changes: 7 additions & 6 deletions crates/perry-codegen/src/codegen/index_method_clone_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -804,15 +804,16 @@ fn u31_bitset_clone_uses_one_guarded_uint32_load_and_keeps_dynamic_miss() {
&& clone.contains("load i32")
&& clone.contains("call double @js_dyn_index_get(")
&& clone.contains("call double @js_dynamic_bitand(")
&& !clone.contains("tav.k.i8")
&& !clone.contains("tav.k.f64"),
&& !clone.contains("arrlike.ic.header")
&& !clone.contains("js_packed_arraylike_index_get"),
"the u31 clone must use the monomorphic Uint32 bitset tier and a canonical miss:\n{clone}"
);
assert!(
generic.contains("tav.k.i8")
&& generic.contains("tav.k.f64")
generic.contains("arrlike.ic.header")
&& generic.contains("call double @js_packed_arraylike_index_get(")
&& generic.contains("call double @js_dynamic_bitand("),
"the unproven body must retain the full dynamic typed-array and BigInt behavior:\n{generic}"
"the unproven body must retain the complete dynamic element read (inline hit \
plus its one out-of-line exit) and the BigInt behavior:\n{generic}"
);
}

Expand Down Expand Up @@ -843,7 +844,7 @@ fn u31_transition_clone_returns_a_proved_cached_array_hit_without_second_get() {
.and_then(|tail| tail.split("\ncached_field_index.normal.").next())
.is_some_and(|fast_return| fast_return.contains("ret double"))
&& clone.contains("cached_field_index.normal")
&& clone.contains("tav.k.i8")
&& clone.contains("arrlike.ic.header")
&& clone.contains("if.then"),
"the proved truthy hit must return directly while the complete original body remains as fallback:\n{clone}"
);
Expand Down
1,171 changes: 384 additions & 787 deletions crates/perry-codegen/src/expr/index_get/inline_dyn_typed_array.rs

Large diffs are not rendered by default.

Loading
Loading