wasmtime/runtime/vm/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::{VMArrayCallNative, VMOpaqueContext};
6use crate::prelude::*;
7use crate::runtime::vm::{StoreBox, VMFuncRef};
8use core::any::Any;
9use core::ptr::NonNull;
10use wasmtime_environ::{VMSharedTypeIndex, VM_ARRAY_CALL_HOST_FUNC_MAGIC};
11
12/// The `VM*Context` for array-call host functions.
13///
14/// Its `magic` field must always be
15/// `wasmtime_environ::VM_ARRAY_CALL_HOST_FUNC_MAGIC`, and this is how you can
16/// determine whether a `VM*Context` is a `VMArrayCallHostFuncContext` versus a
17/// different kind of context.
18#[repr(C)]
19pub struct VMArrayCallHostFuncContext {
20    magic: u32,
21    // _padding: u32, // (on 64-bit systems)
22    pub(crate) func_ref: VMFuncRef,
23    host_state: Box<dyn Any + Send + Sync>,
24}
25
26impl VMArrayCallHostFuncContext {
27    /// Create the context for the given host function.
28    ///
29    /// # Safety
30    ///
31    /// The `host_func` must be a pointer to a host (not Wasm) function and it
32    /// must be `Send` and `Sync`.
33    pub unsafe fn new(
34        host_func: VMArrayCallNative,
35        type_index: VMSharedTypeIndex,
36        host_state: Box<dyn Any + Send + Sync>,
37    ) -> StoreBox<VMArrayCallHostFuncContext> {
38        let ctx = StoreBox::new(VMArrayCallHostFuncContext {
39            magic: wasmtime_environ::VM_ARRAY_CALL_HOST_FUNC_MAGIC,
40            func_ref: VMFuncRef {
41                array_call: NonNull::new(host_func as *mut u8).unwrap().cast().into(),
42                type_index,
43                wasm_call: None,
44                vmctx: NonNull::dangling().into(),
45            },
46            host_state,
47        });
48        let vmctx = VMOpaqueContext::from_vm_array_call_host_func_context(ctx.get());
49        unsafe {
50            ctx.get().as_mut().func_ref.vmctx = vmctx.into();
51        }
52        ctx
53    }
54
55    /// Get the host state for this host function context.
56    #[inline]
57    pub fn host_state(&self) -> &(dyn Any + Send + Sync) {
58        &*self.host_state
59    }
60
61    /// Get this context's `VMFuncRef`.
62    #[inline]
63    pub fn func_ref(&self) -> &VMFuncRef {
64        &self.func_ref
65    }
66
67    /// Helper function to cast between context types using a debug assertion to
68    /// protect against some mistakes.
69    #[inline]
70    pub unsafe fn from_opaque(
71        opaque: NonNull<VMOpaqueContext>,
72    ) -> NonNull<VMArrayCallHostFuncContext> {
73        // See comments in `VMContext::from_opaque` for this debug assert
74        debug_assert_eq!(opaque.as_ref().magic, VM_ARRAY_CALL_HOST_FUNC_MAGIC);
75        opaque.cast()
76    }
77}
78
79#[test]
80fn vmarray_call_host_func_context_offsets() {
81    use core::mem::offset_of;
82    use wasmtime_environ::{HostPtr, PtrSize};
83    assert_eq!(
84        usize::from(HostPtr.vmarray_call_host_func_context_func_ref()),
85        offset_of!(VMArrayCallHostFuncContext, func_ref)
86    );
87}