Change some VMContext pointers to () pointers (#4190)

* Change some `VMContext` pointers to `()` pointers

This commit is motivated by my work on the component model
implementation for imported functions. Currently all context pointers in
wasm are `*mut VMContext` but with the component model my plan is to
make some pointers instead along the lines of `*mut VMComponentContext`.
In doing this though one worry I have is breaking what has otherwise
been a core invariant of Wasmtime for quite some time, subtly
introducing bugs by accident.

To help assuage my worry I've opted here to erase knowledge of
`*mut VMContext` where possible. Instead where applicable a context
pointer is simply known as `*mut ()` and the embedder doesn't actually
know anything about this context beyond the value of the pointer. This
will help prevent Wasmtime from accidentally ever trying to interpret
this context pointer as an actual `VMContext` when it might instead be a
`VMComponentContext`.

Overall this was a pretty smooth transition. The main change here is
that the `VMTrampoline` (now sporting more docs) has its first argument
changed to `*mut ()`. The second argument, the caller context, is still
configured as `*mut VMContext` though because all functions are always
called from wasm still. Eventually for component-to-component calls I
think we'll probably "fake" the second argument as the same as the first
argument, losing track of the original caller, as an intentional way of
isolating components from each other.

Along the way there are a few host locations which do actually assume
that the first argument is indeed a `VMContext`. These are valid
assumptions that are upheld from a correct implementation, but I opted
to add a "magic" field to `VMContext` to assert this in debug mode. This
new "magic" field is inintialized during normal vmcontext initialization
and it's checked whenever a `VMContext` is reinterpreted as an
`Instance` (but only in debug mode). My hope here is to catch any future
accidental mistakes, if ever.

* Use a VMOpaqueContext wrapper

* Fix typos
This commit is contained in:
Alex Crichton
2022-06-01 11:00:43 -05:00
committed by GitHub
parent f4b9020913
commit 2a4851ad2b
9 changed files with 155 additions and 38 deletions

View File

@@ -13,8 +13,8 @@ use std::sync::Arc;
use wasmtime_environ::FuncIndex;
use wasmtime_runtime::{
raise_user_trap, ExportFunction, InstanceAllocator, InstanceHandle, OnDemandInstanceAllocator,
VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMFunctionImport, VMSharedSignatureIndex,
VMTrampoline,
VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMFunctionImport, VMOpaqueContext,
VMSharedSignatureIndex, VMTrampoline,
};
/// A WebAssembly function which can be called.
@@ -1852,7 +1852,7 @@ macro_rules! impl_into_func {
/// by Cranelift, since Cranelift is generating raw function
/// calls directly to this function.
unsafe extern "C" fn wasm_to_host_shim<T, F, $($args,)* R>(
vmctx: *mut VMContext,
vmctx: *mut VMOpaqueContext,
caller_vmctx: *mut VMContext,
$( $args: $args::Abi, )*
retptr: R::Retptr,
@@ -1875,6 +1875,7 @@ macro_rules! impl_into_func {
// should be part of this block, and the long-jmp-ing
// happens after the block in handling `CallResult`.
let result = Caller::with(caller_vmctx, |mut caller| {
let vmctx = VMContext::from_opaque(vmctx);
let state = (*vmctx).host_state();
// Double-check ourselves in debug mode, but we control
// the `Any` here so an unsafe downcast should also
@@ -1940,7 +1941,7 @@ macro_rules! impl_into_func {
/// calls the given function pointer, and then stores the result
/// back into the `args` array.
unsafe extern "C" fn host_trampoline<$($args,)* R>(
callee_vmctx: *mut VMContext,
callee_vmctx: *mut VMOpaqueContext,
caller_vmctx: *mut VMContext,
ptr: *const VMFunctionBody,
args: *mut ValRaw,
@@ -1952,7 +1953,7 @@ macro_rules! impl_into_func {
let ptr = mem::transmute::<
*const VMFunctionBody,
unsafe extern "C" fn(
*mut VMContext,
*mut VMOpaqueContext,
*mut VMContext,
$( $args::Abi, )*
R::Retptr,

View File

@@ -5,7 +5,9 @@ use anyhow::{bail, Result};
use std::marker;
use std::mem::{self, MaybeUninit};
use std::ptr;
use wasmtime_runtime::{VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMSharedSignatureIndex};
use wasmtime_runtime::{
VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMOpaqueContext, VMSharedSignatureIndex,
};
/// A statically typed WebAssembly function.
///
@@ -464,7 +466,7 @@ pub unsafe trait WasmParams: Send {
#[doc(hidden)]
unsafe fn invoke<R: WasmResults>(
func: *const VMFunctionBody,
vmctx1: *mut VMContext,
vmctx1: *mut VMOpaqueContext,
vmctx2: *mut VMContext,
abi: Self::Abi,
) -> R::ResultAbi;
@@ -494,7 +496,7 @@ where
unsafe fn invoke<R: WasmResults>(
func: *const VMFunctionBody,
vmctx1: *mut VMContext,
vmctx1: *mut VMOpaqueContext,
vmctx2: *mut VMContext,
abi: Self::Abi,
) -> R::ResultAbi {
@@ -554,14 +556,14 @@ macro_rules! impl_wasm_params {
unsafe fn invoke<R: WasmResults>(
func: *const VMFunctionBody,
vmctx1: *mut VMContext,
vmctx1: *mut VMOpaqueContext,
vmctx2: *mut VMContext,
abi: Self::Abi,
) -> R::ResultAbi {
let fnptr = mem::transmute::<
*const VMFunctionBody,
unsafe extern "C" fn(
*mut VMContext,
*mut VMOpaqueContext,
*mut VMContext,
$($t::Abi,)*
<R::ResultAbi as HostAbi>::Retptr,

View File

@@ -11,7 +11,7 @@ use std::sync::Arc;
use wasmtime_environ::{EntityType, FuncIndex, GlobalIndex, MemoryIndex, PrimaryMap, TableIndex};
use wasmtime_runtime::{
Imports, InstanceAllocationRequest, InstantiationError, StorePtr, VMContext, VMFunctionBody,
VMFunctionImport, VMGlobalImport, VMMemoryImport, VMTableImport,
VMFunctionImport, VMGlobalImport, VMMemoryImport, VMOpaqueContext, VMTableImport,
};
/// An instantiated WebAssembly module.
@@ -345,7 +345,7 @@ impl Instance {
super::func::invoke_wasm_and_catch_traps(store, |_default_callee| {
mem::transmute::<
*const VMFunctionBody,
unsafe extern "C" fn(*mut VMContext, *mut VMContext),
unsafe extern "C" fn(*mut VMOpaqueContext, *mut VMContext),
>(f.anyfunc.as_ref().func_ptr.as_ptr())(
f.anyfunc.as_ref().vmctx, vmctx
)

View File

@@ -12,8 +12,8 @@ use wasmtime_environ::{
use wasmtime_jit::{CodeMemory, ProfilingAgent};
use wasmtime_runtime::{
Imports, InstanceAllocationRequest, InstanceAllocator, InstanceHandle,
OnDemandInstanceAllocator, StorePtr, VMContext, VMFunctionBody, VMSharedSignatureIndex,
VMTrampoline,
OnDemandInstanceAllocator, StorePtr, VMContext, VMFunctionBody, VMOpaqueContext,
VMSharedSignatureIndex, VMTrampoline,
};
struct TrampolineState<F> {
@@ -23,7 +23,7 @@ struct TrampolineState<F> {
}
unsafe extern "C" fn stub_fn<F>(
vmctx: *mut VMContext,
vmctx: *mut VMOpaqueContext,
caller_vmctx: *mut VMContext,
values_vec: *mut ValRaw,
values_vec_len: usize,
@@ -44,6 +44,7 @@ unsafe extern "C" fn stub_fn<F>(
// have any. To prevent leaks we avoid having any local destructors by
// avoiding local variables.
let result = panic::catch_unwind(AssertUnwindSafe(|| {
let vmctx = VMContext::from_opaque(vmctx);
// Double-check ourselves in debug mode, but we control
// the `Any` here so an unsafe downcast should also
// work.