mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-12-23 15:50:11 -05:00
V8 Fast API Sequence (#1022)
Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
parent
1d0a4c1792
commit
47a7bece35
2 changed files with 185 additions and 1 deletions
|
@ -102,6 +102,9 @@ pub enum Type {
|
|||
Float32,
|
||||
Float64,
|
||||
V8Value,
|
||||
Sequence(CType),
|
||||
TypedArray(CType),
|
||||
ArrayBuffer(CType),
|
||||
}
|
||||
|
||||
impl From<&Type> for CType {
|
||||
|
@ -116,6 +119,20 @@ impl From<&Type> for CType {
|
|||
Type::Float32 => CType::Float32,
|
||||
Type::Float64 => CType::Float64,
|
||||
Type::V8Value => CType::V8Value,
|
||||
Type::Sequence(ty) => *ty,
|
||||
Type::TypedArray(ty) => *ty,
|
||||
Type::ArrayBuffer(ty) => *ty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +141,7 @@ impl From<&Type> for CTypeSequenceInfo {
|
|||
fn from(ty: &Type) -> CTypeSequenceInfo {
|
||||
CTypeSequenceInfo {
|
||||
c_type: ty.into(),
|
||||
sequence_type: SequenceType::Scalar,
|
||||
sequence_type: ty.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7078,3 +7078,170 @@ fn test_fast_calls() {
|
|||
eval(scope, source).unwrap();
|
||||
assert_eq!("fast", unsafe { WHO });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fast_calls_sequence() {
|
||||
static mut WHO: &str = "none";
|
||||
fn fast_fn(
|
||||
_recv: v8::Local<v8::Object>,
|
||||
a: u32,
|
||||
b: u32,
|
||||
array: v8::Local<v8::Array>,
|
||||
) -> u32 {
|
||||
unsafe { WHO = "fast" };
|
||||
assert_eq!(array.length(), 2);
|
||||
a + b + array.length()
|
||||
}
|
||||
|
||||
pub struct FastTest;
|
||||
impl fast_api::FastFunction for FastTest {
|
||||
fn args(&self) -> &'static [fast_api::Type] {
|
||||
&[
|
||||
fast_api::Type::V8Value,
|
||||
fast_api::Type::Uint32,
|
||||
fast_api::Type::Uint32,
|
||||
fast_api::Type::Sequence(fast_api::CType::Void),
|
||||
]
|
||||
}
|
||||
|
||||
fn return_type(&self) -> fast_api::CType {
|
||||
fast_api::CType::Uint32
|
||||
}
|
||||
|
||||
type Signature = fn(
|
||||
receiver: v8::Local<v8::Object>,
|
||||
a: u32,
|
||||
b: u32,
|
||||
array: v8::Local<v8::Array>,
|
||||
) -> u32;
|
||||
fn function(&self) -> Self::Signature {
|
||||
fast_fn
|
||||
}
|
||||
}
|
||||
|
||||
fn slow_fn(
|
||||
scope: &mut v8::HandleScope,
|
||||
_: v8::FunctionCallbackArguments,
|
||||
mut rv: v8::ReturnValue,
|
||||
) {
|
||||
unsafe { WHO = "slow" };
|
||||
rv.set(v8::Boolean::new(scope, false).into());
|
||||
}
|
||||
|
||||
let _setup_guard = setup();
|
||||
let isolate = &mut v8::Isolate::new(Default::default());
|
||||
let scope = &mut v8::HandleScope::new(isolate);
|
||||
let context = v8::Context::new(scope);
|
||||
let scope = &mut v8::ContextScope::new(scope, context);
|
||||
|
||||
let global = context.global(scope);
|
||||
|
||||
let template =
|
||||
v8::FunctionTemplate::builder(slow_fn).build_fast(scope, FastTest);
|
||||
|
||||
let name = v8::String::new(scope, "func").unwrap();
|
||||
let value = template.get_function(scope).unwrap();
|
||||
global.set(scope, name.into(), value.into()).unwrap();
|
||||
let source = r#"
|
||||
function f(x, y, data) { return func(x, y, data); }
|
||||
%PrepareFunctionForOptimization(f);
|
||||
const arr = [3, 4];
|
||||
f(1, 2, arr);
|
||||
"#;
|
||||
eval(scope, source).unwrap();
|
||||
assert_eq!("slow", unsafe { WHO });
|
||||
|
||||
let source = r#"
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
f(1, 2, arr);
|
||||
"#;
|
||||
eval(scope, source).unwrap();
|
||||
assert_eq!("fast", unsafe { WHO });
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FastApiArrayBuffer {
|
||||
byte_length: usize,
|
||||
data: *mut u32,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fast_calls_arraybuffer() {
|
||||
static mut WHO: &str = "none";
|
||||
fn fast_fn(
|
||||
_recv: v8::Local<v8::Object>,
|
||||
a: u32,
|
||||
b: u32,
|
||||
data: *const FastApiArrayBuffer,
|
||||
) -> u32 {
|
||||
unsafe { WHO = "fast" };
|
||||
let buf =
|
||||
unsafe { std::slice::from_raw_parts((*data).data, (*data).byte_length) };
|
||||
a + b + buf[0]
|
||||
}
|
||||
|
||||
pub struct FastTest;
|
||||
impl fast_api::FastFunction for FastTest {
|
||||
fn args(&self) -> &'static [fast_api::Type] {
|
||||
&[
|
||||
fast_api::Type::V8Value,
|
||||
fast_api::Type::Uint32,
|
||||
fast_api::Type::Uint32,
|
||||
fast_api::Type::TypedArray(fast_api::CType::Uint32),
|
||||
]
|
||||
}
|
||||
|
||||
fn return_type(&self) -> fast_api::CType {
|
||||
fast_api::CType::Uint32
|
||||
}
|
||||
|
||||
type Signature = fn(
|
||||
receiver: v8::Local<v8::Object>,
|
||||
a: u32,
|
||||
b: u32,
|
||||
data: *const FastApiArrayBuffer,
|
||||
) -> u32;
|
||||
fn function(&self) -> Self::Signature {
|
||||
fast_fn
|
||||
}
|
||||
}
|
||||
|
||||
fn slow_fn(
|
||||
scope: &mut v8::HandleScope,
|
||||
_: v8::FunctionCallbackArguments,
|
||||
mut rv: v8::ReturnValue,
|
||||
) {
|
||||
unsafe { WHO = "slow" };
|
||||
rv.set(v8::Boolean::new(scope, false).into());
|
||||
}
|
||||
|
||||
let _setup_guard = setup();
|
||||
let isolate = &mut v8::Isolate::new(Default::default());
|
||||
let scope = &mut v8::HandleScope::new(isolate);
|
||||
let context = v8::Context::new(scope);
|
||||
let scope = &mut v8::ContextScope::new(scope, context);
|
||||
|
||||
let global = context.global(scope);
|
||||
|
||||
let template =
|
||||
v8::FunctionTemplate::builder(slow_fn).build_fast(scope, FastTest);
|
||||
|
||||
let name = v8::String::new(scope, "func").unwrap();
|
||||
let value = template.get_function(scope).unwrap();
|
||||
global.set(scope, name.into(), value.into()).unwrap();
|
||||
let source = r#"
|
||||
function f(x, y, data) { return func(x, y, data); }
|
||||
%PrepareFunctionForOptimization(f);
|
||||
const arr = new Uint32Array([3, 4]);
|
||||
f(1, 2, arr);
|
||||
"#;
|
||||
eval(scope, source).unwrap();
|
||||
assert_eq!("slow", unsafe { WHO });
|
||||
|
||||
let source = r#"
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
f(1, 2, arr);
|
||||
"#;
|
||||
eval(scope, source).unwrap();
|
||||
assert_eq!("fast", unsafe { WHO });
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue