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,
|
||||
Float64,
|
||||
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
|
||||
|
@ -110,6 +111,7 @@ pub enum Type {
|
|||
Float32,
|
||||
Float64,
|
||||
V8Value,
|
||||
SeqOneByteString,
|
||||
CallbackOptions,
|
||||
Sequence(CType),
|
||||
TypedArray(CType),
|
||||
|
@ -128,6 +130,7 @@ impl From<&Type> for CType {
|
|||
Type::Float32 => CType::Float32,
|
||||
Type::Float64 => CType::Float64,
|
||||
Type::V8Value => CType::V8Value,
|
||||
Type::SeqOneByteString => CType::SeqOneByteString,
|
||||
Type::CallbackOptions => CType::CallbackOptions,
|
||||
Type::Sequence(ty) => *ty,
|
||||
Type::TypedArray(ty) => *ty,
|
||||
|
@ -204,6 +207,25 @@ pub struct FastApiTypedArray<T: Default> {
|
|||
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> {
|
||||
#[inline(always)]
|
||||
pub fn get(&self, index: usize) -> T {
|
||||
|
|
|
@ -8603,3 +8603,73 @@ fn test_detach_key() {
|
|||
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