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 super::VMOpaqueContext;
6use crate::{StoreBox, VMFuncRef};
7use std::any::Any;
8use wasmtime_environ::{VM_ARRAY_CALL_HOST_FUNC_MAGIC, VM_NATIVE_CALL_HOST_FUNC_MAGIC};
9
10/// The `VM*Context` for array-call host functions.
11///
12/// Its `magic` field must always be
13/// `wasmtime_environ::VM_ARRAY_CALL_HOST_FUNC_MAGIC`, and this is how you can
14/// determine whether a `VM*Context` is a `VMArrayCallHostFuncContext` versus a
15/// different kind of context.
16#[repr(C)]
17pub struct VMArrayCallHostFuncContext {
18    magic: u32,
19    // _padding: u32, // (on 64-bit systems)
20    pub(crate) func_ref: VMFuncRef,
21    host_state: Box<dyn Any + Send + Sync>,
22}
23
24impl VMArrayCallHostFuncContext {
25    /// Create the context for the given host function.
26    ///
27    /// # Safety
28    ///
29    /// The `host_func` must be a pointer to a host (not Wasm) function and it
30    /// must be `Send` and `Sync`.
31    pub unsafe fn new(
32        func_ref: VMFuncRef,
33        host_state: Box<dyn Any + Send + Sync>,
34    ) -> StoreBox<VMArrayCallHostFuncContext> {
35        debug_assert!(func_ref.vmctx.is_null());
36        let ctx = StoreBox::new(VMArrayCallHostFuncContext {
37            magic: wasmtime_environ::VM_ARRAY_CALL_HOST_FUNC_MAGIC,
38            func_ref,
39            host_state,
40        });
41        let vmctx = VMOpaqueContext::from_vm_array_call_host_func_context(ctx.get());
42        unsafe {
43            (*ctx.get()).func_ref.vmctx = vmctx;
44        }
45        ctx
46    }
47
48    /// Get the host state for this host function context.
49    #[inline]
50    pub fn host_state(&self) -> &(dyn Any + Send + Sync) {
51        &*self.host_state
52    }
53
54    /// Get this context's `VMFuncRef`.
55    #[inline]
56    pub fn func_ref(&self) -> &VMFuncRef {
57        &self.func_ref
58    }
59
60    /// Helper function to cast between context types using a debug assertion to
61    /// protect against some mistakes.
62    #[inline]
63    pub unsafe fn from_opaque(opaque: *mut VMOpaqueContext) -> *mut VMArrayCallHostFuncContext {
64        // See comments in `VMContext::from_opaque` for this debug assert
65        debug_assert_eq!((*opaque).magic, VM_ARRAY_CALL_HOST_FUNC_MAGIC);
66        opaque.cast()
67    }
68}
69
70/// The `VM*Context` for native-call host functions.
71///
72/// Its `magic` field must always be
73/// `wasmtime_environ::VM_NATIVE_CALL_HOST_FUNC_MAGIC`, and this is how you can
74/// determine whether a `VM*Context` is a `VMNativeCallHostFuncContext` versus a
75/// different kind of context.
76#[repr(C)]
77pub struct VMNativeCallHostFuncContext {
78    magic: u32,
79    // _padding: u32, // (on 64-bit systems)
80    func_ref: VMFuncRef,
81    host_state: Box<dyn Any + Send + Sync>,
82}
83
84#[test]
85fn vmnative_call_host_func_context_offsets() {
86    use memoffset::offset_of;
87    use wasmtime_environ::{HostPtr, PtrSize};
88    assert_eq!(
89        usize::from(HostPtr.vmnative_call_host_func_context_func_ref()),
90        offset_of!(VMNativeCallHostFuncContext, func_ref)
91    );
92}
93
94impl VMNativeCallHostFuncContext {
95    /// Create the context for the given host function.
96    ///
97    /// # Safety
98    ///
99    /// The `host_func` must be a pointer to a host (not Wasm) function and it
100    /// must be `Send` and `Sync`.
101    pub unsafe fn new(
102        func_ref: VMFuncRef,
103        host_state: Box<dyn Any + Send + Sync>,
104    ) -> StoreBox<VMNativeCallHostFuncContext> {
105        let ctx = StoreBox::new(VMNativeCallHostFuncContext {
106            magic: wasmtime_environ::VM_NATIVE_CALL_HOST_FUNC_MAGIC,
107            func_ref,
108            host_state,
109        });
110        let vmctx = VMOpaqueContext::from_vm_native_call_host_func_context(ctx.get());
111        unsafe {
112            (*ctx.get()).func_ref.vmctx = vmctx;
113        }
114        ctx
115    }
116
117    /// Get the host state for this host function context.
118    #[inline]
119    pub fn host_state(&self) -> &(dyn Any + Send + Sync) {
120        &*self.host_state
121    }
122
123    /// Get this context's `VMFuncRef`.
124    #[inline]
125    pub fn func_ref(&self) -> &VMFuncRef {
126        &self.func_ref
127    }
128
129    /// Helper function to cast between context types using a debug assertion to
130    /// protect against some mistakes.
131    #[inline]
132    pub unsafe fn from_opaque(opaque: *mut VMOpaqueContext) -> *mut VMNativeCallHostFuncContext {
133        // See comments in `VMContext::from_opaque` for this debug assert
134        debug_assert_eq!((*opaque).magic, VM_NATIVE_CALL_HOST_FUNC_MAGIC);
135        opaque.cast()
136    }
137}