diff --git a/crates/perry-abi/src/lib.rs b/crates/perry-abi/src/lib.rs index d75f79105d..06c7300a4c 100644 --- a/crates/perry-abi/src/lib.rs +++ b/crates/perry-abi/src/lib.rs @@ -572,9 +572,46 @@ pub const SETTER_SITE_ADDRESS_MASK: u64 = 0x0000_FFFF_FFFF_FFFF; pub const SETTER_SITE_RECV_SHAPE_OFFSET: usize = 0; pub const SETTER_SITE_HOLDER_SHAPE_OFFSET: usize = 4; pub const SETTER_SITE_HOLDER_OFFSET: usize = 8; -pub const SETTER_SITE_SLOT_OFFSET: usize = 16; -pub const SETTER_SITE_PAIR_OFFSET: usize = 24; -pub const SETTER_SITE_CODE_OFFSET: usize = 32; + +/// Byte offsets of the entry's pointer-sized fields and the u32 slot, for a +/// target whose pointers are `ptr_bytes` wide (8 on LP64, 4 on ILP32 such as +/// wasm32). The entry is `#[repr(C)]` with `usize` address fields, so the +/// offsets after the two u32 ShapeIds follow the target's pointer width; the +/// runtime asserts the `SETTER_SITE_*_OFFSET` constants (this crate's own +/// target width) against `offset_of!`, and codegen asks for the width of the +/// target it emits for. +pub const fn setter_site_layout(ptr_bytes: usize) -> SetterSiteLayout { + let slot = SETTER_SITE_HOLDER_OFFSET + ptr_bytes; + let pair = (slot + 4).next_multiple_of(ptr_bytes); + SetterSiteLayout { + holder: SETTER_SITE_HOLDER_OFFSET, + slot, + pair, + code: pair + ptr_bytes, + } +} + +/// See [`setter_site_layout`]. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SetterSiteLayout { + pub holder: usize, + pub slot: usize, + pub pair: usize, + pub code: usize, +} + +const SETTER_SITE_NATIVE: SetterSiteLayout = setter_site_layout(core::mem::size_of::()); +pub const SETTER_SITE_SLOT_OFFSET: usize = SETTER_SITE_NATIVE.slot; +pub const SETTER_SITE_PAIR_OFFSET: usize = SETTER_SITE_NATIVE.pair; +pub const SETTER_SITE_CODE_OFFSET: usize = SETTER_SITE_NATIVE.code; +const _: () = assert!( + setter_site_layout(8).slot == 16 + && setter_site_layout(8).pair == 24 + && setter_site_layout(8).code == 32 + && setter_site_layout(4).slot == 12 + && setter_site_layout(4).pair == 16 + && setter_site_layout(4).code == 20 +); /// The site's holder state word, and its bit for a LATCHED site: one that /// refused, or whose non-own receivers took several shapes. Its misses ask the /// inherited-read hook, as a never-primed site's do. diff --git a/crates/perry-codegen/src/expr/put_value_store_ic/setter_arm.rs b/crates/perry-codegen/src/expr/put_value_store_ic/setter_arm.rs index 7c5d395ea7..e77f7add82 100644 --- a/crates/perry-codegen/src/expr/put_value_store_ic/setter_arm.rs +++ b/crates/perry-codegen/src/expr/put_value_store_ic/setter_arm.rs @@ -107,12 +107,25 @@ pub(super) fn emit_setter_arm( blk.cond_br(&tagged, &recv_l, next_label); addr }; + // The entry's address fields are `usize`: 4 bytes on an ILP32 target, whose + // layout differs from the host's (`abi::setter_site_layout`). + let ilp32 = crate::target_layout::target_is_ilp32(ctx.target_triple); + let layout = abi::setter_site_layout(if ilp32 { 4 } else { 8 }); let field = |ctx: &mut FnCtx<'_>, offset: usize, ty| -> String { let blk = ctx.block(); let a = blk.add(I64, &entry, &offset.to_string()); let p = blk.inttoptr(I64, &a); blk.load(ty, &p) }; + // A pointer-sized field, widened to i64. + let addr_field = |ctx: &mut FnCtx<'_>, offset: usize| -> String { + if ilp32 { + let narrow = field(ctx, offset, I32); + ctx.block().zext(I32, &narrow, I64) + } else { + field(ctx, offset, I64) + } + }; ctx.current_block = recv_idx; let recv_shape = field(ctx, abi::SETTER_SITE_RECV_SHAPE_OFFSET, I32); @@ -123,7 +136,7 @@ pub(super) fn emit_setter_arm( } ctx.current_block = holder_idx; - let holder = field(ctx, abi::SETTER_SITE_HOLDER_OFFSET, I64); + let holder = addr_field(ctx, layout.holder); let holder_shape = field(ctx, abi::SETTER_SITE_HOLDER_SHAPE_OFFSET, I32); { let blk = ctx.block(); @@ -135,9 +148,9 @@ pub(super) fn emit_setter_arm( } ctx.current_block = lane_idx; - let slot = field(ctx, abi::SETTER_SITE_SLOT_OFFSET, I32); - let pair = field(ctx, abi::SETTER_SITE_PAIR_OFFSET, I64); - let code = field(ctx, abi::SETTER_SITE_CODE_OFFSET, I64); + let slot = field(ctx, layout.slot, I32); + let pair = addr_field(ctx, layout.pair); + let code = addr_field(ctx, layout.code); { let blk = ctx.block(); let slot64 = blk.zext(I32, &slot, I64); diff --git a/crates/perry-codegen/src/wasm32/runtime_abi.tsv b/crates/perry-codegen/src/wasm32/runtime_abi.tsv index fedebdeaa9..e895024759 100644 --- a/crates/perry-codegen/src/wasm32/runtime_abi.tsv +++ b/crates/perry-codegen/src/wasm32/runtime_abi.tsv @@ -1977,6 +1977,7 @@ js_native_call_method f64 f64,ptr,usize,ptr,usize js_native_call_method_apply f64 f64,ptr,usize,i64 js_native_call_method_apply_by_id f64 f64,i64,i64 js_native_call_method_by_id f64 f64,i64,ptr,usize +js_native_call_method_by_id_learn f64 f64,i64,ptr,usize,ptr,i32u js_native_call_method_nullsafe f64 f64,ptr,usize,ptr,usize js_native_call_method_patched_proto f64 f64,ptr,usize,ptr,usize js_native_call_method_patched_proto_apply f64 f64,ptr,usize,i64 @@ -2594,6 +2595,7 @@ js_object_get_field_ic_overflow_load f64 ptr,ptr,i32s,ptr js_object_get_field_ic_slow f64 i64,ptr,ptr,ptr js_object_get_index_polymorphic f64 i64,f64 js_object_get_own_field_or_undef f64 f64,ptr,usize +js_object_get_own_field_or_undef_learn f64 f64,ptr,usize,ptr js_object_get_own_property_descriptor f64 f64,f64 js_object_get_own_property_descriptors f64 f64 js_object_get_own_property_names f64 f64 @@ -3908,6 +3910,7 @@ js_typed_feedback_native_call_method_by_id f64 i64,f64,i64,ptr,usize js_typed_feedback_numeric_array_index_get_guard i32s i64,f64,i32s,i32s js_typed_feedback_numeric_array_index_set_guard i32s i64,f64,i32s,f64,i32s js_typed_feedback_numeric_array_push_guard i32s i64,f64,f64 +js_typed_feedback_object_get_field_by_key_f64 f64 i64,ptr,f64,f64 js_typed_feedback_object_get_field_by_name_f64 f64 i64,ptr,ptr js_typed_feedback_object_get_field_by_value_f64 f64 i64,ptr,f64 js_typed_feedback_object_set_field_by_name void i64,ptr,ptr,f64