mirror of
https://github.com/denoland/deno.git
synced 2024-12-12 02:27:46 -05:00
perf(ext/ffi): support Uint8Array in fast calls (#15319)
This commit is contained in:
parent
210e1445f2
commit
a1b989c842
5 changed files with 48 additions and 7 deletions
|
@ -32,7 +32,8 @@ fn native_arg_to_c(ty: &NativeType) -> &'static str {
|
||||||
NativeType::I64 => "int64_t",
|
NativeType::I64 => "int64_t",
|
||||||
NativeType::ISize => "intptr_t",
|
NativeType::ISize => "intptr_t",
|
||||||
NativeType::USize => "uintptr_t",
|
NativeType::USize => "uintptr_t",
|
||||||
NativeType::Pointer | NativeType::Function => "void*",
|
NativeType::Pointer => "struct FastApiTypedArray*",
|
||||||
|
NativeType::Function => "void*",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,12 +86,16 @@ pub(crate) fn codegen(sym: &crate::Symbol) -> String {
|
||||||
c += ") {\n";
|
c += ") {\n";
|
||||||
// return func(p0, p1, ...);
|
// return func(p0, p1, ...);
|
||||||
c += " return func(";
|
c += " return func(";
|
||||||
for (i, _) in sym.parameter_types.iter().enumerate() {
|
for (i, ty) in sym.parameter_types.iter().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
c += ", ";
|
c += ", ";
|
||||||
}
|
}
|
||||||
|
if matches!(ty, NativeType::Pointer) {
|
||||||
|
let _ = write!(c, "p{i}->data");
|
||||||
|
} else {
|
||||||
let _ = write!(c, "p{i}");
|
let _ = write!(c, "p{i}");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
c += ");\n}\n\n";
|
c += ");\n}\n\n";
|
||||||
c
|
c
|
||||||
}
|
}
|
||||||
|
@ -103,7 +108,6 @@ pub(crate) fn gen_trampoline(
|
||||||
// SAFETY: symbol satisfies ABI requirement.
|
// SAFETY: symbol satisfies ABI requirement.
|
||||||
unsafe { ctx.add_symbol(cstr!("func"), sym.ptr.0 as *const c_void) };
|
unsafe { ctx.add_symbol(cstr!("func"), sym.ptr.0 as *const c_void) };
|
||||||
let c = codegen(&sym);
|
let c = codegen(&sym);
|
||||||
|
|
||||||
ctx.compile_string(cstr!(c))?;
|
ctx.compile_string(cstr!(c))?;
|
||||||
let alloc = Allocation {
|
let alloc = Allocation {
|
||||||
addr: ctx.relocate_and_get_symbol(cstr!("func_trampoline"))?,
|
addr: ctx.relocate_and_get_symbol(cstr!("func_trampoline"))?,
|
||||||
|
@ -172,6 +176,20 @@ mod tests {
|
||||||
\n return func(p0, p1);\n\
|
\n return func(p0, p1);\n\
|
||||||
}\n\n",
|
}\n\n",
|
||||||
);
|
);
|
||||||
|
assert_codegen(
|
||||||
|
codegen(vec![NativeType::Pointer, NativeType::U32], NativeType::U32),
|
||||||
|
"extern uint32_t func(void* p0, uint32_t p1);\n\n\
|
||||||
|
uint32_t func_trampoline(void* recv, struct FastApiTypedArray* p0, uint32_t p1) {\
|
||||||
|
\n return func(p0->data, p1);\n\
|
||||||
|
}\n\n",
|
||||||
|
);
|
||||||
|
assert_codegen(
|
||||||
|
codegen(vec![NativeType::Pointer, NativeType::Pointer], NativeType::U32),
|
||||||
|
"extern uint32_t func(void* p0, void* p1);\n\n\
|
||||||
|
uint32_t func_trampoline(void* recv, struct FastApiTypedArray* p0, struct FastApiTypedArray* p1) {\
|
||||||
|
\n return func(p0->data, p1->data);\n\
|
||||||
|
}\n\n",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -746,9 +746,8 @@ impl From<&NativeType> for fast_api::Type {
|
||||||
NativeType::I64 => fast_api::Type::Int64,
|
NativeType::I64 => fast_api::Type::Int64,
|
||||||
NativeType::U64 => fast_api::Type::Uint64,
|
NativeType::U64 => fast_api::Type::Uint64,
|
||||||
NativeType::ISize => fast_api::Type::Int64,
|
NativeType::ISize => fast_api::Type::Int64,
|
||||||
NativeType::USize | NativeType::Function | NativeType::Pointer => {
|
NativeType::USize | NativeType::Function => fast_api::Type::Uint64,
|
||||||
fast_api::Type::Uint64
|
NativeType::Pointer => fast_api::Type::TypedArray(fast_api::CType::Uint8),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,3 +17,9 @@ typedef unsigned long int uint64_t;
|
||||||
/* Types for `void *' pointers. */
|
/* Types for `void *' pointers. */
|
||||||
typedef long int intptr_t;
|
typedef long int intptr_t;
|
||||||
typedef unsigned long int uintptr_t;
|
typedef unsigned long int uintptr_t;
|
||||||
|
|
||||||
|
// https://source.chromium.org/chromium/chromium/src/+/main:v8/include/v8-fast-api-calls.h;l=336
|
||||||
|
struct FastApiTypedArray {
|
||||||
|
uintptr_t length_;
|
||||||
|
void* data;
|
||||||
|
};
|
||||||
|
|
|
@ -94,6 +94,16 @@ pub extern "C" fn add_f64(a: f64, b: f64) -> f64 {
|
||||||
a + b
|
a + b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn hash(ptr: *const u8, length: u32) -> u32 {
|
||||||
|
let buf = std::slice::from_raw_parts(ptr, length as usize);
|
||||||
|
let mut hash: u32 = 0;
|
||||||
|
for byte in buf {
|
||||||
|
hash = hash.wrapping_mul(0x10001000).wrapping_add(*byte as u32);
|
||||||
|
}
|
||||||
|
hash
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn sleep_blocking(ms: u64) {
|
pub extern "C" fn sleep_blocking(ms: u64) {
|
||||||
let duration = Duration::from_millis(ms);
|
let duration = Duration::from_millis(ms);
|
||||||
|
|
|
@ -12,6 +12,7 @@ const libPath = `${targetDir}/${libPrefix}test_ffi.${libSuffix}`;
|
||||||
const dylib = Deno.dlopen(libPath, {
|
const dylib = Deno.dlopen(libPath, {
|
||||||
"nop": { parameters: [], result: "void" },
|
"nop": { parameters: [], result: "void" },
|
||||||
"add_u32": { parameters: ["u32", "u32"], result: "u32" },
|
"add_u32": { parameters: ["u32", "u32"], result: "u32" },
|
||||||
|
"hash": { parameters: ["pointer", "u32"], result: "u32" },
|
||||||
"nop_u8": { parameters: ["u8"], result: "void" },
|
"nop_u8": { parameters: ["u8"], result: "void" },
|
||||||
"nop_i8": { parameters: ["i8"], result: "void" },
|
"nop_i8": { parameters: ["i8"], result: "void" },
|
||||||
"nop_u16": { parameters: ["u16"], result: "void" },
|
"nop_u16": { parameters: ["u16"], result: "void" },
|
||||||
|
@ -231,6 +232,13 @@ Deno.bench("add_u32()", () => {
|
||||||
add_u32(1, 2);
|
add_u32(1, 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const bytes = new Uint8Array(64);
|
||||||
|
|
||||||
|
const { hash } = dylib.symbols;
|
||||||
|
Deno.bench("hash()", () => {
|
||||||
|
hash(bytes, bytes.byteLength);
|
||||||
|
});
|
||||||
|
|
||||||
const { nop_u8 } = dylib.symbols;
|
const { nop_u8 } = dylib.symbols;
|
||||||
Deno.bench("nop_u8()", () => {
|
Deno.bench("nop_u8()", () => {
|
||||||
nop_u8(100);
|
nop_u8(100);
|
||||||
|
|
Loading…
Reference in a new issue