0
0
Fork 0
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:
Aapo Alasuutari 2023-06-02 20:28:14 +03:00 committed by GitHub
parent 2fc52161ce
commit 6cc61a26b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 154 additions and 7 deletions

View file

@ -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();
}

View file

@ -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,
}

View file

@ -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()
}

View file

@ -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();