summaryrefslogtreecommitdiff
path: root/ext/ffi/lib.rs
diff options
context:
space:
mode:
authorArnau Orriols <arnauorriolsmiro@gmail.com>2022-09-07 08:53:56 +0200
committerGitHub <noreply@github.com>2022-09-07 12:23:56 +0530
commit8bdc3c2bafa9bdfcd6bfaf94b97b960843908ae9 (patch)
treea0019bf3f8432200583dc74093157374605bba7d /ext/ffi/lib.rs
parent5819fef2d53b4e2db6060edb8501a5af73235098 (diff)
feat(ext/ffi): Implement FFI fast-call trampoline with Dynasmrt (#15305)
Diffstat (limited to 'ext/ffi/lib.rs')
-rw-r--r--ext/ffi/lib.rs114
1 files changed, 18 insertions, 96 deletions
diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs
index ead9be283..b93638c88 100644
--- a/ext/ffi/lib.rs
+++ b/ext/ffi/lib.rs
@@ -14,7 +14,6 @@ use deno_core::serde_json::json;
use deno_core::serde_json::Value;
use deno_core::serde_v8;
use deno_core::v8;
-use deno_core::v8::fast_api;
use deno_core::Extension;
use deno_core::OpState;
use deno_core::Resource;
@@ -39,15 +38,11 @@ use std::ptr;
use std::rc::Rc;
use std::sync::mpsc::sync_channel;
-#[cfg(not(target_os = "windows"))]
-mod jit_trampoline;
-#[cfg(not(target_os = "windows"))]
-mod tcc;
+mod fast_call;
#[cfg(not(target_pointer_width = "64"))]
compile_error!("platform not supported");
-// Assert assumptions made in `prelude.h`
const _: () = {
assert!(size_of::<c_char>() == 1);
assert!(size_of::<c_short>() == 2);
@@ -90,8 +85,6 @@ 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,
}
@@ -729,50 +722,6 @@ where
))
}
-pub struct FfiFastCallTemplate {
- args: Box<[fast_api::Type]>,
- ret: fast_api::CType,
- symbol_ptr: *const c_void,
-}
-
-impl fast_api::FastFunction for FfiFastCallTemplate {
- fn function(&self) -> *const c_void {
- self.symbol_ptr
- }
-
- fn args(&self) -> &'static [fast_api::Type] {
- Box::leak(self.args.clone())
- }
-
- fn return_type(&self) -> fast_api::CType {
- self.ret
- }
-}
-
-impl From<&NativeType> for fast_api::Type {
- fn from(native_type: &NativeType) -> Self {
- match native_type {
- NativeType::Bool => fast_api::Type::Bool,
- NativeType::U8 | NativeType::U16 | NativeType::U32 => {
- fast_api::Type::Uint32
- }
- NativeType::I8 | NativeType::I16 | NativeType::I32 => {
- fast_api::Type::Int32
- }
- NativeType::F32 => fast_api::Type::Float32,
- NativeType::F64 => fast_api::Type::Float64,
- NativeType::Void => fast_api::Type::Void,
- NativeType::I64 => fast_api::Type::Int64,
- NativeType::U64 => fast_api::Type::Uint64,
- NativeType::ISize => fast_api::Type::Int64,
- NativeType::USize | NativeType::Pointer | NativeType::Function => {
- fast_api::Type::Uint64
- }
- NativeType::Buffer => fast_api::Type::TypedArray(fast_api::CType::Uint8),
- }
- }
-}
-
fn needs_unwrap(rv: NativeType) -> bool {
matches!(
rv,
@@ -796,42 +745,6 @@ fn make_sync_fn<'s>(
scope: &mut v8::HandleScope<'s>,
sym: Box<Symbol>,
) -> v8::Local<'s, v8::Function> {
- #[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 {
- let needs_unwrap = needs_unwrap(sym.result_type);
- let ret = match needs_unwrap {
- true => fast_api::Type::Void,
- false => fast_api::Type::from(&sym.result_type),
- };
-
- let mut args = sym
- .parameter_types
- .iter()
- .map(|t| t.into())
- .collect::<Vec<_>>();
- // recv
- args.insert(0, fast_api::Type::V8Value);
- if needs_unwrap {
- args.push(fast_api::Type::TypedArray(fast_api::CType::Int32));
- }
- let symbol_trampoline =
- jit_trampoline::gen_trampoline(sym.clone()).expect("gen_trampoline");
- fast_ffi_templ = Some(FfiFastCallTemplate {
- args: args.into_boxed_slice(),
- ret: (&ret).into(),
- symbol_ptr: symbol_trampoline.addr,
- });
- fast_allocations = Some(Box::into_raw(symbol_trampoline) as *mut ());
- }
-
let sym = Box::leak(sym);
let builder = v8::FunctionTemplate::builder(
|scope: &mut v8::HandleScope,
@@ -891,8 +804,17 @@ fn make_sync_fn<'s>(
)
.data(v8::External::new(scope, sym as *mut Symbol as *mut _).into());
- let func = if let Some(fast_ffi_templ) = fast_ffi_templ {
- builder.build_fast(scope, &fast_ffi_templ, None)
+ let mut fast_call_alloc = None;
+
+ let func = if fast_call::is_compatible(sym) {
+ let trampoline = fast_call::compile_trampoline(sym);
+ let func = builder.build_fast(
+ scope,
+ &fast_call::make_template(sym, &trampoline),
+ None,
+ );
+ fast_call_alloc = Some(Box::into_raw(Box::new(trampoline)));
+ func
} else {
builder.build(scope)
};
@@ -904,12 +826,12 @@ 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);
- #[cfg(not(target_os = "windows"))]
- if let Some(fast_allocations) = fast_allocations {
- Box::from_raw(fast_allocations as *mut jit_trampoline::Allocation);
- }
+ let _ = unsafe { Box::from_raw(sym) };
+ if let Some(fast_call_ptr) = fast_call_alloc {
+ // fast-call compiled trampoline is unmapped when the MMAP handle is dropped
+ // SAFETY: This is never called twice. pointer obtained
+ // from Box::into_raw, hence, satisfies memory layout requirements.
+ let _ = unsafe { Box::from_raw(fast_call_ptr) };
}
}),
);