diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2022-07-28 18:08:22 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-28 18:08:22 +0530 |
commit | ef7bc2e6cc4856a0372086b3ceb7d470508aaa52 (patch) | |
tree | 02045406d0fe21bf77bcb3697ed2e75006aebeed /ext/ffi/00_ffi.js | |
parent | 519ed44ebb4bab71c6b80f7c1ef432354654da8c (diff) |
perf(ext/ffi): use fast api calls for 64bit return types (#15313)
Diffstat (limited to 'ext/ffi/00_ffi.js')
-rw-r--r-- | ext/ffi/00_ffi.js | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/ext/ffi/00_ffi.js b/ext/ffi/00_ffi.js index bc03dfb14..4d77449e8 100644 --- a/ext/ffi/00_ffi.js +++ b/ext/ffi/00_ffi.js @@ -7,9 +7,17 @@ const { BigInt, ObjectDefineProperty, + ArrayPrototypeMap, + Number, + NumberIsSafeInteger, + ArrayPrototypeJoin, ObjectPrototypeIsPrototypeOf, PromisePrototypeThen, TypeError, + Int32Array, + Uint32Array, + BigInt64Array, + Function, } = window.__bootstrap.primordials; function unpackU64(returnValue) { @@ -209,6 +217,10 @@ type === "usize" || type === "isize"; } + function isI64(type) { + return type === "i64" || type === "isize"; + } + class UnsafeCallback { #refcount; #rid; @@ -293,11 +305,11 @@ ); continue; } + const resultType = symbols[symbol].result; + const needsUnpacking = isReturnedAsBigInt(resultType); const isNonBlocking = symbols[symbol].nonblocking; if (isNonBlocking) { - const resultType = symbols[symbol].result; - const needsUnpacking = isReturnedAsBigInt(resultType); ObjectDefineProperty( this.symbols, symbol, @@ -326,6 +338,38 @@ }, ); } + + if (needsUnpacking && !isNonBlocking) { + const call = this.symbols[symbol]; + const parameters = symbols[symbol].parameters; + const vi = new Int32Array(2); + const vui = new Uint32Array(vi.buffer); + const b = new BigInt64Array(vi.buffer); + + const params = ArrayPrototypeJoin( + ArrayPrototypeMap(parameters, (_, index) => `p${index}`), + ", ", + ); + // Make sure V8 has no excuse to not optimize this function. + this.symbols[symbol] = new Function( + "vi", + "vui", + "b", + "call", + "NumberIsSafeInteger", + "Number", + `return function (${params}) { + call(${params}${parameters.length > 0 ? ", " : ""}vi); + ${ + isI64(resultType) + ? `const n1 = Number(b[0])` + : `const n1 = vui[0] + 2 ** 32 * vui[1]` // Faster path for u64 + }; + if (NumberIsSafeInteger(n1)) return n1; + return b[0]; + }`, + )(vi, vui, b, call, NumberIsSafeInteger, Number); + } } } |