1 //! Definition of `VM*Context` variant for host functions. 2 //! 3 //! Keep in sync with `wasmtime_environ::VMHostFuncOffsets`. 4 5 use super::{VMArrayCallNative, VMOpaqueContext}; 6 use crate::prelude::*; 7 use crate::runtime::vm::{StoreBox, VMFuncRef}; 8 use core::any::Any; 9 use core::ptr::NonNull; 10 use wasmtime_environ::{VM_ARRAY_CALL_HOST_FUNC_MAGIC, VMSharedTypeIndex}; 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)] 19 pub 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 26 impl 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 unsafe { 75 debug_assert_eq!(opaque.as_ref().magic, VM_ARRAY_CALL_HOST_FUNC_MAGIC); 76 } 77 opaque.cast() 78 } 79 } 80 81 #[test] 82 fn vmarray_call_host_func_context_offsets() { 83 use core::mem::offset_of; 84 use wasmtime_environ::{HostPtr, PtrSize}; 85 assert_eq!( 86 usize::from(HostPtr.vmarray_call_host_func_context_func_ref()), 87 offset_of!(VMArrayCallHostFuncContext, func_ref) 88 ); 89 } 90