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::runtime::vm::{StoreBox, VMFuncRef}; 7 use std::any::Any; 8 use 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)] 17 pub 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 24 impl 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)] 77 pub 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] 85 fn 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 94 impl 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 } 138