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/lib.rs | |
parent | 519ed44ebb4bab71c6b80f7c1ef432354654da8c (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.rs | 61 |
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()); |