Skip to content

Commit

Permalink
fix(ext/ffi): allow opting out of fast ffi calls (denoland#15131)
Browse files Browse the repository at this point in the history
  • Loading branch information
littledivy committed Jul 9, 2022
1 parent 3da182b commit 132c761
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 3 deletions.
2 changes: 2 additions & 0 deletions cli/dts/lib.deno.unstable.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,8 @@ declare namespace Deno {
result: Result;
/** When true, function calls will run on a dedicated blocking thread and will return a Promise resolving to the `result`. */
nonblocking?: NonBlocking;
/** When true, function calls can safely callback into JS or trigger a GC event. Default is `false`. */
callback?: boolean;
}

export interface ForeignStatic<Type extends NativeType = NativeType> {
Expand Down
14 changes: 13 additions & 1 deletion ext/ffi/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ struct Symbol {
ptr: libffi::middle::CodePtr,
parameter_types: Vec<NativeType>,
result_type: NativeType,
can_callback: bool,
}

#[allow(clippy::non_send_fields_in_send_ty)]
Expand Down Expand Up @@ -433,6 +434,13 @@ struct ForeignFunction {
result: NativeType,
#[serde(rename = "nonblocking")]
non_blocking: Option<bool>,
#[serde(rename = "callback")]
#[serde(default = "default_callback")]
callback: bool,
}

fn default_callback() -> bool {
false
}

// ForeignStatic's name and type fields are read and used by
Expand Down Expand Up @@ -599,6 +607,7 @@ where
ptr,
parameter_types: foreign_fn.parameters,
result_type: foreign_fn.result,
can_callback: foreign_fn.callback,
});

resource.symbols.insert(symbol_key, sym.clone());
Expand Down Expand Up @@ -689,7 +698,8 @@ fn make_sync_fn<'s>(
) -> v8::Local<'s, v8::Function> {
let mut fast_ffi_templ = None;

if !sym.parameter_types.iter().any(|t| !is_fast_api(*t))
if !sym.can_callback
&& !sym.parameter_types.iter().any(|t| !is_fast_api(*t))
&& is_fast_api(sym.result_type)
{
let mut args = sym
Expand Down Expand Up @@ -941,6 +951,7 @@ where
result_type,
cif,
ptr: fun_ptr,
..
} = symbol;
let mut ffi_args: Vec<NativeValue> =
Vec::with_capacity(parameter_types.len());
Expand Down Expand Up @@ -1814,6 +1825,7 @@ fn op_ffi_call_nonblocking<'scope>(
ptr,
parameter_types,
result_type,
..
} = symbol.clone();
ffi_call(call_args, &cif, ptr, &parameter_types, result_type)
});
Expand Down
2 changes: 1 addition & 1 deletion test_ffi/tests/ffi_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
const remote = Deno.dlopen(
"dummy_lib.so",
{
method1: { parameters: ["usize", "usize"], result: "void" },
method1: { parameters: ["usize", "usize"], result: "void", callback: true },
method2: { parameters: [], result: "void" },
method3: { parameters: ["usize"], result: "void" },
method4: { parameters: ["isize"], result: "void" },
Expand Down
6 changes: 5 additions & 1 deletion test_ffi/tests/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,12 @@ const dylib = Deno.dlopen(libPath, {
call_stored_function: {
parameters: [],
result: "void",
callback: true,
},
call_stored_function_2: {
parameters: ["u8"],
result: "void",
callback: true,
},
// Statics
"static_u32": {
Expand Down Expand Up @@ -372,12 +374,14 @@ assertThrows(
"hi",
);

const { call_stored_function } = dylib.symbols;

dylib.symbols.call_fn_ptr(ptr(logCallback));
dylib.symbols.call_fn_ptr_many_parameters(ptr(logManyParametersCallback));
dylib.symbols.call_fn_ptr_return_u8(ptr(returnU8Callback));
dylib.symbols.call_fn_ptr_return_buffer(ptr(returnBufferCallback));
dylib.symbols.store_function(ptr(logCallback));
dylib.symbols.call_stored_function();
call_stored_function();
dylib.symbols.store_function_2(ptr(add10Callback));
dylib.symbols.call_stored_function_2(20);

Expand Down

0 comments on commit 132c761

Please sign in to comment.