mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-12-24 08:09:16 -05:00
Add SeqOneByteString to fast API calls (#1129)
This commit is contained in:
parent
3603c6e9c5
commit
f5c9e90c6d
2 changed files with 92 additions and 0 deletions
|
@ -91,6 +91,7 @@ pub enum CType {
|
||||||
Float32,
|
Float32,
|
||||||
Float64,
|
Float64,
|
||||||
V8Value,
|
V8Value,
|
||||||
|
SeqOneByteString,
|
||||||
// https://github.com/v8/v8/blob/492a32943bc34a527f42df2ae15a77154b16cc84/include/v8-fast-api-calls.h#L264-L267
|
// https://github.com/v8/v8/blob/492a32943bc34a527f42df2ae15a77154b16cc84/include/v8-fast-api-calls.h#L264-L267
|
||||||
// kCallbackOptionsType is not part of the Type enum
|
// kCallbackOptionsType is not part of the Type enum
|
||||||
// because it is only used internally. Use value 255 that is larger
|
// because it is only used internally. Use value 255 that is larger
|
||||||
|
@ -110,6 +111,7 @@ pub enum Type {
|
||||||
Float32,
|
Float32,
|
||||||
Float64,
|
Float64,
|
||||||
V8Value,
|
V8Value,
|
||||||
|
SeqOneByteString,
|
||||||
CallbackOptions,
|
CallbackOptions,
|
||||||
Sequence(CType),
|
Sequence(CType),
|
||||||
TypedArray(CType),
|
TypedArray(CType),
|
||||||
|
@ -128,6 +130,7 @@ impl From<&Type> for CType {
|
||||||
Type::Float32 => CType::Float32,
|
Type::Float32 => CType::Float32,
|
||||||
Type::Float64 => CType::Float64,
|
Type::Float64 => CType::Float64,
|
||||||
Type::V8Value => CType::V8Value,
|
Type::V8Value => CType::V8Value,
|
||||||
|
Type::SeqOneByteString => CType::SeqOneByteString,
|
||||||
Type::CallbackOptions => CType::CallbackOptions,
|
Type::CallbackOptions => CType::CallbackOptions,
|
||||||
Type::Sequence(ty) => *ty,
|
Type::Sequence(ty) => *ty,
|
||||||
Type::TypedArray(ty) => *ty,
|
Type::TypedArray(ty) => *ty,
|
||||||
|
@ -204,6 +207,25 @@ pub struct FastApiTypedArray<T: Default> {
|
||||||
data: *mut T,
|
data: *mut T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct FastApiOneByteString {
|
||||||
|
data: *const u8,
|
||||||
|
pub length: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FastApiOneByteString {
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn as_str(&self) -> &str {
|
||||||
|
// SAFETY: The string is guaranteed to be valid UTF-8.
|
||||||
|
unsafe {
|
||||||
|
std::str::from_utf8_unchecked(std::slice::from_raw_parts(
|
||||||
|
self.data,
|
||||||
|
self.length,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Default> FastApiTypedArray<T> {
|
impl<T: Default> FastApiTypedArray<T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get(&self, index: usize) -> T {
|
pub fn get(&self, index: usize) -> T {
|
||||||
|
|
|
@ -8603,3 +8603,73 @@ fn test_detach_key() {
|
||||||
assert!(buffer.was_detached());
|
assert!(buffer.was_detached());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fast_calls_onebytestring() {
|
||||||
|
static mut WHO: &str = "none";
|
||||||
|
fn fast_fn(
|
||||||
|
_recv: v8::Local<v8::Object>,
|
||||||
|
data: *const fast_api::FastApiOneByteString,
|
||||||
|
) -> u32 {
|
||||||
|
unsafe { WHO = "fast" };
|
||||||
|
let data = unsafe { &*data }.as_str();
|
||||||
|
assert_eq!("hello", data);
|
||||||
|
data.len() as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FastTest;
|
||||||
|
impl fast_api::FastFunction for FastTest {
|
||||||
|
fn args(&self) -> &'static [fast_api::Type] {
|
||||||
|
&[fast_api::Type::V8Value, fast_api::Type::SeqOneByteString]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn return_type(&self) -> fast_api::CType {
|
||||||
|
fast_api::CType::Uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn function(&self) -> *const c_void {
|
||||||
|
fast_fn as _
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn slow_fn(
|
||||||
|
_: &mut v8::HandleScope,
|
||||||
|
_: v8::FunctionCallbackArguments,
|
||||||
|
_: v8::ReturnValue,
|
||||||
|
) {
|
||||||
|
unsafe { WHO = "slow" };
|
||||||
|
}
|
||||||
|
|
||||||
|
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, None);
|
||||||
|
|
||||||
|
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(data) { return func(data); }
|
||||||
|
%PrepareFunctionForOptimization(f);
|
||||||
|
const str = "hello";
|
||||||
|
f(str);
|
||||||
|
"#;
|
||||||
|
eval(scope, source).unwrap();
|
||||||
|
assert_eq!("slow", unsafe { WHO });
|
||||||
|
|
||||||
|
let source = r#"
|
||||||
|
%OptimizeFunctionOnNextCall(f);
|
||||||
|
const result = f(str);
|
||||||
|
if (result != 5) {
|
||||||
|
throw new Error("wrong result");
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
eval(scope, source).unwrap();
|
||||||
|
assert_eq!("fast", unsafe { WHO });
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue