Add API to statically assert signature of a Func (#955)
* Add API to statically assert signature of a `Func` This commit add a family of APIs to `Func` named `getN` where `N` is the number of arguments. Each function will attempt to statically assert the signature of a `Func` and, if matching, returns a corresponding closure which can be used to invoke the underlying function. The purpose of this commit is to add a highly optimized way to enter a wasm module, performing type checks up front and avoiding all the costs of boxing and unboxing arguments within a `Val`. In general this should be much more optimized than the previous `call` API for entering a wasm module, if the signature is statically known. * rustfmt * Remove stray debugging
This commit is contained in:
@@ -8,7 +8,7 @@ use crate::jit_int::GdbJitImageRegistration;
|
||||
use crate::memory::LinearMemory;
|
||||
use crate::signalhandlers;
|
||||
use crate::table::Table;
|
||||
use crate::traphandlers::{wasmtime_call, Trap};
|
||||
use crate::traphandlers::{catch_traps, Trap};
|
||||
use crate::vmcontext::{
|
||||
VMBuiltinFunctionsArray, VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMFunctionImport,
|
||||
VMGlobalDefinition, VMGlobalImport, VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex,
|
||||
@@ -367,8 +367,15 @@ impl Instance {
|
||||
};
|
||||
|
||||
// Make the call.
|
||||
unsafe { wasmtime_call(callee_vmctx, self.vmctx_ptr(), callee_address) }
|
||||
unsafe {
|
||||
catch_traps(callee_vmctx, || {
|
||||
mem::transmute::<
|
||||
*const VMFunctionBody,
|
||||
unsafe extern "C" fn(*mut VMContext, *mut VMContext),
|
||||
>(callee_address)(callee_vmctx, self.vmctx_ptr())
|
||||
})
|
||||
.map_err(InstantiationError::StartTrap)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the offset from the vmctx pointer to its containing Instance.
|
||||
|
||||
@@ -44,7 +44,7 @@ pub use crate::mmap::Mmap;
|
||||
pub use crate::sig_registry::SignatureRegistry;
|
||||
pub use crate::trap_registry::{TrapDescription, TrapRegistration, TrapRegistry};
|
||||
pub use crate::traphandlers::resume_panic;
|
||||
pub use crate::traphandlers::{raise_user_trap, wasmtime_call, wasmtime_call_trampoline, Trap};
|
||||
pub use crate::traphandlers::{catch_traps, raise_user_trap, wasmtime_call_trampoline, Trap};
|
||||
pub use crate::vmcontext::{
|
||||
VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMFunctionImport, VMGlobalDefinition,
|
||||
VMGlobalImport, VMInvokeArgument, VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex,
|
||||
|
||||
@@ -9,23 +9,15 @@ use std::any::Any;
|
||||
use std::cell::Cell;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use wasmtime_environ::ir;
|
||||
|
||||
extern "C" {
|
||||
fn WasmtimeCallTrampoline(
|
||||
fn RegisterSetjmp(
|
||||
jmp_buf: *mut *const u8,
|
||||
vmctx: *mut u8,
|
||||
caller_vmctx: *mut u8,
|
||||
trampoline: *const VMFunctionBody,
|
||||
callee: *const VMFunctionBody,
|
||||
values_vec: *mut u8,
|
||||
) -> i32;
|
||||
fn WasmtimeCall(
|
||||
jmp_buf: *mut *const u8,
|
||||
vmctx: *mut u8,
|
||||
caller_vmctx: *mut u8,
|
||||
callee: *const VMFunctionBody,
|
||||
callback: extern "C" fn(*mut u8),
|
||||
payload: *mut u8,
|
||||
) -> i32;
|
||||
fn Unwind(jmp_buf: *const u8) -> !;
|
||||
}
|
||||
@@ -154,33 +146,36 @@ pub unsafe fn wasmtime_call_trampoline(
|
||||
callee: *const VMFunctionBody,
|
||||
values_vec: *mut u8,
|
||||
) -> Result<(), Trap> {
|
||||
CallThreadState::new(vmctx).with(|cx| {
|
||||
WasmtimeCallTrampoline(
|
||||
cx.jmp_buf.as_ptr(),
|
||||
vmctx as *mut u8,
|
||||
caller_vmctx as *mut u8,
|
||||
trampoline,
|
||||
callee,
|
||||
values_vec,
|
||||
)
|
||||
catch_traps(vmctx, || {
|
||||
mem::transmute::<
|
||||
_,
|
||||
extern "C" fn(*mut VMContext, *mut VMContext, *const VMFunctionBody, *mut u8),
|
||||
>(trampoline)(vmctx, caller_vmctx, callee, values_vec)
|
||||
})
|
||||
}
|
||||
|
||||
/// Call the wasm function pointed to by `callee`, which has no arguments or
|
||||
/// return values.
|
||||
pub unsafe fn wasmtime_call(
|
||||
vmctx: *mut VMContext,
|
||||
caller_vmctx: *mut VMContext,
|
||||
callee: *const VMFunctionBody,
|
||||
) -> Result<(), Trap> {
|
||||
CallThreadState::new(vmctx).with(|cx| {
|
||||
WasmtimeCall(
|
||||
/// Catches any wasm traps that happen within the execution of `closure`,
|
||||
/// returning them as a `Result`.
|
||||
///
|
||||
/// Highly unsafe since `closure` won't have any dtors run.
|
||||
pub unsafe fn catch_traps<F>(vmctx: *mut VMContext, mut closure: F) -> Result<(), Trap>
|
||||
where
|
||||
F: FnMut(),
|
||||
{
|
||||
return CallThreadState::new(vmctx).with(|cx| {
|
||||
RegisterSetjmp(
|
||||
cx.jmp_buf.as_ptr(),
|
||||
vmctx as *mut u8,
|
||||
caller_vmctx as *mut u8,
|
||||
callee,
|
||||
call_closure::<F>,
|
||||
&mut closure as *mut F as *mut u8,
|
||||
)
|
||||
})
|
||||
});
|
||||
|
||||
extern "C" fn call_closure<F>(payload: *mut u8)
|
||||
where
|
||||
F: FnMut(),
|
||||
{
|
||||
unsafe { (*(payload as *mut F))() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Temporary state stored on the stack which is registered in the `tls` module
|
||||
|
||||
Reference in New Issue
Block a user