Skip to content

fix(ext/ffi): match V8 stack-arg layout in turbocall trampoline on Apple silicon#34561

Merged
littledivy merged 1 commit into
mainfrom
orch/divybot-321
May 30, 2026
Merged

fix(ext/ffi): match V8 stack-arg layout in turbocall trampoline on Apple silicon#34561
littledivy merged 1 commit into
mainfrom
orch/divybot-321

Conversation

@divybot

@divybot divybot commented May 30, 2026

Copy link
Copy Markdown
Contributor

Summary

V8's fast API on arm64 always packs stack arguments into 8-byte slots (AAPCS64 layout), but Apple silicon's ABI uses natural alignment (e.g. 4-byte slots for i32/f32). Cranelift's default calling convention on aarch64-apple-darwin is AppleAarch64, so the turbocall wrapper that V8 invokes would read stack args at the wrong offsets and pick up garbage as soon as a fast-call argument spilled past the registers.

This PR forces the wrapper's calling convention to SystemV (AAPCS64) on aarch64-apple-darwin, so the wrapper reads stack args at the same 8-byte-aligned offsets V8 writes them. The target signature used to call the user's C function from inside the wrapper still uses the platform default (AppleAarch64), so the user function continues to be invoked per its native ABI.

Why no observable change yet

V8 currently short-circuits fast-API dispatch on Apple silicon with c_signature->ArgumentCount() > 8 (v8/src/compiler/fast-api-calls.cc::CanOptimizeFastSignature) as a workaround for the same alignment bug. With the V8 guard in place, the trampoline never gets a stack-arg call on Apple silicon today, so behaviour is unchanged. This change is the Deno-side half of the fix and keeps the trampoline correct for the day V8 relaxes that restriction.

Upstream V8 issue: https://crbug.com/v8/13171 (chromium:42203110)
Original Deno issue: #15785

The two skipped fast-call assertions for log_many_parameters / add_many_u16 in tests/ffi/testdata/test.js remain gated on darwin+arm64, since V8 still refuses to dispatch the fast path there; the comments are updated to note Deno's side is now correct and the skip can be removed once V8 lifts its guard.

Closes denoland/divybot#321

Test plan

  • cargo check -p deno_ffi builds clean (verified locally on x86_64-linux).
  • CI: cargo test on aarch64-apple-darwin continues to pass (skipped fast-call cases stay skipped).
  • CI: no regression on other targets - fix is gated by cfg!(all(target_os = "macos", target_arch = "aarch64")).

…ple silicon

V8's fast API on arm64 always packs stack arguments into 8-byte slots
(AAPCS64 layout), but Apple silicon's ABI uses natural alignment (e.g.
4-byte slots for i32/f32). Cranelift's default convention on
aarch64-apple-darwin is `AppleAarch64`, so the trampoline wrapper that
V8 invokes would read stack args at the wrong offsets and pick up
garbage as soon as a fast-call argument spilled past the registers.

Force the wrapper's calling convention to `SystemV` (AAPCS64) on
aarch64-apple-darwin so the wrapper reads stack args at the same
8-byte-aligned offsets V8 writes them. The target signature used to
call the user's C function from inside the wrapper still uses the
platform default, so the user function is invoked per its native ABI.

V8 still gates fast-API dispatch with `ArgumentCount() > 8` on Apple
silicon (`fast-api-calls.cc`), so this change has no observable effect
until that upstream guard is relaxed (crbug.com/v8/13171), but it is
the Deno-side half of the fix and keeps the trampoline correct for the
day V8 lifts the restriction.

Closes denoland/orchid#321

Co-Authored-By: Divy Srivastava <[email protected]>
@divybot divybot changed the title [denoland/deno#15785] FFI stack alignment on Apple silicon fix(ext/ffi): match V8 stack-arg layout in turbocall trampoline on Apple silicon May 30, 2026
@littledivy
littledivy merged commit 26b6458 into main May 30, 2026
137 of 138 checks passed
@littledivy
littledivy deleted the orch/divybot-321 branch May 30, 2026 06:38
littledivy pushed a commit to crowlKats/deno that referenced this pull request Jun 10, 2026
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.

2 participants