fix(ext/ffi): trampoline for fast calls (#15139)

This commit is contained in:
Divy Srivastava 2022-07-12 06:33:05 +05:30 committed by GitHub
parent 5db16d1229
commit 77d065e034
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 435 additions and 11 deletions

View file

@ -39,6 +39,11 @@ use std::path::PathBuf;
use std::ptr;
use std::rc::Rc;
#[cfg(not(target_os = "windows"))]
mod jit_trampoline;
#[cfg(not(target_os = "windows"))]
mod tcc;
thread_local! {
static LOCAL_ISOLATE_POINTER: RefCell<*const v8::Isolate> = RefCell::new(ptr::null());
}
@ -72,6 +77,8 @@ struct Symbol {
ptr: libffi::middle::CodePtr,
parameter_types: Vec<NativeType>,
result_type: NativeType,
// This is dead code only on Windows
#[allow(dead_code)]
can_callback: bool,
}
@ -678,6 +685,7 @@ impl From<&NativeType> for fast_api::Type {
}
}
#[cfg(not(target_os = "windows"))]
fn is_fast_api(rv: NativeType) -> bool {
!matches!(
rv,
@ -696,25 +704,36 @@ fn make_sync_fn<'s>(
scope: &mut v8::HandleScope<'s>,
sym: Box<Symbol>,
) -> v8::Local<'s, v8::Function> {
let mut fast_ffi_templ = None;
#[cfg(not(target_os = "windows"))]
let mut fast_ffi_templ: Option<FfiFastCallTemplate> = None;
#[cfg(target_os = "windows")]
let fast_ffi_templ: Option<FfiFastCallTemplate> = None;
#[cfg(not(target_os = "windows"))]
let mut fast_allocations: Option<*mut ()> = None;
#[cfg(not(target_os = "windows"))]
if !sym.can_callback
&& !sym.parameter_types.iter().any(|t| !is_fast_api(*t))
&& is_fast_api(sym.result_type)
{
let ret = fast_api::Type::from(&sym.result_type);
let mut args = sym
.parameter_types
.iter()
.map(|t| t.into())
.collect::<Vec<_>>();
if args.is_empty() {
args.push(fast_api::Type::V8Value);
}
// recv
args.insert(0, fast_api::Type::V8Value);
let symbol_trampoline =
jit_trampoline::gen_trampoline(sym.clone()).expect("gen_trampoline");
fast_ffi_templ = Some(FfiFastCallTemplate {
args: args.into_boxed_slice(),
ret: (&fast_api::Type::from(&sym.result_type)).into(),
symbol_ptr: sym.ptr.as_ptr() as *const c_void,
ret: (&ret).into(),
symbol_ptr: symbol_trampoline.addr,
});
fast_allocations = Some(Box::into_raw(symbol_trampoline) as *mut ());
}
let sym = Box::leak(sym);
@ -754,7 +773,13 @@ fn make_sync_fn<'s>(
Box::new(move |_| {
// SAFETY: This is never called twice. pointer obtained
// from Box::into_raw, hence, satisfies memory layout requirements.
unsafe { Box::from_raw(sym) };
unsafe {
Box::from_raw(sym);
#[cfg(not(target_os = "windows"))]
if let Some(fast_allocations) = fast_allocations {
Box::from_raw(fast_allocations as *mut jit_trampoline::Allocation);
}
}
}),
);