update fast calls api (#1564)

This commit is contained in:
snek 2024-08-13 18:15:34 +02:00 committed by GitHub
parent 0d57670bac
commit 70e18db2ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 359 additions and 475 deletions

View File

@ -65,11 +65,13 @@ 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,
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,
@ -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();

View File

@ -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<v8::CTypeInfo> u =
std::make_unique<v8::CTypeInfo>(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<v8::CFunctionInfo> info = std::make_unique<v8::CFunctionInfo>(
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<const v8::CFunction>{o, 1};
v8::SideEffectType side_effect_type, const v8::CFunction* c_functions,
size_t c_functions_len) {
v8::MemorySpan<const v8::CFunction> 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));
} else {
const v8::CFunction o[] = {v8::CFunction(func_ptr1, c_function_info1),
v8::CFunction(func_ptr2, c_function_info2)};
auto overload = v8::MemorySpan<const v8::CFunction>{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<const v8::CFunction>{};
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(

View File

@ -1,4 +1,5 @@
#include <v8-cppgc.h>
#include <v8-fast-api-calls.h>
#include <v8-message.h>
#include <v8-typed-array.h>
@ -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;

View File

@ -1,3 +1,4 @@
#![allow(unused)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

View File

@ -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> {

View File

@ -1,204 +1,137 @@
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,
})
}
#[repr(C)]
#[derive(Default)]
pub struct CFunctionInfo(Opaque);
pub const fn address(&self) -> *const c_void {
self.0.address_
}
#[repr(C)]
#[derive(Default)]
pub struct CFunction(Opaque);
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(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<CFunctionInfo> {
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<CTypeInfo> {
unsafe { NonNull::new_unchecked(v8__CTypeInfo__New(ty)) }
}
pub fn new_from_slice(types: &[Type]) -> NonNull<CTypeInfo> {
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(),
))
}
}
}
impl Drop for CTypeInfo {
fn drop(&mut self) {
unsafe { v8__CTypeInfo__DELETE(self) };
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 _,
})
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum SequenceType {
Scalar,
/// sequence<T>
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<T>
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,
}
impl From<&Type> for CTypeSequenceInfo {
fn from(ty: &Type) -> CTypeSequenceInfo {
CTypeSequenceInfo {
c_type: ty.into(),
sequence_type: ty.into(),
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;
}
}
}
#[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
@ -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<u8>,
}
@ -235,8 +169,45 @@ pub struct FastApiTypedArray<T: Default> {
data: *mut T,
}
impl<T: Default> FastApiTypedArray<T> {
/// 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::<T>() != 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 doesnt have its
/// own instance type. It could be supported if we specify that
/// TypedArray<T> 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<T: Default> FastApiTypedArray<T> {
/// 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::<T>() != 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,
}

View File

@ -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(),
)
})
}

View File

@ -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<v8::Object>,
buffer: *mut FastApiTypedArray<u8>,
buffer: *mut fast_api::FastApiTypedArray<u8>,
) {
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::<v8::External>::cast_unchecked(options.data.data);
let data = v8::Local::<v8::External>::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,17 +11243,30 @@ 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,
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(
@ -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();