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
14 changes: 12 additions & 2 deletions crates/perry-codegen/src/expr/property_get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1325,10 +1325,20 @@ pub(crate) fn lower(ctx: &mut FnCtx<'_>, expr: &Expr) -> Result<String> {
.cond_br(&guard_pass, &fast_label, &fallback_label);

ctx.current_block = fast_idx;
// arm64_32 watchOS: the object fields region begins at
// `size_of::<ObjectHeader>()` past the user pointer — 24 on
// 64-bit, 20 on ILP32 (the trailing `keys_array` pointer is 4
// bytes there). A hardcoded 24 reads every class field 4 bytes
// off on a 32-bit watch, so this inline class-field load
// disagreed with the generic-PIC load / runtime setter (both
// target-aware) and typed-object string fields came back as
// word-swapped NaN-boxes. Derive it from the target triple
// (no-op on 64-bit; see `target_layout`).
let header_skip =
crate::target_layout::object_header_size_bytes(ctx.target_triple)
.to_string();
let blk = ctx.block();
let obj_ptr = blk.inttoptr(I64, &obj_handle);
// Skip the 24-byte ObjectHeader.
let header_skip = "24".to_string();
let fields_base = blk.gep(I8, &obj_ptr, &[(I64, &header_skip)]);
let field_ptr = blk.gep(DOUBLE, &fields_base, &[(I64, &field_idx_str)]);
let val_fast = blk.load(DOUBLE, &field_ptr);
Expand Down
12 changes: 11 additions & 1 deletion crates/perry-codegen/src/expr/property_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -650,9 +650,19 @@ pub(crate) fn lower(ctx: &mut FnCtx<'_>, expr: &Expr) -> Result<String> {
let field_set_barrier_needed =
!expr_produces_non_pointer_bits_by_construction(ctx, value);
let raw_stored_value = {
// arm64_32 watchOS: the object fields region begins at
// `size_of::<ObjectHeader>()` past the user pointer — 24 on
// 64-bit, 20 on ILP32 (the trailing `keys_array` pointer is
// 4 bytes there). A hardcoded 24 writes every class field 4
// bytes off on a 32-bit watch; the paired inline read
// (`property_get`) and the runtime setter must agree, so
// derive it from the target triple (no-op on 64-bit; see
// `target_layout`).
let header_skip =
crate::target_layout::object_header_size_bytes(ctx.target_triple)
.to_string();
let blk = ctx.block();
let obj_ptr = blk.inttoptr(I64, &obj_handle);
let header_skip = "24".to_string();
let fields_base = blk.gep(I8, &obj_ptr, &[(I64, &header_skip)]);
let field_ptr = blk.gep(DOUBLE, &fields_base, &[(I64, &field_idx_str)]);
let raw_stored_value = if requires_raw_f64 {
Expand Down
Loading