Commit Graph
11 Commits
Author SHA1 Message Date
Trivikram Kamat c55eb4acb1 ffi: reject fast calls after library close
Optimized Fast API calls bypass InvokeFunction and can jump directly to
a symbol after DynamicLibrary::close() unloads its library.

Check the function's closed state in the AArch64 and SysV x64
trampolines before entering the target. If the library is closed,
schedule ERR_FFI_LIBRARY_CLOSED and return without calling the symbol.

Keep the JavaScript guard on platforms without a native trampoline guard
and for signatures that already require argument conversion or
validation. This keeps raw scalar fast calls close to their original
performance on supported platforms.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: codex:gpt-5.6-sol
PR-URL: https://github.com/nodejs/node/pull/64860
Fixes: https://github.com/nodejs/node/issues/64854
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-08-02 14:54:42 +00:00
Trivikram Kamat f85fdabc47 ffi: fix optimized buffer conversions
Preserve pointer-like argument conversions for buffer and arraybuffer
signatures after Fast API optimization. Keep memory-backed arguments
on the specialized native fast path.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: openai:gpt-5.6-sol
PR-URL: https://github.com/nodejs/node/pull/64639
Fixes: https://github.com/nodejs/node/issues/64638
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Aviv Keller <me@aviv.sh>
2026-07-30 18:57:47 +00:00
Trivikram Kamat 00917ba54c ffi: evaluate function signatures once
Function signatures were read by the native implementation and then
read again while creating JavaScript wrappers. Accessors, proxies,
or mutations could therefore produce different native and JavaScript
signatures.

Build wrappers from signature metadata captured by native code instead.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: openai:gpt-5.6-sol
PR-URL: https://github.com/nodejs/node/pull/64559
Fixes: https://github.com/nodejs/node/issues/64558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
2026-07-20 05:24:57 +00:00
Paolo Insogna 3e8aa7de27 ffi: add getCurrentEventLoop
Signed-off-by: Paolo Insogna <paolo@cowtech.it>
Assisted-By: OpenAI:GPT-5.5 <openai/gpt-5.5>
PR-URL: https://github.com/nodejs/node/pull/64323
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Edy Silva <edigleyssonsilva@gmail.com>
2026-07-08 13:24:50 +00:00
Paolo InsognaandBryan English 3e55527eef ffi: add experimental fast FFI call API for AArch64 and x86_64
Add fast API trampolines for AArch64 and x86_64.

IsJitMemorySupported() maps an RW page, writes a ret instruction
(0xD65F03C0 AArch64 / 0xC3 x86_64), and mprotects it to RX. A
successful RX transition is treated as the support signal. The page is
deliberately not executed: this check may run during normal operation
(when an FFI function is first created), and executing freshly written
code from a capability probe could SIGSEGV/SIGKILL the process on
systems that block executable memory. The real trampoline emitter
performs the same mprotect at creation time and falls back to libffi
when it is rejected.

The result is computed once via std::call_once and cached for the
lifetime of the process, so concurrent callers never observe a
provisional value.

Wired into CreateFastFFIMetadata() for early nullptr bail-out when
JIT memory is unavailable.

Windows stub returns false (no trampolines yet on this branch).

IsFastCallEligible() validates at parse time whether a signature can
use the fast-call path, covering:

- Return and argument type eligibility (numeric, pointer; no structs)
- Argument count cap (8, matching V8 fast-call limit)
- Per-ABI register pressure limits that mirror the trampoline emitters
  (AArch64 and x86_64 SysV). Platforms without an emitter, including
  Win64, are reported ineligible.
- Buffer and float args cannot coexist, and buffer args additionally
  consume an extra GP register slot on both supported ABIs.

The arg/arg-name lengths are checked before the per-arg loop so a
malformed signature cannot index out of bounds.

Returns nullptr from CreateFastFFIMetadata() for ineligible signatures,
falling back to libffi.

Co-authored-by: Bryan English <bryan@bryanenglish.com>
Signed-off-by: Paolo Insogna <paolo@cowtech.it>
Signed-off-by: Bryan English <bryan@bryanenglish.com>
Assisted-By: OpenAI:GPT-5.5 <openai/gpt-5.5>
PR-URL: https://github.com/nodejs/node/pull/63068
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Bryan English <bryan@bryanenglish.com>
2026-06-16 09:35:02 +00:00
René ca3766568e ffi: move DynamicLibrary disposer to native layer
Signed-off-by: Renegade334 <contact.9a5d6388@renegade334.me.uk>
PR-URL: https://github.com/nodejs/node/pull/63459
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
2026-05-22 17:01:28 +00:00
Rafael Gonzaga dc99d18597 lib: handle --permission-audit when propagating flags
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: https://github.com/nodejs/node/pull/63047
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-05-06 19:21:11 +00:00
Matteo Collina 61db2609e3 ffi: support Symbol.dispose on DynamicLibrary
Install [Symbol.dispose]() on DynamicLibrary.prototype (calling close())
and on the object returned from ffi.dlopen(), so both can be used with
the `using` declaration for automatic cleanup.

Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: https://github.com/nodejs/node/pull/62925
Reviewed-By: Bryan English <bryan@bryanenglish.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
2026-04-29 11:13:47 +00:00
Bryan English 1ad06ff9a7 ffi: add shared-buffer fast path for numeric and pointer signatures
Adds an ArrayBuffer-based invocation path for FFI functions whose
signatures are composed entirely of numeric types (i8..i64, u8..u64,
f32, f64, bool, char) and/or pointer types. The JS wrapper packs
arguments directly into a per-function AB via primordial DataView
setters and the C++ invoker (`InvokeFunctionSB`) reads them without
going through V8's `FunctionCallbackInfo`. Results are returned the same
way.

Pointer arguments use runtime dispatch: BigInt, null, and undefined take
the fast path, while Buffer, ArrayBuffer, ArrayBufferView, and String
fall back transparently to the classic `InvokeFunction` path via a
stashed `_invokeSlow` function. Signatures containing
non-numeric/non-pointer types also bypass the fast path.

The fast path is disabled on big-endian platforms.

Callers do not opt in, and the fast path is transparent in every way
users should rely on. One observable change: function wrappers returned
by `library.getFunction`, `library.getFunctions`, and `library.functions`
now have `.length` equal to the declared parameter count rather than
`0`. Code that relied on the previous value will need to be updated.

Adds microbenchmarks covering the common FFI call shapes so future
changes to the invoker can be evaluated:

- add-i32.js: 2-arg integer
- add-f64.js: 2-arg float
- many-args.js: 6-arg integer
- pointer-bigint.js: 1-arg pointer (BigInt)
- sum-buffer.js: pointer + length (Buffer)

A `common.js` helper resolves the fixture-library path from
`test/ffi/fixture_library` without pulling in the test harness, and
throws a clear message if the fixture hasn't been built yet.

Also adds `sum_6_i32` to the fixture library for the many-args case.

Signed-off-by: Bryan English <bryan@bryanenglish.com>
PR-URL: https://github.com/nodejs/node/pull/62918
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
2026-04-28 14:55:52 +02:00
Paolo Insogna 14e16db1bf lib: add new methods and error codes
Signed-off-by: Paolo Insogna <paolo@cowtech.it>
PR-URL: https://github.com/nodejs/node/pull/62762
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Bryan English <bryan@bryanenglish.com>
2026-04-19 18:39:01 +00:00
cjihrigandPaolo Insogna d0fa608c07 lib,src,test,doc: add node:ffi module
PR-URL: https://github.com/nodejs/node/pull/62072
Co-authored-by: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Bryan English <bryan@bryanenglish.com>
2026-04-14 10:44:30 +01:00