Skip to content

Commit c3559d4

Browse files
authored
Move *mut dyn VMStore out of VMContext (#10040)
* Move `*mut dyn VMStore` out of `VMContext` There's no need for this type to be accessible from compiled code, so store and manage it entirely from Rust instead. * Fix test expectations * Update disas test expectations
1 parent 938c177 commit c3559d4

File tree

673 files changed

+2547
-2551
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

673 files changed

+2547
-2551
lines changed

crates/environ/src/component/vmcomponent_offsets.rs

-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// struct VMComponentContext {
44
// magic: u32,
55
// builtins: &'static VMComponentBuiltins,
6-
// store: *mut dyn Store,
76
// limits: *const VMRuntimeLimits,
87
// flags: [VMGlobalDefinition; component.num_runtime_component_instances],
98
// trampoline_func_refs: [VMFuncRef; component.num_trampolines],
@@ -62,7 +61,6 @@ pub struct VMComponentOffsets<P> {
6261
// precalculated offsets of various member fields
6362
magic: u32,
6463
builtins: u32,
65-
store: u32,
6664
limits: u32,
6765
flags: u32,
6866
trampoline_func_refs: u32,
@@ -100,7 +98,6 @@ impl<P: PtrSize> VMComponentOffsets<P> {
10098
num_resources: component.num_resources,
10199
magic: 0,
102100
builtins: 0,
103-
store: 0,
104101
limits: 0,
105102
flags: 0,
106103
trampoline_func_refs: 0,
@@ -141,7 +138,6 @@ impl<P: PtrSize> VMComponentOffsets<P> {
141138
size(magic) = 4u32,
142139
align(u32::from(ret.ptr.size())),
143140
size(builtins) = ret.ptr.size(),
144-
size(store) = cmul(2, ret.ptr.size()),
145141
size(limits) = ret.ptr.size(),
146142
align(16),
147143
size(flags) = cmul(ret.num_runtime_component_instances, ret.ptr.size_of_vmglobal_definition()),
@@ -190,12 +186,6 @@ impl<P: PtrSize> VMComponentOffsets<P> {
190186
self.flags + index.as_u32() * u32::from(self.ptr.size_of_vmglobal_definition())
191187
}
192188

193-
/// The offset of the `store` field.
194-
#[inline]
195-
pub fn store(&self) -> u32 {
196-
self.store
197-
}
198-
199189
/// The offset of the `limits` field.
200190
#[inline]
201191
pub fn limits(&self) -> u32 {

crates/environ/src/vmoffsets.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
// gc_heap_base: *mut u8,
1616
// gc_heap_bound: *mut u8,
1717
// gc_heap_data: *mut T, // Collector-specific pointer
18-
// store: *mut dyn Store,
1918
// type_ids: *const VMSharedTypeIndex,
2019
//
2120
// // Variable-width fields come after the fixed-width fields above. Place
@@ -278,16 +277,10 @@ pub trait PtrSize {
278277
self.vmctx_gc_heap_bound() + self.size()
279278
}
280279

281-
/// The offset of the `*const dyn Store` member.
282-
#[inline]
283-
fn vmctx_store(&self) -> u8 {
284-
self.vmctx_gc_heap_data() + self.size()
285-
}
286-
287280
/// The offset of the `type_ids` array pointer.
288281
#[inline]
289282
fn vmctx_type_ids_array(&self) -> u8 {
290-
self.vmctx_store() + 2 * self.size()
283+
self.vmctx_gc_heap_data() + self.size()
291284
}
292285

293286
/// The end of statically known offsets in `VMContext`.

crates/wasmtime/src/runtime/store.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ use core::num::NonZeroU64;
103103
use core::ops::{Deref, DerefMut, Range};
104104
use core::pin::Pin;
105105
use core::ptr;
106+
use core::ptr::NonNull;
106107
use core::task::{Context, Poll};
107108
use wasmtime_environ::TripleExt;
108109

@@ -628,9 +629,9 @@ impl<T> Store<T> {
628629
// maintain throughout Wasmtime.
629630
unsafe {
630631
let traitobj = mem::transmute::<
631-
*mut (dyn crate::runtime::vm::VMStore + '_),
632-
*mut (dyn crate::runtime::vm::VMStore + 'static),
633-
>(&mut *inner);
632+
NonNull<dyn crate::runtime::vm::VMStore + '_>,
633+
NonNull<dyn crate::runtime::vm::VMStore + 'static>,
634+
>(NonNull::from(&mut *inner));
634635
instance.set_store(traitobj);
635636
instance
636637
}
@@ -1933,7 +1934,7 @@ impl StoreOpaque {
19331934
}
19341935

19351936
#[inline]
1936-
pub fn traitobj(&self) -> *mut dyn crate::runtime::vm::VMStore {
1937+
pub fn traitobj(&self) -> NonNull<dyn crate::runtime::vm::VMStore> {
19371938
self.default_caller.traitobj(self)
19381939
}
19391940

crates/wasmtime/src/runtime/vm.rs

+23
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,29 @@ impl DerefMut for dyn VMStore + '_ {
203203
}
204204
}
205205

206+
/// A newtype wrapper around `NonNull<dyn VMStore>` intended to be a
207+
/// self-pointer back to the `Store<T>` within raw data structures like
208+
/// `VMContext`.
209+
///
210+
/// This type exists to manually, and unsafely, implement `Send` and `Sync`.
211+
/// The `VMStore` trait doesn't require `Send` or `Sync` which means this isn't
212+
/// naturally either trait (e.g. with `SendSyncPtr` instead). Note that this
213+
/// means that `Instance` is, for example, mistakenly considered
214+
/// unconditionally `Send` and `Sync`. This is hopefully ok for now though
215+
/// because from a user perspective the only type that matters is `Store<T>`.
216+
/// That type is `Send + Sync` if `T: Send + Sync` already so the internal
217+
/// storage of `Instance` shouldn't matter as the final result is the same.
218+
/// Note though that this means we need to be extra vigilant about cross-thread
219+
/// usage of `Instance` and `ComponentInstance` for example.
220+
#[derive(Copy, Clone)]
221+
#[repr(transparent)]
222+
struct VMStoreRawPtr(NonNull<dyn VMStore>);
223+
224+
// SAFETY: this is the purpose of `VMStoreRawPtr`, see docs above about safe
225+
// usage.
226+
unsafe impl Send for VMStoreRawPtr {}
227+
unsafe impl Sync for VMStoreRawPtr {}
228+
206229
/// Functionality required by this crate for a particular module. This
207230
/// is chiefly needed for lazy initialization of various bits of
208231
/// instance state.

crates/wasmtime/src/runtime/vm/component.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use crate::prelude::*;
1010
use crate::runtime::vm::{
1111
SendSyncPtr, VMArrayCallFunction, VMFuncRef, VMGlobalDefinition, VMMemoryDefinition,
12-
VMOpaqueContext, VMStore, VMWasmCallFunction, ValRaw,
12+
VMOpaqueContext, VMStore, VMStoreRawPtr, VMWasmCallFunction, ValRaw,
1313
};
1414
use alloc::alloc::Layout;
1515
use alloc::sync::Arc;
@@ -66,6 +66,9 @@ pub struct ComponentInstance {
6666
/// Any` is left as an exercise for a future refactoring.
6767
resource_types: Arc<dyn Any + Send + Sync>,
6868

69+
/// Self-pointer back to `Store<T>` and its functions.
70+
store: VMStoreRawPtr,
71+
6972
/// A zero-sized field which represents the end of the struct for the actual
7073
/// `VMComponentContext` to be allocated behind.
7174
vmctx: VMComponentContext,
@@ -193,7 +196,7 @@ impl ComponentInstance {
193196
offsets: VMComponentOffsets<HostPtr>,
194197
runtime_info: Arc<dyn ComponentRuntimeInfo>,
195198
resource_types: Arc<dyn Any + Send + Sync>,
196-
store: *mut dyn VMStore,
199+
store: NonNull<dyn VMStore>,
197200
) {
198201
assert!(alloc_size >= Self::alloc_layout(&offsets).size());
199202

@@ -218,13 +221,14 @@ impl ComponentInstance {
218221
component_resource_tables,
219222
runtime_info,
220223
resource_types,
224+
store: VMStoreRawPtr(store),
221225
vmctx: VMComponentContext {
222226
_marker: marker::PhantomPinned,
223227
},
224228
},
225229
);
226230

227-
(*ptr.as_ptr()).initialize_vmctx(store);
231+
(*ptr.as_ptr()).initialize_vmctx();
228232
}
229233

230234
fn vmctx(&self) -> *mut VMComponentContext {
@@ -258,11 +262,7 @@ impl ComponentInstance {
258262

259263
/// Returns the store that this component was created with.
260264
pub fn store(&self) -> *mut dyn VMStore {
261-
unsafe {
262-
let ret = *self.vmctx_plus_offset::<*mut dyn VMStore>(self.offsets.store());
263-
assert!(!ret.is_null());
264-
ret
265-
}
265+
self.store.0.as_ptr()
266266
}
267267

268268
/// Returns the runtime memory definition corresponding to the index of the
@@ -439,11 +439,11 @@ impl ComponentInstance {
439439
}
440440
}
441441

442-
unsafe fn initialize_vmctx(&mut self, store: *mut dyn VMStore) {
442+
unsafe fn initialize_vmctx(&mut self) {
443443
*self.vmctx_plus_offset_mut(self.offsets.magic()) = VMCOMPONENT_MAGIC;
444444
*self.vmctx_plus_offset_mut(self.offsets.builtins()) = &libcalls::VMComponentBuiltins::INIT;
445-
*self.vmctx_plus_offset_mut(self.offsets.store()) = store;
446-
*self.vmctx_plus_offset_mut(self.offsets.limits()) = (*store).vmruntime_limits();
445+
*self.vmctx_plus_offset_mut(self.offsets.limits()) =
446+
self.store.0.as_ref().vmruntime_limits();
447447

448448
for i in 0..self.offsets.num_runtime_component_instances {
449449
let i = RuntimeComponentInstanceIndex::from_u32(i);
@@ -662,7 +662,7 @@ impl OwnedComponentInstance {
662662
pub fn new(
663663
runtime_info: Arc<dyn ComponentRuntimeInfo>,
664664
resource_types: Arc<dyn Any + Send + Sync>,
665-
store: *mut dyn VMStore,
665+
store: NonNull<dyn VMStore>,
666666
) -> OwnedComponentInstance {
667667
let component = runtime_info.component();
668668
let offsets = VMComponentOffsets::new(HostPtr, component);

crates/wasmtime/src/runtime/vm/instance.rs

+19-29
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::runtime::vm::vmcontext::{
1313
};
1414
use crate::runtime::vm::{
1515
ExportFunction, ExportGlobal, ExportMemory, ExportTable, GcStore, Imports, ModuleRuntimeInfo,
16-
SendSyncPtr, VMFunctionBody, VMGcRef, VMStore, WasmFault,
16+
SendSyncPtr, VMFunctionBody, VMGcRef, VMStore, VMStoreRawPtr, WasmFault,
1717
};
1818
use crate::store::{StoreInner, StoreOpaque};
1919
use crate::{prelude::*, StoreContextMut};
@@ -162,13 +162,7 @@ impl InstanceAndStore {
162162
/// store).
163163
#[inline]
164164
fn store_ptr(&self) -> *mut dyn VMStore {
165-
let ptr = unsafe {
166-
*self
167-
.instance
168-
.vmctx_plus_offset::<*mut dyn VMStore>(self.instance.offsets().ptr.vmctx_store())
169-
};
170-
debug_assert!(!ptr.is_null());
171-
ptr
165+
self.instance.store.unwrap().0.as_ptr()
172166
}
173167
}
174168

@@ -281,6 +275,12 @@ pub struct Instance {
281275
#[cfg(feature = "wmemcheck")]
282276
pub(crate) wmemcheck_state: Option<Wmemcheck>,
283277

278+
/// Self-pointer back to `Store<T>` and its functions. Not present for
279+
/// the brief time that `Store<T>` is itself being created. Also not
280+
/// present for some niche uses that are disconnected from stores (e.g.
281+
/// cross-thread stuff used in `InstancePre`)
282+
store: Option<VMStoreRawPtr>,
283+
284284
/// Additional context used by compiled wasm code. This field is last, and
285285
/// represents a dynamically-sized array that extends beyond the nominal
286286
/// end of the struct (similar to a flexible array member).
@@ -341,6 +341,7 @@ impl Instance {
341341
None
342342
}
343343
},
344+
store: None,
344345
},
345346
);
346347

@@ -584,19 +585,14 @@ impl Instance {
584585
unsafe { self.vmctx_plus_offset_mut(self.offsets().ptr.vmctx_gc_heap_data()) }
585586
}
586587

587-
pub(crate) unsafe fn set_store(&mut self, store: Option<*mut dyn VMStore>) {
588-
if let Some(store) = store {
589-
*self.vmctx_plus_offset_mut(self.offsets().ptr.vmctx_store()) = store;
590-
*self.runtime_limits() = (*store).vmruntime_limits();
591-
*self.epoch_ptr() = (*store).engine().epoch_counter();
592-
self.set_gc_heap((*store).gc_store_mut().ok());
588+
pub(crate) unsafe fn set_store(&mut self, store: Option<NonNull<dyn VMStore>>) {
589+
self.store = store.map(VMStoreRawPtr);
590+
if let Some(mut store) = store {
591+
let store = store.as_mut();
592+
*self.runtime_limits() = store.vmruntime_limits();
593+
*self.epoch_ptr() = store.engine().epoch_counter();
594+
self.set_gc_heap(store.gc_store_mut().ok());
593595
} else {
594-
assert_eq!(
595-
mem::size_of::<*mut dyn VMStore>(),
596-
mem::size_of::<[*mut (); 2]>()
597-
);
598-
*self.vmctx_plus_offset_mut::<[*mut (); 2]>(self.offsets().ptr.vmctx_store()) =
599-
[ptr::null_mut(), ptr::null_mut()];
600596
*self.runtime_limits() = ptr::null_mut();
601597
*self.epoch_ptr() = ptr::null_mut();
602598
self.set_gc_heap(None);
@@ -1607,28 +1603,22 @@ impl InstanceHandle {
16071603
/// This should only be used for initializing a vmctx's store pointer. It
16081604
/// should never be used to access the store itself. Use `InstanceAndStore`
16091605
/// for that instead.
1610-
pub fn traitobj(&self, store: &StoreOpaque) -> *mut dyn VMStore {
1606+
pub fn traitobj(&self, store: &StoreOpaque) -> NonNull<dyn VMStore> {
16111607
// By requiring a store argument, we are ensuring that callers aren't
16121608
// getting this trait object in order to access the store, since they
16131609
// already have access. See `InstanceAndStore` and its documentation for
16141610
// details about the store access patterns we want to restrict host code
16151611
// to.
16161612
let _ = store;
16171613

1618-
let ptr = unsafe {
1619-
*self
1620-
.instance()
1621-
.vmctx_plus_offset::<*mut dyn VMStore>(self.instance().offsets().ptr.vmctx_store())
1622-
};
1623-
debug_assert!(!ptr.is_null());
1624-
ptr
1614+
self.instance().store.unwrap().0
16251615
}
16261616

16271617
/// Configure the `*mut dyn Store` internal pointer after-the-fact.
16281618
///
16291619
/// This is provided for the original `Store` itself to configure the first
16301620
/// self-pointer after the original `Box` has been initialized.
1631-
pub unsafe fn set_store(&mut self, store: *mut dyn VMStore) {
1621+
pub unsafe fn set_store(&mut self, store: NonNull<dyn VMStore>) {
16321622
self.instance_mut().set_store(Some(store));
16331623
}
16341624

crates/wasmtime/src/runtime/vm/instance/allocator.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub struct InstanceAllocationRequest<'a> {
8585
/// InstanceAllocationRequest, rather than on a &mut InstanceAllocationRequest
8686
/// itself, because several use-sites require a split mut borrow on the
8787
/// InstanceAllocationRequest.
88-
pub struct StorePtr(Option<*mut dyn VMStore>);
88+
pub struct StorePtr(Option<NonNull<dyn VMStore>>);
8989

9090
impl StorePtr {
9191
/// A pointer to no Store.
@@ -94,23 +94,21 @@ impl StorePtr {
9494
}
9595

9696
/// A pointer to a Store.
97-
pub fn new(ptr: *mut dyn VMStore) -> Self {
97+
pub fn new(ptr: NonNull<dyn VMStore>) -> Self {
9898
Self(Some(ptr))
9999
}
100100

101101
/// The raw contents of this struct
102-
pub fn as_raw(&self) -> Option<*mut dyn VMStore> {
102+
pub fn as_raw(&self) -> Option<NonNull<dyn VMStore>> {
103103
self.0
104104
}
105105

106106
/// Use the StorePtr as a mut ref to the Store.
107107
///
108108
/// Safety: must not be used outside the original lifetime of the borrow.
109109
pub(crate) unsafe fn get(&mut self) -> Option<&mut dyn VMStore> {
110-
match self.0 {
111-
Some(ptr) => Some(&mut *ptr),
112-
None => None,
113-
}
110+
let ptr = self.0?.as_mut();
111+
Some(ptr)
114112
}
115113
}
116114

0 commit comments

Comments
 (0)