diff options
author | Aapo Alasuutari <aapo.alasuutari@gmail.com> | 2022-10-20 07:07:37 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-20 09:37:37 +0530 |
commit | e2be70b035459cb534360b72ece4ff2abaa09cd7 (patch) | |
tree | 6be089ecce80843c01cd85cd2ff049d03f9e0955 /ext/ffi/lib.rs | |
parent | 722ea20e860df0a568b5d97734ad8d89aa7382a9 (diff) |
feat(ext/ffi): Make op_ffi_ptr_of fast (#16297)
Makes `op_ffi_ptr_of` fast. One of the tests changed from printing
`false` to `true` as the fast `&[u8]` slice path creates the slice with
a null pointer. Thus the `op_ffi_ptr_of` will now return a null pointer
value whereas previously it returned a dangling pointer value.
Diffstat (limited to 'ext/ffi/lib.rs')
-rw-r--r-- | ext/ffi/lib.rs | 48 |
1 files changed, 16 insertions, 32 deletions
diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs index ae51db34c..3ad75e245 100644 --- a/ext/ffi/lib.rs +++ b/ext/ffi/lib.rs @@ -2063,12 +2063,12 @@ fn op_ffi_call_nonblocking<'scope>( }) } -#[op(v8)] -fn op_ffi_ptr_of<FP, 'scope>( - scope: &mut v8::HandleScope<'scope>, +#[op(fast)] +fn op_ffi_ptr_of<FP>( state: &mut deno_core::OpState, - buf: serde_v8::Value<'scope>, -) -> Result<serde_v8::Value<'scope>, AnyError> + buf: &[u8], + out: &mut [u32], +) -> Result<(), AnyError> where FP: FfiPermissions + 'static, { @@ -2076,34 +2076,18 @@ where let permissions = state.borrow_mut::<FP>(); permissions.check(None)?; - let pointer = if let Ok(value) = - v8::Local::<v8::ArrayBufferView>::try_from(buf.v8_value) - { - let backing_store = value - .buffer(scope) - .ok_or_else(|| { - type_error("Invalid FFI ArrayBufferView, expected data in the buffer") - })? - .get_backing_store(); - let byte_offset = value.byte_offset(); - &backing_store[byte_offset..] as *const _ as *const u8 - } else if let Ok(value) = v8::Local::<v8::ArrayBuffer>::try_from(buf.v8_value) - { - let backing_store = value.get_backing_store(); - &backing_store[..] as *const _ as *const u8 - } else { - return Err(type_error( - "Invalid FFI buffer, expected ArrayBuffer, or ArrayBufferView", - )); - }; + let outptr = out.as_ptr() as *mut usize; + let length = out.len(); + assert!( + length >= (std::mem::size_of::<usize>() / std::mem::size_of::<u32>()) + ); + assert_eq!(outptr as usize % std::mem::size_of::<usize>(), 0); - let integer: v8::Local<v8::Value> = - if pointer as usize > MAX_SAFE_INTEGER as usize { - v8::BigInt::new_from_u64(scope, pointer as u64).into() - } else { - v8::Number::new(scope, pointer as usize as f64).into() - }; - Ok(integer.into()) + // SAFETY: Out buffer was asserted to be at least large enough to hold a usize, and properly aligned. + let out = unsafe { &mut *outptr }; + *out = buf.as_ptr() as usize; + + Ok(()) } unsafe extern "C" fn noop_deleter_callback( |