mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-23 15:17:01 -05:00
update fast calls api (#1564)
This commit is contained in:
parent
0d57670bac
commit
70e18db2ff
8 changed files with 359 additions and 475 deletions
|
@ -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();
|
||||
|
||||
|
|
|
@ -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};
|
||||
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>{};
|
||||
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));
|
||||
side_effect_type, overloads));
|
||||
}
|
||||
|
||||
const v8::Function* v8__FunctionTemplate__GetFunction(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#![allow(unused)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
|
|
|
@ -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> {
|
||||
|
|
404
src/fast_api.rs
404
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<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(),
|
||||
))
|
||||
}
|
||||
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<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,
|
||||
}
|
||||
|
||||
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<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 doesn’t 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,
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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,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();
|
||||
|
|
Loading…
Reference in a new issue