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