wasmtime_runtime/vmcontext/
vm_host_func_context.rs

1//! Definition of `VM*Context` variant for host functions.
2//!
3//! Keep in sync with `wasmtime_environ::VMHostFuncOffsets`.
4
5use wasmtime_environ::VM_HOST_FUNC_MAGIC;
6
7use super::{VMCallerCheckedFuncRef, VMFunctionBody, VMOpaqueContext, VMSharedSignatureIndex};
8use std::{
9    any::Any,
10    ptr::{self, NonNull},
11};
12
13/// The `VM*Context` for host functions.
14///
15/// Its `magic` field must always be `wasmtime_environ::VM_HOST_FUNC_MAGIC`, and
16/// this is how you can determine whether a `VM*Context` is a
17/// `VMHostFuncContext` versus a different kind of context.
18#[repr(C)]
19pub struct VMHostFuncContext {
20    magic: u32,
21    // _padding: u32, // (on 64-bit systems)
22    pub(crate) host_func: NonNull<VMFunctionBody>,
23    wasm_to_host_trampoline: VMCallerCheckedFuncRef,
24    host_state: Box<dyn Any + Send + Sync>,
25}
26
27// Declare that this type is send/sync, it's the responsibility of
28// `VMHostFuncContext::new` callers to uphold this guarantee.
29unsafe impl Send for VMHostFuncContext {}
30unsafe impl Sync for VMHostFuncContext {}
31
32impl VMHostFuncContext {
33    /// Create the context for the given host function.
34    ///
35    /// # Safety
36    ///
37    /// The `host_func` must be a pointer to a host (not Wasm) function and it
38    /// must be `Send` and `Sync`.
39    pub unsafe fn new(
40        host_func: NonNull<VMFunctionBody>,
41        signature: VMSharedSignatureIndex,
42        host_state: Box<dyn Any + Send + Sync>,
43    ) -> Box<VMHostFuncContext> {
44        let wasm_to_host_trampoline = VMCallerCheckedFuncRef {
45            func_ptr: NonNull::new(crate::trampolines::wasm_to_host_trampoline as _).unwrap(),
46            type_index: signature,
47            vmctx: ptr::null_mut(),
48        };
49        let mut ctx = Box::new(VMHostFuncContext {
50            magic: wasmtime_environ::VM_HOST_FUNC_MAGIC,
51            host_func,
52            wasm_to_host_trampoline,
53            host_state,
54        });
55        ctx.wasm_to_host_trampoline.vmctx =
56            VMOpaqueContext::from_vm_host_func_context(&*ctx as *const _ as *mut _);
57        ctx
58    }
59
60    /// Get the Wasm-to-host trampoline for this host function context.
61    pub fn wasm_to_host_trampoline(&self) -> NonNull<VMCallerCheckedFuncRef> {
62        NonNull::from(&self.wasm_to_host_trampoline)
63    }
64
65    /// Get the host state for this host function context.
66    pub fn host_state(&self) -> &(dyn Any + Send + Sync) {
67        &*self.host_state
68    }
69}
70
71impl VMHostFuncContext {
72    /// Helper function to cast between context types using a debug assertion to
73    /// protect against some mistakes.
74    #[inline]
75    pub unsafe fn from_opaque(opaque: *mut VMOpaqueContext) -> *mut VMHostFuncContext {
76        // See comments in `VMContext::from_opaque` for this debug assert
77        debug_assert_eq!((*opaque).magic, VM_HOST_FUNC_MAGIC);
78        opaque.cast()
79    }
80}