Skip to content

fix(codegen): treat LLVM macOS and visionOS triples as low-address heap targets - #12247

Merged
proggeramlug merged 2 commits into
mainfrom
fix/macos-llvm-triple-heap-floor
Oct 9, 2026
Merged

proggeramlug merged 2 commits into
mainfrom
fix/macos-llvm-triple-heap-floor

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Problem

perry-codegen/src/target_layout.rs::heap_addr_lower_bound_inclusive sets the lowest address that codegen's inline heap guards will dereference. It recognises "mainstream" targets by substring, but codegen passes LLVM triples rather than rustc ones:

  • the macOS host default is arm64-apple-macosx15.0.0 (codegen/helpers.rs::default_target_triple, and --target macos), which contains neither darwin nor ios;
  • visionOS is arm64-apple-xros1.0 (--target visionos), which doesn't contain visionos.

Both fall to the conservative 2 TiB floor instead of the 1 MiB handle-band floor that the runtime's is_valid_obj_ptr uses on those OSes. Every inline guard built on that floor sends any GC object below 2 TiB to the runtime slow path. That includes class-method direct calls and learned receiver words, the #620 own-method override probe, composed property ICs, inline typed-array/buffer reads and versioned indexed loops.

On macOS today this is mostly hidden: mimalloc places its arenas above 2 TiB, so GC objects happen to clear the floor. Anything that puts GC memory below 2 TiB pays the slow path on every call. That includes OS-backed GC regions, which land near 4 GiB on macOS, and libsystem-malloc allocations on visionOS.

Evidence

The bug was found while investigating why Perry-owned mmap GC regions regressed on macOS (portable region branch vs #12132, same generated program code).

  • Commander's retired instructions rose by +14% and Zod's by +7%.
  • sample profile on symbolized builds: js_object_get_own_field_or_undef went from 0% to 7.6% of leaf samples on Commander, with learn_absent_method_word and from_utf8 appearing.
  • lldb call counts, 300 Commander iterations: js_object_get_own_field_or_undef_learn was called 24,300 times vs 42 on gc: Perry-owned memory for GC arena blocks (2 MiB OS regions, huge pages by complete units) #12132. js_native_call_method_by_id_learn was called 7,200 vs 2 times. On Zod (50 iterations) it was 1,850 vs 60.
  • A per-call trace showed the site had already learned exactly the receiver's (class_id, ShapeId) word and the header was a plain GC_TYPE_OBJECT. The only failing input was the address gate (0x1_05a7_74e8 < 2 TiB; on mimalloc the same receiver sat at 0x34c_d52a_74e8).
  • With this fix the counts return to 42 / 2 / 60. Commander's regression drops from +14% to +0.5%, and Zod's from +7% to +1.1%. The remainder was a separate runtime issue on that branch, not part of this PR.
  • On gc: Perry-owned memory for GC arena blocks (2 MiB OS regions, huge pages by complete units) #12132 with mimalloc, the fix is neutral (interleaved, n=3): Commander retired 6,999–7,039M instructions before the fix and 6,990–7,026M after; Zod 13,627–13,645M before and 13,629–13,676M after.

Change

  • heap_addr_lower_bound_inclusive also matches macos and xros.
  • New test heap_address_floor_covers_emitted_triples checks the floor for the triples codegen really emits: default_target_triple() and resolve_target_triple() for every public --target name. HarmonyOS keeps the 2 TiB floor, as before.
  • Negative control: with the two new arms removed, the test fails on arm64-apple-macosx15.0.0.

Linux, Android, Windows, iOS, tvOS, watchOS and WASI triples already matched, so their generated code is unchanged.

Validation

  • cargo test --release -p perry-codegen --lib: 2,104 passed, 0 failed, 1 ignored. The new test is included.
  • rustfmt --check is clean.

No version bump.

Ralph Küpper added 2 commits October 9, 2026 04:58
Codegen's inline heap guards use heap_addr_lower_bound_inclusive. It
matched rustc spellings (darwin, visionos) but codegen passes LLVM
triples: the macOS host default is arm64-apple-macosx15.0.0 and visionOS
is arm64-apple-xros1.0. Both fell to the 2 TiB floor, so every inline
method, learned-word and property guard missed for heap objects below
2 TiB. mimalloc's arenas sit above 2 TiB, which hid it; Perry's own mmap
regions land near 4 GiB and paid the runtime slow path on every call.

The test now checks the triples codegen really emits.
@coderabbitai

coderabbitai Bot commented Oct 9, 2026

Copy link
Copy Markdown

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 9af3b760-17fe-4cc4-bdda-663745d7cd61
📥 Commits

Reviewing files that changed from the base of the PR and between 484345a and 283cdb9.

📒 Files selected for processing (1)
  • crates/perry-codegen/src/target_layout.rs
 ________________________________________________________________
< This is the kind of code that makes on-call believe in ghosts. >
 ----------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@proggeramlug
proggeramlug merged commit 2759d7e into main Oct 9, 2026
72 of 73 checks passed
@proggeramlug
proggeramlug deleted the fix/macos-llvm-triple-heap-floor branch October 9, 2026 03:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant