@@ -41,10 +41,9 @@ The implementation is split across these files:
4141* ` src/ffi/types.{h,cc} ` parses public FFI signatures and implements
4242 ` IsFastCallEligible() ` , which rejects signatures that the current Fast API
4343 trampolines cannot represent.
44- * ` src/ffi/platforms/arm64.cc ` and ` src/ffi/platforms/x64.cc ` contain the
45- platform trampoline generators. These files follow the contract exposed by
46- ` node_ffi_create_fast_trampoline() ` and release code with
47- ` node_ffi_free_fast_trampoline() ` .
44+ * ` src/ffi/platforms/*.cc ` contain the platform trampoline generators. These
45+ files follow the contract exposed by ` node_ffi_create_fast_trampoline() ` and
46+ release code with ` node_ffi_free_fast_trampoline() ` .
4847* ` src/node_ffi.cc ` decides whether a function gets a Fast API callable,
4948 SharedBuffer callable, or generic callable, and attaches hidden metadata used
5049 by JavaScript wrappers.
@@ -88,8 +87,7 @@ true only on supported architectures when `IsJitMemorySupported()` succeeds.
8887` IsJitMemorySupported() ` runs a one-time self-test:
8988
9089* Map one writable anonymous page.
91- * Write a minimal return instruction (` 0xD65F03C0 ` on AArch64, ` 0xC3 ` on
92- x86\_ 64).
90+ * Write a minimal return instruction for the current architecture.
9391* Flush the instruction cache where required.
9492* Try to transition the page to read/execute with `mprotect(PROT_READ |
9593 PROT_EXEC)`.
@@ -99,8 +97,8 @@ The probe deliberately does not execute the generated instruction. Executing a
9997freshly written capability probe could terminate the process on systems that
10098block generated code. The real trampoline emitter performs the same writable to
10199executable transition when creating a callable trampoline and falls back when it
102- is rejected. Windows currently returns false because the branch does not yet
103- have a Win64 trampoline emitter or ` VirtualAlloc ` -based JIT memory support .
100+ is rejected. Windows uses ` VirtualAlloc ` , ` VirtualProtect ` , and
101+ ` FlushInstructionCache ` for the same probe .
104102
105103## Signature Eligibility
106104
@@ -110,8 +108,8 @@ keeps unsupported cases out of the trampoline emitters and lets
110108
111109Eligibility requires:
112110
113- * A supported platform emitter: AArch64 or x86\_ 64 SysV. Win64 is currently
114- ineligible .
111+ * A supported platform emitter: AArch64, x86\_ 64 SysV, Win64 x64, PPC64LE
112+ ELFv2, LoongArch64, RISC-V 64, or s390x .
115113* A return type that is numeric, pointer, or ` void ` .
116114* Argument types that are numeric or pointer. ` void ` cannot be an argument.
117115* No ` function ` typed argument or return value.
@@ -141,6 +139,56 @@ x86\_64 SysV eligibility mirrors `src/ffi/platforms/x64.cc`:
141139 incoming GP count is capped at 5 and buffer-shaped arguments cannot coexist
142140 with FP arguments.
143141
142+ Win64 x64 eligibility mirrors the conservative Windows emitter in
143+ ` src/ffi/platforms/x64.cc ` :
144+
145+ * The JavaScript receiver occupies the first positional register slot.
146+ * Public arguments are shifted from positions 1..3 into positions 0..2.
147+ * Integer and FP arguments are handled according to their positional Win64
148+ register slots.
149+ * Only scalar register-only signatures with at most three public arguments are
150+ currently eligible.
151+ * Buffer-shaped arguments and stack-passed arguments fall back.
152+
153+ PPC64LE eligibility mirrors ` src/ffi/platforms/ppc64.cc ` :
154+
155+ * ` r3 ` is occupied by V8's receiver, so user GP arguments arrive in ` r4..r10 ` .
156+ * FP arguments use FPRs and are not shifted by the receiver slot.
157+ * The generated trampoline shifts only GP registers and tail-branches to the
158+ target through ` ctr ` , with the target address in ` r12 ` for ELFv2 global entry.
159+ * Only scalar register-only signatures are currently eligible.
160+ * Buffer-shaped arguments, stack-passed arguments, narrow returns, and PPC64BE
161+ platforms fall back. AIX/PPC64BE is intentionally a non-target for the current
162+ Fast FFI trampoline work because its ABI/linkage shape needs separate design.
163+
164+ LoongArch64 eligibility mirrors ` src/ffi/platforms/loong64.cc ` :
165+
166+ * ` a0 ` is occupied by V8's receiver, so user GP arguments arrive in ` a1..a7 ` .
167+ * FP arguments use ` fa0..fa7 ` and are not shifted by the receiver slot.
168+ * The generated trampoline shifts only GP registers and tail-branches to the
169+ target through ` jirl ` .
170+ * Only scalar register-only signatures are currently eligible.
171+ * Buffer-shaped arguments, stack-passed arguments, and narrow returns fall back.
172+
173+ RISC-V 64 eligibility mirrors ` src/ffi/platforms/riscv64.cc ` :
174+
175+ * ` a0 ` is occupied by V8's receiver, so user GP arguments arrive in ` a1..a7 ` .
176+ * FP arguments use ` fa0..fa7 ` and are not shifted by the receiver slot.
177+ * The generated trampoline shifts only GP registers and tail-branches to the
178+ target through ` jalr ` .
179+ * Only scalar register-only signatures are currently eligible.
180+ * Buffer-shaped arguments, stack-passed arguments, and narrow returns fall back.
181+
182+ s390x eligibility mirrors ` src/ffi/platforms/s390x.cc ` :
183+
184+ * ` r2 ` is occupied by V8's receiver, so user GP arguments arrive in ` r3..r6 ` .
185+ * FP arguments use ` f0 ` , ` f2 ` , ` f4 ` , and ` f6 ` and are not shifted by the receiver
186+ slot.
187+ * The generated trampoline shifts only GP registers and tail-branches to the
188+ target through ` br ` .
189+ * Only scalar register-only signatures are currently eligible.
190+ * Buffer-shaped arguments, stack-passed arguments, and narrow returns fall back.
191+
144192The native trampoline generator still repeats its own register checks. The
145193eligibility function is the early, centralized rejection point; the generator
146194checks are a defense against direct or future callers.
@@ -395,9 +443,22 @@ Important limits are:
395443* No stack arguments in the current AArch64 trampoline.
396444* At most one stack-loaded scalar GP argument in the current x86\_ 64 SysV
397445 trampoline.
446+ * No stack arguments or buffer-shaped arguments in the current Win64 x64
447+ trampoline.
448+ * No stack arguments, buffer-shaped arguments, or narrow returns in the current
449+ PPC64LE trampoline.
450+ * No stack arguments, buffer-shaped arguments, or narrow returns in the current
451+ LoongArch64, RISC-V 64, and s390x trampolines.
398452* No mixed buffer-shaped and FP arguments.
399453* No ` function ` argument or return type in the Fast API path.
400454
455+ Linux x86 and armv7 are experimental Node.js platforms, but the current Fast FFI
456+ trampoline model remains 64-bit only. They continue to use SharedBuffer or
457+ generic libffi fallback paths. Linux s390x is a Tier 2 Node.js platform, but
458+ bundled FFI is not currently enabled for that target; if built with
459+ ` --shared-ffi ` , scalar register-only Fast API FFI can use the s390x emitter. AIX
460+ PPC64BE is intentionally not covered by this implementation.
461+
401462These are optimization boundaries, not public FFI signature boundaries. User
402463code can still call supported public FFI signatures through fallback paths.
403464
0 commit comments