use Isolate for creating primitives (#1082)

This commit is contained in:
Divy Srivastava 2022-10-06 11:44:16 -07:00 committed by GitHub
parent 8f8636b4f7
commit 5dd41e9dba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 114 additions and 37 deletions

View File

@ -94,36 +94,74 @@ fn main() {
global.set(scope, name.into(), value.into()).unwrap();
}
{
extern "C" fn callback(info: *const v8::FunctionCallbackInfo) {
let scope = unsafe { &mut v8::CallbackScope::new(&*info) };
let mut rv =
unsafe { v8::ReturnValue::from_function_callback_info(info) };
rv.set(v8::undefined(scope).into());
}
let func = v8::Function::new_raw(scope, callback).unwrap();
let name = v8::String::new(scope, "undefined_from_scope").unwrap();
global.set(scope, name.into(), func.into()).unwrap();
}
{
extern "C" fn callback(info: *const v8::FunctionCallbackInfo) {
let mut rv =
unsafe { v8::ReturnValue::from_function_callback_info(info) };
let mut info = unsafe {
v8::FunctionCallbackArguments::from_function_callback_info(info)
};
rv.set(v8::undefined(unsafe { info.get_isolate() }).into());
}
let func = v8::Function::new_raw(scope, callback).unwrap();
let name = v8::String::new(scope, "undefined_from_isolate").unwrap();
global.set(scope, name.into(), func.into()).unwrap();
}
let runs = 100_000_000;
for x in [
"new_",
"new_raw",
"new_set_uint32",
"new_raw_set_uint32",
"new_fast",
for (group_name, benches) in [
(
"function_overhead",
&[
"new_",
"new_raw",
"new_set_uint32",
"new_raw_set_uint32",
"new_fast",
][..],
),
(
"primitives",
&["undefined_from_scope", "undefined_from_isolate"][..],
),
] {
let code = format!(
"
function bench() {{ return {}(); }};
runs = {};
start = Date.now();
for (i = 0; i < runs; i++) bench();
Date.now() - start;
",
x, runs
);
println!("Running {} ...", group_name);
for x in benches {
let code = format!(
"
function bench() {{ return {}(); }};
runs = {};
start = Date.now();
for (i = 0; i < runs; i++) bench();
Date.now() - start;
",
x, runs
);
let r = eval(scope, &code).unwrap();
let number = r.to_number(scope).unwrap();
let total_ms = number.number_value(scope).unwrap();
let total_ns = 1e6 * total_ms;
let ns_per_run = total_ns / (runs as f64);
let mops_per_sec = (runs as f64) / (total_ms / 1000.0) / 1e6;
println!(
"{:.1} ns per run {:.1} million ops/sec → {}",
ns_per_run, mops_per_sec, x
);
let r = eval(scope, &code).unwrap();
let number = r.to_number(scope).unwrap();
let total_ms = number.number_value(scope).unwrap();
let total_ns = 1e6 * total_ms;
let ns_per_run = total_ns / (runs as f64);
let mops_per_sec = (runs as f64) / (total_ms / 1000.0) / 1e6;
println!(
" {:.1} ns per run {:.1} million ops/sec → {}",
ns_per_run, mops_per_sec, x
);
}
}
}

View File

@ -12,6 +12,7 @@ use crate::support::{int, Opaque};
use crate::Context;
use crate::Function;
use crate::HandleScope;
use crate::Isolate;
use crate::Local;
use crate::Name;
use crate::Object;
@ -69,6 +70,9 @@ extern "C" {
fn v8__FunctionCallbackInfo__NewTarget(
this: *const FunctionCallbackInfo,
) -> *const Value;
fn v8__FunctionCallbackInfo__GetIsolate(
this: *const FunctionCallbackInfo,
) -> *mut Isolate;
fn v8__PropertyCallbackInfo__GetReturnValue(
this: *const PropertyCallbackInfo,
@ -233,6 +237,11 @@ impl<'s> FunctionCallbackArguments<'s> {
}
}
#[inline(always)]
pub unsafe fn get_isolate(&mut self) -> &mut Isolate {
&mut *v8__FunctionCallbackInfo__GetIsolate(self.info)
}
/// Returns the receiver. This corresponds to the "this" value.
#[inline(always)]
pub fn this(&self) -> Local<'s, Object> {

View File

@ -107,6 +107,11 @@ impl<'s, T> Local<'s, T> {
NonNull::new(ptr as *mut _).map(|nn| Self::from_non_null(nn))
}
#[inline(always)]
pub(crate) unsafe fn from_raw_unchecked(ptr: *const T) -> Self {
Self(NonNull::new_unchecked(ptr as *mut _), PhantomData)
}
#[inline(always)]
pub(crate) unsafe fn from_non_null(nn: NonNull<T>) -> Self {
Self(nn, PhantomData)

View File

@ -1123,6 +1123,18 @@ impl DerefMut for OwnedIsolate {
}
}
impl AsMut<Isolate> for OwnedIsolate {
fn as_mut(&mut self) -> &mut Isolate {
self
}
}
impl AsMut<Isolate> for Isolate {
fn as_mut(&mut self) -> &mut Isolate {
self
}
}
impl HeapStatistics {
#[inline(always)]
pub fn total_heap_size(&self) -> usize {

View File

@ -1,6 +1,5 @@
use crate::isolate::Isolate;
use crate::Boolean;
use crate::HandleScope;
use crate::Local;
use crate::Primitive;
@ -12,24 +11,29 @@ extern "C" {
}
#[inline(always)]
pub fn null<'s>(scope: &mut HandleScope<'s, ()>) -> Local<'s, Primitive> {
unsafe { scope.cast_local(|sd| v8__Null(sd.get_isolate_ptr())) }.unwrap()
pub fn null<'a, R>(scope: &mut R) -> Local<'a, Primitive>
where
R: AsMut<Isolate>,
{
unsafe { Local::from_raw_unchecked(v8__Null(scope.as_mut())) }
}
#[inline(always)]
pub fn undefined<'s>(scope: &mut HandleScope<'s, ()>) -> Local<'s, Primitive> {
unsafe { scope.cast_local(|sd| v8__Undefined(sd.get_isolate_ptr())) }.unwrap()
pub fn undefined<'a, R>(scope: &mut R) -> Local<'a, Primitive>
where
R: AsMut<Isolate>,
{
unsafe { Local::from_raw_unchecked(v8__Undefined(scope.as_mut())) }
}
impl Boolean {
#[inline(always)]
pub fn new<'s>(
scope: &mut HandleScope<'s, ()>,
value: bool,
) -> Local<'s, Boolean> {
pub fn new<'a, R>(scope: &mut R, value: bool) -> Local<'a, Boolean>
where
R: AsMut<Isolate>,
{
unsafe {
scope.cast_local(|sd| v8__Boolean__New(sd.get_isolate_ptr(), value))
Local::from_raw_unchecked(v8__Boolean__New(scope.as_mut(), value))
}
.unwrap()
}
}

View File

@ -553,6 +553,15 @@ fn get_isolate_from_handle() {
check_eval(scope, Some(false), "3.3 / 3.3");
}
#[test]
fn handles_from_isolate() {
let _setup_guard = setup();
let isolate = &mut v8::Isolate::new(Default::default());
let _ = v8::null(isolate);
let _ = v8::undefined(isolate);
let _ = v8::Boolean::new(isolate, true);
}
#[test]
fn array_buffer() {
let _setup_guard = setup();