* Add `*_unchecked` variants of `Func` APIs for the C API This commit is what is hopefully going to be my last installment within the saga of optimizing function calls in/out of WebAssembly modules in the C API. This is yet another alternative approach to #3345 (sorry) but also contains everything necessary to make the C API fast. As in #3345 the general idea is just moving checks out of the call path in the same style of `TypedFunc`. This new strategy takes inspiration from previously learned attempts effectively "just" exposes how we previously passed `*mut u128` through trampolines for arguments/results. This storage format is formalized through a new `ValRaw` union that is exposed from the `wasmtime` crate. By doing this it made it relatively easy to expose two new APIs: * `Func::new_unchecked` * `Func::call_unchecked` These are the same as their checked equivalents except that they're `unsafe` and they work with `*mut ValRaw` rather than safe slices of `Val`. Working with these eschews type checks and such and requires callers/embedders to do the right thing. These two new functions are then exposed via the C API with new functions, enabling C to have a fast-path of calling/defining functions. This fast path is akin to `Func::wrap` in Rust, although that API can't be built in C due to C not having generics in the same way that Rust has. For some benchmarks, the benchmarks here are: * `nop` - Call a wasm function from the host that does nothing and returns nothing. * `i64` - Call a wasm function from the host, the wasm function calls a host function, and the host function returns an `i64` all the way out to the original caller. * `many` - Call a wasm function from the host, the wasm calls host function with 5 `i32` parameters, and then an `i64` result is returned back to the original host * `i64` host - just the overhead of the wasm calling the host, so the wasm calls the host function in a loop. * `many` host - same as `i64` host, but calling the `many` host function. All numbers in this table are in nanoseconds, and this is just one measurement as well so there's bound to be some variation in the precise numbers here. | Name | Rust | C (before) | C (after) | |-----------|------|------------|-----------| | nop | 19 | 112 | 25 | | i64 | 22 | 207 | 32 | | many | 27 | 189 | 34 | | i64 host | 2 | 38 | 5 | | many host | 7 | 75 | 8 | The main conclusion here is that the C API is significantly faster than before when using the `*_unchecked` variants of APIs. The Rust implementation is still the ceiling (or floor I guess?) for performance The main reason that C is slower than Rust is that a little bit more has to travel through memory where on the Rust side of things we can monomorphize and inline a bit more to get rid of that. Overall though the costs are way way down from where they were originally and I don't plan on doing a whole lot more myself at this time. There's various things we theoretically could do I've considered but implementation-wise I think they'll be much more weighty. * Tweak `wasmtime_externref_t` API comments
102 lines
3.7 KiB
Rust
102 lines
3.7 KiB
Rust
//! Runtime library support for Wasmtime.
|
|
|
|
#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
|
|
#![warn(unused_import_braces)]
|
|
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
|
|
#![cfg_attr(
|
|
feature = "cargo-clippy",
|
|
allow(clippy::new_without_default, clippy::new_without_default)
|
|
)]
|
|
#![cfg_attr(
|
|
feature = "cargo-clippy",
|
|
warn(
|
|
clippy::float_arithmetic,
|
|
clippy::mut_mut,
|
|
clippy::nonminimal_bool,
|
|
clippy::map_unwrap_or,
|
|
clippy::clippy::print_stdout,
|
|
clippy::unicode_not_nfc,
|
|
clippy::use_self
|
|
)
|
|
)]
|
|
|
|
use std::error::Error;
|
|
|
|
mod export;
|
|
mod externref;
|
|
mod imports;
|
|
mod instance;
|
|
mod jit_int;
|
|
mod memory;
|
|
mod mmap;
|
|
mod table;
|
|
mod traphandlers;
|
|
mod vmcontext;
|
|
|
|
pub mod debug_builtins;
|
|
pub mod libcalls;
|
|
|
|
pub use crate::export::*;
|
|
pub use crate::externref::*;
|
|
pub use crate::imports::Imports;
|
|
pub use crate::instance::{
|
|
InstanceAllocationRequest, InstanceAllocator, InstanceHandle, InstanceLimits,
|
|
InstantiationError, LinkError, ModuleLimits, OnDemandInstanceAllocator,
|
|
PoolingAllocationStrategy, PoolingInstanceAllocator, ResourceLimiter, DEFAULT_INSTANCE_LIMIT,
|
|
DEFAULT_MEMORY_LIMIT, DEFAULT_TABLE_LIMIT,
|
|
};
|
|
pub use crate::jit_int::GdbJitImageRegistration;
|
|
pub use crate::memory::{Memory, RuntimeLinearMemory, RuntimeMemoryCreator};
|
|
pub use crate::mmap::Mmap;
|
|
pub use crate::table::{Table, TableElement};
|
|
pub use crate::traphandlers::{
|
|
catch_traps, init_traps, raise_lib_trap, raise_user_trap, resume_panic, tls_eager_initialize,
|
|
SignalHandler, TlsRestore, Trap,
|
|
};
|
|
pub use crate::vmcontext::{
|
|
VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMFunctionImport, VMGlobalDefinition,
|
|
VMGlobalImport, VMInterrupts, VMInvokeArgument, VMMemoryDefinition, VMMemoryImport,
|
|
VMSharedSignatureIndex, VMTableDefinition, VMTableImport, VMTrampoline, ValRaw,
|
|
};
|
|
|
|
/// Version number of this crate.
|
|
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
|
|
/// Dynamic runtime functionality needed by this crate throughout the execution
|
|
/// of a wasm instance.
|
|
///
|
|
/// This trait is used to store a raw pointer trait object within each
|
|
/// `VMContext`. This raw pointer trait object points back to the
|
|
/// `wasmtime::Store` internally but is type-erased so this `wasmtime_runtime`
|
|
/// crate doesn't need the entire `wasmtime` crate to build.
|
|
///
|
|
/// Note that this is an extra-unsafe trait because no heed is paid to the
|
|
/// lifetime of this store or the Send/Sync-ness of this store. All of that must
|
|
/// be respected by embedders (e.g. the `wasmtime::Store` structure). The theory
|
|
/// is that `wasmtime::Store` handles all this correctly.
|
|
pub unsafe trait Store {
|
|
/// Returns the raw pointer in memory where this store's shared
|
|
/// `VMInterrupts` structure is located.
|
|
///
|
|
/// Used to configure `VMContext` initialization and store the right pointer
|
|
/// in the `VMContext`.
|
|
fn vminterrupts(&self) -> *mut VMInterrupts;
|
|
|
|
/// Returns the externref management structures necessary for this store.
|
|
///
|
|
/// The first element returned is the table in which externrefs are stored
|
|
/// throughout wasm execution, and the second element is how to look up
|
|
/// module information for gc requests.
|
|
fn externref_activations_table(
|
|
&mut self,
|
|
) -> (&mut VMExternRefActivationsTable, &dyn ModuleInfoLookup);
|
|
|
|
/// Returns a reference to the store's limiter for limiting resources, if any.
|
|
fn limiter(&mut self) -> Option<&mut dyn ResourceLimiter>;
|
|
|
|
/// Callback invoked whenever fuel runs out by a wasm instance. If an error
|
|
/// is returned that's raised as a trap. Otherwise wasm execution will
|
|
/// continue as normal.
|
|
fn out_of_gas(&mut self) -> Result<(), Box<dyn Error + Send + Sync>>;
|
|
}
|