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