diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml index bd9f2722a297..46e6378b4a6e 100644 --- a/crates/wasmtime/Cargo.toml +++ b/crates/wasmtime/Cargo.toml @@ -126,6 +126,7 @@ default = [ 'component-model', 'threads', 'std', + 'call-hook', ] # An on-by-default feature enabling runtime compilation of WebAssembly modules @@ -261,3 +262,9 @@ std = [ 'object/std', 'once_cell/std', ] + +# Enables support for the `Store::call_hook` API which enables injecting custom +# logic around all entries/exits from WebAssembly. This has a slight performance +# cost for all host functions so is provided as a compile-time feature if +# embedders would like to disable it. +call-hook = [] diff --git a/crates/wasmtime/src/lib.rs b/crates/wasmtime/src/lib.rs index 69203cf169d9..fe32a3d6c75c 100644 --- a/crates/wasmtime/src/lib.rs +++ b/crates/wasmtime/src/lib.rs @@ -254,6 +254,11 @@ //! * `threads` - Enabled by default, this enables compile-time support for the //! WebAssembly `threads` proposal, notably shared memories. //! +//! * `call-hook` - Enabled by default, this enables support for the +//! [`Store::call_hook`] API. This incurs a small overhead on all +//! entries/exits from WebAssembly and may want to be disabled by some +//! embedders. +//! //! More crate features can be found in the [manifest] of Wasmtime itself for //! seeing what can be enabled and disabled. //! diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index 0750ad42451b..0d8eaca2da2c 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -49,7 +49,7 @@ pub use linker::*; pub use memory::*; pub use module::{Module, ModuleExport}; pub use resources::*; -#[cfg(feature = "async")] +#[cfg(all(feature = "async", feature = "call-hook"))] pub use store::CallHookHandler; pub use store::{ AsContext, AsContextMut, CallHook, Store, StoreContext, StoreContextMut, UpdateDeadline, diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs index 83aa99f68764..4c91d58e2ce3 100644 --- a/crates/wasmtime/src/runtime/store.rs +++ b/crates/wasmtime/src/runtime/store.rs @@ -90,7 +90,7 @@ use crate::runtime::vm::{ use crate::trampoline::VMHostGlobalContext; use crate::RootSet; use crate::{module::ModuleRegistry, Engine, Module, Trap, Val, ValRaw}; -use crate::{Global, Instance, Memory, RootScope, Table}; +use crate::{Global, Instance, Memory, RootScope, Table, Uninhabited}; use alloc::sync::Arc; use anyhow::{anyhow, bail, Result}; use core::cell::UnsafeCell; @@ -234,7 +234,7 @@ enum ResourceLimiterInner { } /// An object that can take callbacks when the runtime enters or exits hostcalls. -#[cfg(feature = "async")] +#[cfg(all(feature = "async", feature = "call-hook"))] #[async_trait::async_trait] pub trait CallHookHandler: Send { /// A callback to run when wasmtime is about to enter a host call, or when about to @@ -243,9 +243,15 @@ pub trait CallHookHandler: Send { } enum CallHookInner { + #[cfg(feature = "call-hook")] Sync(Box, CallHook) -> Result<()> + Send + Sync>), - #[cfg(feature = "async")] + #[cfg(all(feature = "async", feature = "call-hook"))] Async(Box + Send + Sync>), + #[allow(dead_code)] + ForceTypeParameterToBeUsed { + uninhabited: Uninhabited, + _marker: marker::PhantomData, + }, } /// What to do after returning from a callback when the engine epoch reaches @@ -751,7 +757,7 @@ impl Store { /// /// After this function returns a trap, it may be called for subsequent /// returns to host or wasm code as the trap propagates to the root call. - #[cfg(feature = "async")] + #[cfg(all(feature = "async", feature = "call-hook"))] pub fn call_hook_async(&mut self, hook: impl CallHookHandler + Send + Sync + 'static) { self.inner.call_hook = Some(CallHookInner::Async(Box::new(hook))); } @@ -770,6 +776,7 @@ impl Store { /// /// After this function returns a trap, it may be called for subsequent returns /// to host or wasm code as the trap propagates to the root call. + #[cfg(feature = "call-hook")] pub fn call_hook( &mut self, hook: impl FnMut(StoreContextMut<'_, T>, CallHook) -> Result<()> + Send + Sync + 'static, @@ -1156,9 +1163,10 @@ impl StoreInner { fn invoke_call_hook(&mut self, call_hook: &mut CallHookInner, s: CallHook) -> Result<()> { match call_hook { + #[cfg(feature = "call-hook")] CallHookInner::Sync(hook) => hook((&mut *self).as_context_mut(), s), - #[cfg(feature = "async")] + #[cfg(all(feature = "async", feature = "call-hook"))] CallHookInner::Async(handler) => unsafe { self.inner .async_cx() @@ -1169,6 +1177,11 @@ impl StoreInner { .as_mut(), )? }, + + CallHookInner::ForceTypeParameterToBeUsed { uninhabited, .. } => { + let _ = s; + match *uninhabited {} + } } } }