From 70e18db2ffdf4553daf3ae1b2f66292c351cd176 Mon Sep 17 00:00:00 2001 From: snek Date: Tue, 13 Aug 2024 18:15:34 +0200 Subject: [PATCH] update fast calls api (#1564) --- benches/function.rs | 16 +- src/binding.cc | 61 +----- src/binding.hpp | 4 + src/binding.rs | 1 + src/external_references.rs | 2 + src/fast_api.rs | 404 +++++++++++++------------------------ src/template.rs | 62 +----- tests/test_api.rs | 284 +++++++++++++++++--------- 8 files changed, 359 insertions(+), 475 deletions(-) diff --git a/benches/function.rs b/benches/function.rs index 4116221f..d0d8362c 100644 --- a/benches/function.rs +++ b/benches/function.rs @@ -65,12 +65,14 @@ fn main() { fn fast_fn() -> i32 { 42 } - const FAST_CALL: v8::fast_api::FastFunction = - v8::fast_api::FastFunction::new( - &[v8::fast_api::Type::V8Value], - v8::fast_api::CType::Int32, - fast_fn as _, - ); + const FAST_CALL: v8::fast_api::CFunction = v8::fast_api::CFunction::new( + fast_fn as _, + &v8::fast_api::CFunctionInfo::new( + v8::fast_api::Type::Int32.scalar(), + &[v8::fast_api::Type::V8Value.scalar()], + v8::fast_api::Int64Representation::Number, + ), + ); let template = v8::FunctionTemplate::builder( |scope: &mut v8::HandleScope, _: v8::FunctionCallbackArguments, @@ -78,7 +80,7 @@ fn main() { rv.set(v8::Integer::new(scope, 42).into()); }, ) - .build_fast(scope, &FAST_CALL, None, None, None); + .build_fast(scope, &[FAST_CALL]); let name = v8::String::new(scope, "new_fast").unwrap(); let value = template.get_function(scope).unwrap(); diff --git a/src/binding.cc b/src/binding.cc index 82554363..29dad040 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -2247,70 +2247,17 @@ const v8::Signature* v8__Signature__New(v8::Isolate* isolate, return local_to_ptr(v8::Signature::New(isolate, ptr_to_local(templ))); } -v8::CTypeInfo* v8__CTypeInfo__New(v8::CTypeInfo::Type ty) { - std::unique_ptr u = - std::make_unique(v8::CTypeInfo(ty)); - return u.release(); -} - -void v8__CTypeInfo__DELETE(v8::CTypeInfo* self) { delete self; } - -struct CTypeSequenceType { - v8::CTypeInfo::Type c_type; - v8::CTypeInfo::SequenceType sequence_type; -}; - -v8::CTypeInfo* v8__CTypeInfo__New__From__Slice(unsigned int len, - CTypeSequenceType* ty) { - v8::CTypeInfo* v = (v8::CTypeInfo*)malloc(sizeof(v8::CTypeInfo) * len); - for (size_t i = 0; i < len; i += 1) { - v[i] = v8::CTypeInfo(ty[i].c_type, ty[i].sequence_type); - } - return v; -} - -v8::CFunctionInfo* v8__CFunctionInfo__New( - const v8::CTypeInfo& return_info, unsigned int args_len, - v8::CTypeInfo* args_info, v8::CFunctionInfo::Int64Representation repr) { - std::unique_ptr info = std::make_unique( - v8::CFunctionInfo(return_info, args_len, args_info, repr)); - return info.release(); -} - -void v8__CFunctionInfo__DELETE(v8::CFunctionInfo* self) { delete self; } - const v8::FunctionTemplate* v8__FunctionTemplate__New( v8::Isolate* isolate, v8::FunctionCallback callback, const v8::Value* data_or_null, const v8::Signature* signature_or_null, int length, v8::ConstructorBehavior constructor_behavior, - v8::SideEffectType side_effect_type, void* func_ptr1, - const v8::CFunctionInfo* c_function_info1, void* func_ptr2, - const v8::CFunctionInfo* c_function_info2) { - // Support upto 2 overloads. V8 requires TypedArray to have a - // v8::Array overload. - if (func_ptr1) { - if (func_ptr2 == nullptr) { - const v8::CFunction o[] = {v8::CFunction(func_ptr1, c_function_info1)}; - auto overload = v8::MemorySpan{o, 1}; - return local_to_ptr(v8::FunctionTemplate::NewWithCFunctionOverloads( - isolate, callback, ptr_to_local(data_or_null), - ptr_to_local(signature_or_null), length, constructor_behavior, - side_effect_type, overload)); - } else { - const v8::CFunction o[] = {v8::CFunction(func_ptr1, c_function_info1), - v8::CFunction(func_ptr2, c_function_info2)}; - auto overload = v8::MemorySpan{o, 2}; - return local_to_ptr(v8::FunctionTemplate::NewWithCFunctionOverloads( - isolate, callback, ptr_to_local(data_or_null), - ptr_to_local(signature_or_null), length, constructor_behavior, - side_effect_type, overload)); - } - } - auto overload = v8::MemorySpan{}; + v8::SideEffectType side_effect_type, const v8::CFunction* c_functions, + size_t c_functions_len) { + v8::MemorySpan overloads{c_functions, c_functions_len}; return local_to_ptr(v8::FunctionTemplate::NewWithCFunctionOverloads( isolate, callback, ptr_to_local(data_or_null), ptr_to_local(signature_or_null), length, constructor_behavior, - side_effect_type, overload)); + side_effect_type, overloads)); } const v8::Function* v8__FunctionTemplate__GetFunction( diff --git a/src/binding.hpp b/src/binding.hpp index 6bba1799..b028e704 100644 --- a/src/binding.hpp +++ b/src/binding.hpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -28,3 +29,6 @@ static size_t v8__TypedArray__kMaxByteLength = v8::TypedArray::kMaxByteLength; static size_t v8__##name##__kMaxLength = v8::name::kMaxLength; EACH_TYPED_ARRAY(TYPED_ARRAY_MAX_LENGTH) #undef TYPED_ARRAY_MAX_LENGTH + +using v8__CFunction = v8::CFunction; +using v8__CFunctionInfo = v8::CFunctionInfo; diff --git a/src/binding.rs b/src/binding.rs index 3ef84eac..70f4b6b0 100644 --- a/src/binding.rs +++ b/src/binding.rs @@ -1,3 +1,4 @@ +#![allow(unused)] #![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] diff --git a/src/external_references.rs b/src/external_references.rs index e36257ad..ba944b2e 100644 --- a/src/external_references.rs +++ b/src/external_references.rs @@ -1,5 +1,6 @@ // Copyright 2019-2021 the Deno authors. All rights reserved. MIT license. +use crate::fast_api::CFunctionInfo; use crate::support::intptr_t; use crate::FunctionCallback; use crate::IndexedDefinerCallback; @@ -33,6 +34,7 @@ pub union ExternalReference<'s> { pub enumerator: PropertyEnumeratorCallback<'s>, pub message: MessageCallback, pub pointer: *mut c_void, + pub type_info: *const CFunctionInfo, } impl<'s> Debug for ExternalReference<'s> { diff --git a/src/fast_api.rs b/src/fast_api.rs index d75520cc..7c69b8e6 100644 --- a/src/fast_api.rs +++ b/src/fast_api.rs @@ -1,205 +1,138 @@ -use crate::support::Opaque; +use std::ffi::c_void; + +use crate::binding::*; use crate::Isolate; use crate::Local; use crate::Value; -use std::{ - ffi::c_void, - mem::align_of, - ptr::{self, NonNull}, -}; -extern "C" { - fn v8__CTypeInfo__New(ty: CType) -> *mut CTypeInfo; - fn v8__CTypeInfo__New__From__Slice( - len: usize, - tys: *const CTypeSequenceInfo, - ) -> *mut CTypeInfo; - fn v8__CTypeInfo__DELETE(this: *mut CTypeInfo); - fn v8__CFunctionInfo__New( - return_info: *const CTypeInfo, - args_len: usize, - args_info: *const CTypeInfo, - repr: Int64Representation, - ) -> *mut CFunctionInfo; - fn v8__CFunctionInfo__DELETE(this: *mut CFunctionInfo); +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct CFunction(v8__CFunction); + +impl CFunction { + pub const fn new(address: *const c_void, type_info: &CFunctionInfo) -> Self { + Self(v8__CFunction { + address_: address, + type_info_: &type_info.0, + }) + } + + pub const fn address(&self) -> *const c_void { + self.0.address_ + } + + pub const fn type_info(&self) -> &CFunctionInfo { + // SAFETY: We initialize this field with a reference. and + // the layout of CFunctionInfo is identical to v8_CFunctionInfo. + unsafe { &*(self.0.type_info_ as *const CFunctionInfo) } + } } -#[repr(C)] -#[derive(Default)] -pub struct CFunctionInfo(Opaque); - -#[repr(C)] -#[derive(Default)] -pub struct CFunction(Opaque); +#[repr(transparent)] +pub struct CFunctionInfo(v8__CFunctionInfo); impl CFunctionInfo { - #[inline(always)] - pub unsafe fn new( - args: *const CTypeInfo, - args_len: usize, - return_type: *const CTypeInfo, + /// Construct a struct to hold a CFunction's type information. + /// |return_info| describes the function's return type. + /// |arg_info| is an array of |arg_count| CTypeInfos describing the + /// arguments. Only the last argument may be of the special type + /// CTypeInfo::kCallbackOptionsType. + pub const fn new( + return_info: CTypeInfo, + arg_info: &[CTypeInfo], repr: Int64Representation, - ) -> NonNull { - NonNull::new_unchecked(v8__CFunctionInfo__New( - return_type, - args_len, - args, - repr, - )) + ) -> Self { + Self(v8__CFunctionInfo { + arg_count_: arg_info.len() as _, + arg_info_: arg_info.as_ptr() as _, + repr_: repr as _, + return_info_: return_info.0, + }) } } -impl Drop for CFunctionInfo { - fn drop(&mut self) { - unsafe { v8__CFunctionInfo__DELETE(self) }; - } +#[derive(Clone, Copy)] +#[repr(u8)] +pub enum Int64Representation { + /// Use numbers to represent 64 bit integers. + Number = v8_CFunctionInfo_Int64Representation_kNumber, + /// Use BigInts to represent 64 bit integers. + BigInt = v8_CFunctionInfo_Int64Representation_kBigInt, } -#[repr(C)] -#[derive(Debug)] -pub struct CTypeInfo(Opaque); +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct CTypeInfo(v8_CTypeInfo); impl CTypeInfo { - #[inline(always)] - pub fn new(ty: CType) -> NonNull { - unsafe { NonNull::new_unchecked(v8__CTypeInfo__New(ty)) } - } - - pub fn new_from_slice(types: &[Type]) -> NonNull { - let mut structs = vec![]; - - for type_ in types.iter() { - structs.push(type_.into()) - } - - unsafe { - NonNull::new_unchecked(v8__CTypeInfo__New__From__Slice( - structs.len(), - structs.as_ptr(), - )) - } + pub const fn new( + r#type: Type, + sequence_type: SequenceType, + flags: Flags, + ) -> Self { + Self(v8_CTypeInfo { + flags_: flags.bits(), + sequence_type_: sequence_type as _, + type_: r#type as _, + }) } } -impl Drop for CTypeInfo { - fn drop(&mut self) { - unsafe { v8__CTypeInfo__DELETE(self) }; - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy)] #[repr(u8)] -pub enum SequenceType { - Scalar, - /// sequence - IsSequence, - /// TypedArray of T or any ArrayBufferView if T is void - IsTypedArray, - /// ArrayBuffer - IsArrayBuffer, -} - -#[derive(Clone, Copy, Debug)] -#[repr(u8)] -#[non_exhaustive] -pub enum CType { - Void = 0, - Bool, - Uint8, - Int32, - Uint32, - Int64, - Uint64, - Float32, - Float64, - Pointer, - V8Value, - SeqOneByteString, - // https://github.com/v8/v8/blob/492a32943bc34a527f42df2ae15a77154b16cc84/include/v8-fast-api-calls.h#L264-L267 - // kCallbackOptionsType is not part of the Type enum - // because it is only used internally. Use value 255 that is larger - // than any valid Type enum. +pub enum Type { + Void = v8_CTypeInfo_Type_kVoid, + Bool = v8_CTypeInfo_Type_kBool, + Uint8 = v8_CTypeInfo_Type_kUint8, + Int32 = v8_CTypeInfo_Type_kInt32, + Uint32 = v8_CTypeInfo_Type_kUint32, + Int64 = v8_CTypeInfo_Type_kInt64, + Uint64 = v8_CTypeInfo_Type_kUint64, + Float32 = v8_CTypeInfo_Type_kFloat32, + Float64 = v8_CTypeInfo_Type_kFloat64, + Pointer = v8_CTypeInfo_Type_kPointer, + V8Value = v8_CTypeInfo_Type_kV8Value, + SeqOneByteString = v8_CTypeInfo_Type_kSeqOneByteString, + ApiObject = v8_CTypeInfo_Type_kApiObject, + Any = v8_CTypeInfo_Type_kAny, CallbackOptions = 255, } -#[derive(Clone, Copy, Debug)] -#[non_exhaustive] -pub enum Type { - Void, - Bool, - Uint8, - Int32, - Uint32, - Int64, - Uint64, - Float32, - Float64, - Pointer, - V8Value, - SeqOneByteString, - CallbackOptions, - Sequence(CType), - TypedArray(CType), - ArrayBuffer(CType), -} +impl Type { + pub const fn scalar(self) -> CTypeInfo { + CTypeInfo::new(self, SequenceType::Scalar, Flags::empty()) + } -impl From<&Type> for CType { - fn from(ty: &Type) -> CType { - match ty { - Type::Void => CType::Void, - Type::Bool => CType::Bool, - Type::Uint8 => CType::Uint8, - Type::Int32 => CType::Int32, - Type::Uint32 => CType::Uint32, - Type::Int64 => CType::Int64, - Type::Uint64 => CType::Uint64, - Type::Float32 => CType::Float32, - Type::Float64 => CType::Float64, - Type::Pointer => CType::Pointer, - Type::V8Value => CType::V8Value, - Type::SeqOneByteString => CType::SeqOneByteString, - Type::CallbackOptions => CType::CallbackOptions, - Type::Sequence(ty) => *ty, - Type::TypedArray(ty) => *ty, - Type::ArrayBuffer(ty) => *ty, - } + pub const fn typed_array(self) -> CTypeInfo { + CTypeInfo::new(self, SequenceType::IsTypedArray, Flags::empty()) } } -impl From<&Type> for SequenceType { - fn from(ty: &Type) -> SequenceType { - match ty { - Type::Sequence(_) => SequenceType::IsSequence, - Type::TypedArray(_) => SequenceType::IsTypedArray, - Type::ArrayBuffer(_) => SequenceType::IsArrayBuffer, - _ => SequenceType::Scalar, - } +#[derive(Clone, Copy)] +#[repr(u8)] +pub enum SequenceType { + Scalar = v8_CTypeInfo_SequenceType_kScalar, + /// sequence + IsSequence = v8_CTypeInfo_SequenceType_kIsSequence, + /// TypedArray of T or any ArrayBufferView if T is void + IsTypedArray = v8_CTypeInfo_SequenceType_kIsTypedArray, + /// ArrayBuffer + IsArrayBuffer = v8_CTypeInfo_SequenceType_kIsArrayBuffer, +} + +bitflags::bitflags! { + pub struct Flags: u8 { + /// Must be an ArrayBuffer or TypedArray + const AllowShared = v8_CTypeInfo_Flags_kAllowSharedBit; + /// T must be integral + const EnforceRange = v8_CTypeInfo_Flags_kEnforceRangeBit; + /// T must be integral + const Clamp = v8_CTypeInfo_Flags_kClampBit; + /// T must be float or double + const IsRestricted = v8_CTypeInfo_Flags_kIsRestrictedBit; } } -impl From<&Type> for CTypeSequenceInfo { - fn from(ty: &Type) -> CTypeSequenceInfo { - CTypeSequenceInfo { - c_type: ty.into(), - sequence_type: ty.into(), - } - } -} - -#[repr(C)] -struct CTypeSequenceInfo { - c_type: CType, - sequence_type: SequenceType, -} - -#[repr(C)] -pub union FastApiCallbackData<'a> { - /// `data_ptr` allows for default constructing FastApiCallbackOptions. - pub data_ptr: *mut c_void, - /// The `data` passed to the FunctionTemplate constructor, or `undefined`. - pub data: Local<'a, Value>, -} - /// A struct which may be passed to a fast call callback, like so /// ```c /// void FastMethodWithOptions(int param, FastApiCallbackOptions& options); @@ -217,7 +150,8 @@ pub struct FastApiCallbackOptions<'a> { /// fallback conditions are checked, because otherwise executing the slow /// callback might produce visible side-effects twice. pub fallback: bool, - pub data: FastApiCallbackData<'a>, + /// The `data` passed to the FunctionTemplate constructor, or `undefined`. + pub data: Local<'a, Value>, /// When called from WebAssembly, a view of the calling module's memory. pub wasm_memory: *const FastApiTypedArray, } @@ -235,8 +169,45 @@ pub struct FastApiTypedArray { data: *mut T, } +impl FastApiTypedArray { + /// Performs an unaligned-safe read of T from the underlying data. + #[inline(always)] + pub const fn get(&self, index: usize) -> T { + debug_assert!(index < self.length); + // SAFETY: src is valid for reads, and is a valid value for T + unsafe { std::ptr::read_unaligned(self.data.add(index)) } + } + + /// Returns a slice pointing to the underlying data if safe to do so. + #[inline(always)] + pub fn get_storage_if_aligned(&self) -> Option<&mut [T]> { + // V8 may provide an invalid or null pointer when length is zero, so we just + // ignore that value completely and create an empty slice in this case. + if self.length == 0 { + return Some(&mut []); + } + // Ensure that we never return an unaligned or null buffer + if self.data.is_null() || (self.data as usize) % align_of::() != 0 { + return None; + } + Some(unsafe { std::slice::from_raw_parts_mut(self.data, self.length) }) + } +} + +/// Any TypedArray. It uses kTypedArrayBit with base type void +/// Overloaded args of ArrayBufferView and TypedArray are not supported +/// (for now) because the generic “any” ArrayBufferView doesn’t have its +/// own instance type. It could be supported if we specify that +/// TypedArray always has precedence over the generic ArrayBufferView, +/// but this complicates overload resolution. +#[repr(C)] +pub struct FastApiArrayBufferView { + pub data: *mut c_void, + pub byte_length: usize, +} + // FastApiOneByteString is an alias for SeqOneByteString and the type is widely used in deno_core. -#[allow(dead_code)] +#[allow(unused)] #[repr(C)] pub struct FastApiOneByteString { data: *const u8, @@ -256,88 +227,3 @@ impl FastApiOneByteString { unsafe { std::slice::from_raw_parts(self.data, self.length as usize) } } } - -impl FastApiTypedArray { - /// Performs an unaligned-safe read of T from the underlying data. - #[inline(always)] - pub const fn get(&self, index: usize) -> T { - debug_assert!(index < self.length); - // SAFETY: src is valid for reads, and is a valid value for T - unsafe { ptr::read_unaligned(self.data.add(index)) } - } - - /// Given a pointer to a `FastApiTypedArray`, returns a slice pointing to the - /// data if safe to do so. - /// - /// # Safety - /// - /// The pointer must not be null and the caller must choose a lifetime that is - /// safe. - #[inline(always)] - pub unsafe fn get_storage_from_pointer_if_aligned<'a>( - ptr: *mut Self, - ) -> Option<&'a mut [T]> { - debug_assert!(!ptr.is_null()); - let self_ref = ptr.as_mut().unwrap_unchecked(); - self_ref.get_storage_if_aligned() - } - - /// Returns a slice pointing to the underlying data if safe to do so. - #[inline(always)] - pub fn get_storage_if_aligned(&self) -> Option<&mut [T]> { - // V8 may provide an invalid or null pointer when length is zero, so we just - // ignore that value completely and create an empty slice in this case. - if self.length == 0 { - return Some(&mut []); - } - // Ensure that we never return an unaligned or null buffer - if self.data.is_null() || (self.data as usize) % align_of::() != 0 { - return None; - } - Some(unsafe { std::slice::from_raw_parts_mut(self.data, self.length) }) - } -} - -#[derive(Copy, Clone)] -pub struct FastFunction { - pub args: &'static [Type], - pub function: *const c_void, - pub repr: Int64Representation, - pub return_type: CType, -} - -impl FastFunction { - #[inline(always)] - pub const fn new( - args: &'static [Type], - return_type: CType, - function: *const c_void, - ) -> Self { - Self { - args, - function, - repr: Int64Representation::Number, - return_type, - } - } - - pub const fn new_with_bigint( - args: &'static [Type], - return_type: CType, - function: *const c_void, - ) -> Self { - Self { - args, - function, - repr: Int64Representation::BigInt, - return_type, - } - } -} - -#[derive(Copy, Clone, Debug)] -#[repr(u8)] -pub enum Int64Representation { - Number = 0, - BigInt = 1, -} diff --git a/src/template.rs b/src/template.rs index 6b9bc02a..eaa72d4c 100644 --- a/src/template.rs +++ b/src/template.rs @@ -3,9 +3,7 @@ use crate::data::FunctionTemplate; use crate::data::Name; use crate::data::ObjectTemplate; use crate::data::Template; -use crate::fast_api::CFunctionInfo; -use crate::fast_api::CTypeInfo; -use crate::fast_api::FastFunction; +use crate::fast_api::CFunction; use crate::isolate::Isolate; use crate::support::int; use crate::support::MapFnTo; @@ -37,7 +35,6 @@ use crate::Signature; use crate::String; use crate::Value; use std::convert::TryFrom; -use std::ffi::c_void; use std::ptr::null; extern "C" { @@ -66,10 +63,8 @@ extern "C" { length: i32, constructor_behavior: ConstructorBehavior, side_effect_type: SideEffectType, - func_ptr1: *const c_void, - c_function1: *const CFunctionInfo, - func_ptr2: *const c_void, - c_function2: *const CFunctionInfo, + c_functions: *const CFunction, + c_functions_len: usize, ) -> *const FunctionTemplate; fn v8__FunctionTemplate__GetFunction( this: *const FunctionTemplate, @@ -700,9 +695,7 @@ impl<'s> FunctionBuilder<'s, FunctionTemplate> { self.constructor_behavior, self.side_effect_type, null(), - null(), - null(), - null(), + 0, ) }) } @@ -717,47 +710,8 @@ impl<'s> FunctionBuilder<'s, FunctionTemplate> { pub fn build_fast( self, scope: &mut HandleScope<'s, ()>, - overload1: &FastFunction, - c_fn_info1: Option<*const CFunctionInfo>, - overload2: Option<&FastFunction>, - c_fn_info2: Option<*const CFunctionInfo>, + overloads: &[CFunction], ) -> Local<'s, FunctionTemplate> { - let c_fn1 = if let Some(fn_info) = c_fn_info1 { - fn_info - } else { - let args = CTypeInfo::new_from_slice(overload1.args); - let ret = CTypeInfo::new(overload1.return_type); - let fn_info = unsafe { - CFunctionInfo::new( - args.as_ptr(), - overload1.args.len(), - ret.as_ptr(), - overload1.repr, - ) - }; - fn_info.as_ptr() - }; - - let c_fn2 = if let Some(overload2) = overload2 { - if let Some(fn_info) = c_fn_info2 { - fn_info - } else { - let args = CTypeInfo::new_from_slice(overload2.args); - let ret = CTypeInfo::new(overload2.return_type); - let fn_info = unsafe { - CFunctionInfo::new( - args.as_ptr(), - overload2.args.len(), - ret.as_ptr(), - overload2.repr, - ) - }; - fn_info.as_ptr() - } - } else { - null() - }; - unsafe { scope.cast_local(|sd| { v8__FunctionTemplate__New( @@ -768,10 +722,8 @@ impl<'s> FunctionBuilder<'s, FunctionTemplate> { self.length, ConstructorBehavior::Throw, self.side_effect_type, - overload1.function, - c_fn1, - overload2.map_or(null(), |f| f.function), - c_fn2, + overloads.as_ptr(), + overloads.len(), ) }) } diff --git a/tests/test_api.rs b/tests/test_api.rs index 2d2f84f7..86de4778 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -15,10 +15,9 @@ use std::ptr::{addr_of, addr_of_mut, NonNull}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use std::sync::Mutex; -use v8::fast_api::Type::*; -use v8::fast_api::{CType, FastApiTypedArray}; +use v8::fast_api; use v8::inspector::ChannelBase; -use v8::{fast_api, AccessorConfiguration}; +use v8::AccessorConfiguration; // TODO(piscisaureus): Ideally there would be no need to import this trait. use v8::MapFnTo; @@ -10456,10 +10455,17 @@ fn test_fast_calls() { a + b } - const FAST_TEST: fast_api::FastFunction = fast_api::FastFunction::new( - &[V8Value, Uint32, Uint32], - fast_api::CType::Uint32, + const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Uint32.scalar(), + &[ + fast_api::Type::V8Value.scalar(), + fast_api::Type::Uint32.scalar(), + fast_api::Type::Uint32.scalar(), + ], + fast_api::Int64Representation::Number, + ), ); fn slow_fn( @@ -10481,8 +10487,8 @@ fn test_fast_calls() { let global = context.global(scope); - let template = v8::FunctionTemplate::builder(slow_fn) - .build_fast(scope, &FAST_TEST, None, None, None); + let template = + v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &[FAST_TEST]); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -10508,16 +10514,11 @@ fn test_fast_calls_empty_buffer() { static mut WHO: &str = "none"; unsafe fn fast_fn( _recv: v8::Local, - buffer: *mut FastApiTypedArray, + buffer: *mut fast_api::FastApiTypedArray, ) { assert_eq!(WHO, "slow"); WHO = "fast"; - assert_eq!( - 0, - FastApiTypedArray::get_storage_from_pointer_if_aligned(buffer) - .unwrap() - .len() - ); + assert_eq!(0, (*buffer).get_storage_if_aligned().unwrap().len()); } fn slow_fn( @@ -10530,10 +10531,20 @@ fn test_fast_calls_empty_buffer() { } } - const FAST_TEST: fast_api::FastFunction = fast_api::FastFunction::new( - &[V8Value, TypedArray(CType::Uint8)], - fast_api::CType::Void, + const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Void.scalar(), + &[ + fast_api::Type::V8Value.scalar(), + fast_api::CTypeInfo::new( + fast_api::Type::Uint8, + fast_api::SequenceType::IsTypedArray, + fast_api::Flags::empty(), + ), + ], + fast_api::Int64Representation::Number, + ), ); let _setup_guard = setup::parallel_test(); @@ -10544,8 +10555,8 @@ fn test_fast_calls_empty_buffer() { let global = context.global(scope); - let template = v8::FunctionTemplate::builder(slow_fn) - .build_fast(scope, &FAST_TEST, None, None, None); + let template = + v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &[FAST_TEST]); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -10575,10 +10586,22 @@ fn test_fast_calls_sequence() { a + b + array.length() } - const FAST_TEST: fast_api::FastFunction = fast_api::FastFunction::new( - &[V8Value, Uint32, Uint32, Sequence(fast_api::CType::Void)], - fast_api::CType::Uint32, + const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Uint32.scalar(), + &[ + fast_api::Type::V8Value.scalar(), + fast_api::Type::Uint32.scalar(), + fast_api::Type::Uint32.scalar(), + fast_api::CTypeInfo::new( + fast_api::Type::Void, + fast_api::SequenceType::IsSequence, + fast_api::Flags::empty(), + ), + ], + fast_api::Int64Representation::Number, + ), ); fn slow_fn( @@ -10598,8 +10621,8 @@ fn test_fast_calls_sequence() { let global = context.global(scope); - let template = v8::FunctionTemplate::builder(slow_fn) - .build_fast(scope, &FAST_TEST, None, None, None); + let template = + v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &[FAST_TEST]); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -10634,10 +10657,22 @@ fn test_fast_calls_arraybuffer() { a + b + unsafe { &*data }.get(0) } - const FAST_TEST: fast_api::FastFunction = fast_api::FastFunction::new( - &[V8Value, Uint32, Uint32, TypedArray(fast_api::CType::Uint32)], - fast_api::CType::Uint32, + const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Uint32.scalar(), + &[ + fast_api::Type::V8Value.scalar(), + fast_api::Type::Uint32.scalar(), + fast_api::Type::Uint32.scalar(), + fast_api::CTypeInfo::new( + fast_api::Type::Uint32, + fast_api::SequenceType::IsTypedArray, + fast_api::Flags::empty(), + ), + ], + fast_api::Int64Representation::Number, + ), ); fn slow_fn( @@ -10657,8 +10692,8 @@ fn test_fast_calls_arraybuffer() { let global = context.global(scope); - let template = v8::FunctionTemplate::builder(slow_fn) - .build_fast(scope, &FAST_TEST, None, None, None); + let template = + v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &[FAST_TEST]); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -10698,10 +10733,20 @@ fn test_fast_calls_typedarray() { sum.into() } - const FAST_TEST: fast_api::FastFunction = fast_api::FastFunction::new( - &[V8Value, TypedArray(fast_api::CType::Uint8)], - fast_api::CType::Uint32, + const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Uint32.scalar(), + &[ + fast_api::Type::V8Value.scalar(), + fast_api::CTypeInfo::new( + fast_api::Type::Uint8, + fast_api::SequenceType::IsTypedArray, + fast_api::Flags::empty(), + ), + ], + fast_api::Int64Representation::Number, + ), ); fn slow_fn( @@ -10721,8 +10766,8 @@ fn test_fast_calls_typedarray() { let global = context.global(scope); - let template = v8::FunctionTemplate::builder(slow_fn) - .build_fast(scope, &FAST_TEST, None, None, None); + let template = + v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &[FAST_TEST]); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -10765,10 +10810,13 @@ fn test_fast_calls_reciever() { } } - const FAST_TEST: fast_api::FastFunction = fast_api::FastFunction::new( - &[V8Value], - fast_api::CType::Uint32, + const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Uint32.scalar(), + &[fast_api::Type::V8Value.scalar()], + fast_api::Int64Representation::Number, + ), ); fn slow_fn( @@ -10802,8 +10850,8 @@ fn test_fast_calls_reciever() { embedder_obj as _, ); - let template = v8::FunctionTemplate::builder(slow_fn) - .build_fast(scope, &FAST_TEST, None, None, None); + let template = + v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &[FAST_TEST]); let name = v8::String::new(scope, "method").unwrap(); let value = template.get_function(scope).unwrap(); @@ -10848,16 +10896,36 @@ fn test_fast_calls_overload() { assert_eq!(data.length(), 2); } - const FAST_TEST: fast_api::FastFunction = fast_api::FastFunction::new( - &[V8Value, TypedArray(CType::Uint32)], - CType::Void, + const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Void.scalar(), + &[ + fast_api::Type::V8Value.scalar(), + fast_api::CTypeInfo::new( + fast_api::Type::Uint32, + fast_api::SequenceType::IsTypedArray, + fast_api::Flags::empty(), + ), + ], + fast_api::Int64Representation::Number, + ), ); - const FAST_TEST2: fast_api::FastFunction = fast_api::FastFunction::new( - &[V8Value, Sequence(CType::Void)], - CType::Void, + const FAST_TEST2: fast_api::CFunction = fast_api::CFunction::new( fast_fn2 as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Void.scalar(), + &[ + fast_api::Type::V8Value.scalar(), + fast_api::CTypeInfo::new( + fast_api::Type::Void, + fast_api::SequenceType::IsSequence, + fast_api::Flags::empty(), + ), + ], + fast_api::Int64Representation::Number, + ), ); fn slow_fn( @@ -10877,13 +10945,8 @@ fn test_fast_calls_overload() { let global = context.global(scope); - let template = v8::FunctionTemplate::builder(slow_fn).build_fast( - scope, - &FAST_TEST, - None, - Some(&FAST_TEST2), - None, - ); + let template = v8::FunctionTemplate::builder(slow_fn) + .build_fast(scope, &[FAST_TEST, FAST_TEST2]); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -10928,10 +10991,16 @@ fn test_fast_calls_callback_options_fallback() { } } - const FAST_TEST: fast_api::FastFunction = fast_api::FastFunction::new( - &[V8Value, CallbackOptions], - CType::Void, + const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Void.scalar(), + &[ + fast_api::Type::V8Value.scalar(), + fast_api::Type::CallbackOptions.scalar(), + ], + fast_api::Int64Representation::Number, + ), ); fn slow_fn( @@ -10951,8 +11020,8 @@ fn test_fast_calls_callback_options_fallback() { let global = context.global(scope); - let template = v8::FunctionTemplate::builder(slow_fn) - .build_fast(scope, &FAST_TEST, None, None, None); + let template = + v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &[FAST_TEST]); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -10986,20 +11055,26 @@ fn test_fast_calls_callback_options_data() { options: *mut fast_api::FastApiCallbackOptions, ) { let options = &mut *options; - if !options.data.data.is_external() { + if !options.data.is_external() { options.fallback = true; return; } - let data = v8::Local::::cast_unchecked(options.data.data); + let data = v8::Local::::cast_unchecked(options.data); let data = &mut *(data.value() as *mut bool); *data = true; } - const FAST_TEST: fast_api::FastFunction = fast_api::FastFunction::new( - &[V8Value, CallbackOptions], - CType::Void, + const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Void.scalar(), + &[ + fast_api::Type::V8Value.scalar(), + fast_api::Type::CallbackOptions.scalar(), + ], + fast_api::Int64Representation::Number, + ), ); fn slow_fn( @@ -11022,7 +11097,7 @@ fn test_fast_calls_callback_options_data() { let template = v8::FunctionTemplate::builder(slow_fn) .data(external.into()) - .build_fast(scope, &FAST_TEST, None, None, None); + .build_fast(scope, &[FAST_TEST]); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -11103,10 +11178,16 @@ fn test_fast_calls_onebytestring() { data.len() as u32 } - const FAST_TEST: fast_api::FastFunction = fast_api::FastFunction::new( - &[V8Value, SeqOneByteString], - CType::Uint32, + const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Uint32.scalar(), + &[ + fast_api::Type::V8Value.scalar(), + fast_api::Type::SeqOneByteString.scalar(), + ], + fast_api::Int64Representation::Number, + ), ); fn slow_fn( @@ -11125,8 +11206,8 @@ fn test_fast_calls_onebytestring() { let global = context.global(scope); - let template = v8::FunctionTemplate::builder(slow_fn) - .build_fast(scope, &FAST_TEST, None, None, None); + let template = + v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &[FAST_TEST]); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -11162,18 +11243,31 @@ fn test_fast_calls_i64representation() { a * b } - const FAST_TEST_NUMBER: fast_api::FastFunction = fast_api::FastFunction::new( - &[V8Value, Uint64, Uint64], - CType::Uint64, + const FAST_TEST_NUMBER: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Uint64.scalar(), + &[ + fast_api::Type::V8Value.scalar(), + fast_api::Type::Uint64.scalar(), + fast_api::Type::Uint64.scalar(), + ], + fast_api::Int64Representation::Number, + ), ); - const FAST_TEST_BIGINT: fast_api::FastFunction = - fast_api::FastFunction::new_with_bigint( - &[V8Value, Uint64, Uint64], - CType::Uint64, - fast_fn as _, - ); + const FAST_TEST_BIGINT: fast_api::CFunction = fast_api::CFunction::new( + fast_fn as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Uint64.scalar(), + &[ + fast_api::Type::V8Value.scalar(), + fast_api::Type::Uint64.scalar(), + fast_api::Type::Uint64.scalar(), + ], + fast_api::Int64Representation::BigInt, + ), + ); fn slow_fn( _: &mut v8::HandleScope, @@ -11191,20 +11285,10 @@ fn test_fast_calls_i64representation() { let global = context.global(scope); - let template_number = v8::FunctionTemplate::builder(slow_fn).build_fast( - scope, - &FAST_TEST_NUMBER, - None, - None, - None, - ); - let template_bigint = v8::FunctionTemplate::builder(slow_fn).build_fast( - scope, - &FAST_TEST_BIGINT, - None, - None, - None, - ); + let template_number = v8::FunctionTemplate::builder(slow_fn) + .build_fast(scope, &[FAST_TEST_NUMBER]); + let template_bigint = v8::FunctionTemplate::builder(slow_fn) + .build_fast(scope, &[FAST_TEST_BIGINT]); let name_number = v8::String::new(scope, "func_number").unwrap(); let name_bigint = v8::String::new(scope, "func_bigint").unwrap(); @@ -11338,10 +11422,16 @@ fn test_fast_calls_pointer() { std::ptr::null_mut() } - const FAST_TEST: fast_api::FastFunction = fast_api::FastFunction::new( - &[V8Value, Pointer], - fast_api::CType::Pointer, + const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, + &fast_api::CFunctionInfo::new( + fast_api::Type::Pointer.scalar(), + &[ + fast_api::Type::V8Value.scalar(), + fast_api::Type::Pointer.scalar(), + ], + fast_api::Int64Representation::Number, + ), ); fn slow_fn( @@ -11363,8 +11453,8 @@ fn test_fast_calls_pointer() { let global = context.global(scope); - let template = v8::FunctionTemplate::builder(slow_fn) - .build_fast(scope, &FAST_TEST, None, None, None); + let template = + v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &[FAST_TEST]); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap();