summaryrefslogtreecommitdiff
path: root/ext/ffi/lib.rs
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/lib.rs
parent519ed44ebb4bab71c6b80f7c1ef432354654da8c (diff)
perf(ext/ffi): use fast api calls for 64bit return types (#15313)
Diffstat (limited to 'ext/ffi/lib.rs')
-rw-r--r--ext/ffi/lib.rs61
1 files changed, 53 insertions, 8 deletions
diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs
index 05015a45a..ec80d4786 100644
--- a/ext/ffi/lib.rs
+++ b/ext/ffi/lib.rs
@@ -752,9 +752,8 @@ impl From<&NativeType> for fast_api::Type {
}
}
-#[cfg(not(target_os = "windows"))]
-fn is_fast_api_rv(rv: NativeType) -> bool {
- !matches!(
+fn needs_unwrap(rv: NativeType) -> bool {
+ matches!(
rv,
NativeType::Function
| NativeType::Pointer
@@ -765,6 +764,10 @@ fn is_fast_api_rv(rv: NativeType) -> bool {
)
}
+fn is_i64(rv: NativeType) -> bool {
+ matches!(rv, NativeType::I64 | NativeType::ISize)
+}
+
// Create a JavaScript function for synchronous FFI call to
// the given symbol.
fn make_sync_fn<'s>(
@@ -780,8 +783,12 @@ fn make_sync_fn<'s>(
#[cfg(not(target_os = "windows"))]
let mut fast_allocations: Option<*mut ()> = None;
#[cfg(not(target_os = "windows"))]
- if !sym.can_callback && is_fast_api_rv(sym.result_type) {
- let ret = fast_api::Type::from(&sym.result_type);
+ if !sym.can_callback {
+ let needs_unwrap = needs_unwrap(sym.result_type);
+ let ret = match needs_unwrap {
+ true => fast_api::Type::Void,
+ false => fast_api::Type::from(&sym.result_type),
+ };
let mut args = sym
.parameter_types
@@ -790,6 +797,9 @@ fn make_sync_fn<'s>(
.collect::<Vec<_>>();
// recv
args.insert(0, fast_api::Type::V8Value);
+ if needs_unwrap {
+ args.push(fast_api::Type::TypedArray(fast_api::CType::Int32));
+ }
let symbol_trampoline =
jit_trampoline::gen_trampoline(sym.clone()).expect("gen_trampoline");
fast_ffi_templ = Some(FfiFastCallTemplate {
@@ -810,11 +820,46 @@ fn make_sync_fn<'s>(
// SAFETY: The pointer will not be deallocated until the function is
// garbage collected.
let symbol = unsafe { &*(external.value() as *const Symbol) };
+ let needs_unwrap = match needs_unwrap(symbol.result_type) {
+ true => Some(args.get(symbol.parameter_types.len() as i32)),
+ false => None,
+ };
match ffi_call_sync(scope, args, symbol) {
Ok(result) => {
- // SAFETY: Same return type declared to libffi; trust user to have it right beyond that.
- let result = unsafe { result.to_v8(scope, symbol.result_type) };
- rv.set(result.v8_value);
+ match needs_unwrap {
+ Some(v) => {
+ let view: v8::Local<v8::ArrayBufferView> = v.try_into().unwrap();
+ let backing_store =
+ view.buffer(scope).unwrap().get_backing_store();
+
+ if is_i64(symbol.result_type) {
+ // SAFETY: v8::SharedRef<v8::BackingStore> is similar to Arc<[u8]>,
+ // it points to a fixed continuous slice of bytes on the heap.
+ let bs = unsafe {
+ &mut *(&backing_store[..] as *const _ as *mut [u8]
+ as *mut i64)
+ };
+ // SAFETY: We already checked that type == I64
+ let value = unsafe { result.i64_value };
+ *bs = value;
+ } else {
+ // SAFETY: v8::SharedRef<v8::BackingStore> is similar to Arc<[u8]>,
+ // it points to a fixed continuous slice of bytes on the heap.
+ let bs = unsafe {
+ &mut *(&backing_store[..] as *const _ as *mut [u8]
+ as *mut u64)
+ };
+ // SAFETY: We checked that type == U64
+ let value = unsafe { result.u64_value };
+ *bs = value;
+ }
+ }
+ None => {
+ // SAFETY: Same return type declared to libffi; trust user to have it right beyond that.
+ let result = unsafe { result.to_v8(scope, symbol.result_type) };
+ rv.set(result.v8_value);
+ }
+ }
}
Err(err) => {
deno_core::_ops::throw_type_error(scope, err.to_string());