summaryrefslogtreecommitdiff
path: root/ext/ffi/00_ffi.js
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2022-07-28 18:08:22 +0530
committerGitHub <noreply@github.com>2022-07-28 18:08:22 +0530
commitef7bc2e6cc4856a0372086b3ceb7d470508aaa52 (patch)
tree02045406d0fe21bf77bcb3697ed2e75006aebeed /ext/ffi/00_ffi.js
parent519ed44ebb4bab71c6b80f7c1ef432354654da8c (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.js48
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);
+ }
}
}