mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-24 15:19:31 -05:00
feat(fastcall): Int64Representation (#1238)
* feat(fastcall): Int64Representation * Add tests, new_with_bigint API * Fix build, actually
This commit is contained in:
parent
2fc52161ce
commit
6cc61a26b2
4 changed files with 154 additions and 7 deletions
|
@ -1979,9 +1979,10 @@ v8::CTypeInfo* v8__CTypeInfo__New__From__Slice(unsigned int len,
|
|||
|
||||
v8::CFunctionInfo* v8__CFunctionInfo__New(const v8::CTypeInfo& return_info,
|
||||
unsigned int args_len,
|
||||
v8::CTypeInfo* args_info) {
|
||||
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));
|
||||
v8::CFunctionInfo(return_info, args_len, args_info, repr));
|
||||
return info.release();
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ extern "C" {
|
|||
return_info: *const CTypeInfo,
|
||||
args_len: usize,
|
||||
args_info: *const CTypeInfo,
|
||||
repr: Int64Representation,
|
||||
) -> *mut CFunctionInfo;
|
||||
}
|
||||
|
||||
|
@ -34,8 +35,14 @@ impl CFunctionInfo {
|
|||
args: *const CTypeInfo,
|
||||
args_len: usize,
|
||||
return_type: *const CTypeInfo,
|
||||
repr: Int64Representation,
|
||||
) -> NonNull<CFunctionInfo> {
|
||||
NonNull::new_unchecked(v8__CFunctionInfo__New(return_type, args_len, args))
|
||||
NonNull::new_unchecked(v8__CFunctionInfo__New(
|
||||
return_type,
|
||||
args_len,
|
||||
args,
|
||||
repr,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,8 +253,9 @@ impl<T: Default> FastApiTypedArray<T> {
|
|||
|
||||
pub struct FastFunction {
|
||||
pub args: &'static [Type],
|
||||
pub return_type: CType,
|
||||
pub function: *const c_void,
|
||||
pub repr: Int64Representation,
|
||||
pub return_type: CType,
|
||||
}
|
||||
|
||||
impl FastFunction {
|
||||
|
@ -259,8 +267,29 @@ impl FastFunction {
|
|||
) -> Self {
|
||||
Self {
|
||||
args,
|
||||
return_type,
|
||||
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,
|
||||
}
|
||||
|
|
|
@ -578,7 +578,12 @@ impl<'s> FunctionBuilder<'s, FunctionTemplate> {
|
|||
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())
|
||||
CFunctionInfo::new(
|
||||
args.as_ptr(),
|
||||
overload1.args.len(),
|
||||
ret.as_ptr(),
|
||||
overload1.repr,
|
||||
)
|
||||
};
|
||||
fn_info.as_ptr()
|
||||
};
|
||||
|
@ -590,7 +595,12 @@ impl<'s> FunctionBuilder<'s, FunctionTemplate> {
|
|||
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())
|
||||
CFunctionInfo::new(
|
||||
args.as_ptr(),
|
||||
overload2.args.len(),
|
||||
ret.as_ptr(),
|
||||
overload2.repr,
|
||||
)
|
||||
};
|
||||
fn_info.as_ptr()
|
||||
}
|
||||
|
|
|
@ -9873,6 +9873,113 @@ fn test_fast_calls_onebytestring() {
|
|||
assert_eq!("fast", unsafe { WHO });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fast_calls_i64representation() {
|
||||
static mut FAST_CALL_COUNT: u32 = 0;
|
||||
static mut SLOW_CALL_COUNT: u32 = 0;
|
||||
fn fast_fn(_recv: v8::Local<v8::Object>, a: u64, b: u64) -> u64 {
|
||||
unsafe { FAST_CALL_COUNT += 1 };
|
||||
assert_eq!(9007199254740991, a);
|
||||
assert_eq!(646, b);
|
||||
a * b
|
||||
}
|
||||
|
||||
const FAST_TEST_NUMBER: fast_api::FastFunction = fast_api::FastFunction::new(
|
||||
&[V8Value, Uint64, Uint64],
|
||||
CType::Uint64,
|
||||
fast_fn as _,
|
||||
);
|
||||
|
||||
const FAST_TEST_BIGINT: fast_api::FastFunction =
|
||||
fast_api::FastFunction::new_with_bigint(
|
||||
&[V8Value, Uint64, Uint64],
|
||||
CType::Uint64,
|
||||
fast_fn as _,
|
||||
);
|
||||
|
||||
fn slow_fn(
|
||||
_: &mut v8::HandleScope,
|
||||
_: v8::FunctionCallbackArguments,
|
||||
_: v8::ReturnValue,
|
||||
) {
|
||||
unsafe { SLOW_CALL_COUNT += 1 };
|
||||
}
|
||||
|
||||
let _setup_guard = setup::parallel_test();
|
||||
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_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 name_number = v8::String::new(scope, "func_number").unwrap();
|
||||
let name_bigint = v8::String::new(scope, "func_bigint").unwrap();
|
||||
let value_number = template_number.get_function(scope).unwrap();
|
||||
let value_bigint = template_bigint.get_function(scope).unwrap();
|
||||
global
|
||||
.set(scope, name_number.into(), value_number.into())
|
||||
.unwrap();
|
||||
global
|
||||
.set(scope, name_bigint.into(), value_bigint.into())
|
||||
.unwrap();
|
||||
let source = r#"
|
||||
function f(a, b) { return func_number(a, b); }
|
||||
%PrepareFunctionForOptimization(f);
|
||||
f(1, 2);
|
||||
"#;
|
||||
eval(scope, source).unwrap();
|
||||
assert_eq!(1, unsafe { SLOW_CALL_COUNT });
|
||||
|
||||
let source = r#"
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
{
|
||||
const result = f(Number.MAX_SAFE_INTEGER, 646);
|
||||
// Correct answer is 5818650718562680186: data is lost.
|
||||
if (result != 5818650718562680000) {
|
||||
throw new Error(`wrong number result: ${result}`);
|
||||
}
|
||||
}
|
||||
"#;
|
||||
eval(scope, source).unwrap();
|
||||
assert_eq!(1, unsafe { FAST_CALL_COUNT });
|
||||
|
||||
let source = r#"
|
||||
function g(a, b) { return func_bigint(a, b); }
|
||||
%PrepareFunctionForOptimization(g);
|
||||
g(1n, 2n);
|
||||
"#;
|
||||
eval(scope, source).unwrap();
|
||||
assert_eq!(2, unsafe { SLOW_CALL_COUNT });
|
||||
|
||||
let source = r#"
|
||||
%OptimizeFunctionOnNextCall(g);
|
||||
{
|
||||
const result = g(BigInt(Number.MAX_SAFE_INTEGER), 646n);
|
||||
if (result != 5818650718562680186n) {
|
||||
throw new Error(`wrong bigint result: ${result}`);
|
||||
}
|
||||
}
|
||||
"#;
|
||||
eval(scope, source).unwrap();
|
||||
assert_eq!(2, unsafe { FAST_CALL_COUNT });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gc_callbacks() {
|
||||
let _setup_guard = setup::parallel_test();
|
||||
|
|
Loading…
Reference in a new issue