wasmtime/runtime/store/
data.rs

1use crate::module::ModuleRegistry;
2use crate::runtime::vm::{self, GcStore, VMStore};
3use crate::store::StoreOpaque;
4use crate::{StoreContext, StoreContextMut};
5use core::num::NonZeroU64;
6use core::ops::{Index, IndexMut};
7use core::pin::Pin;
8
9// This is defined here, in a private submodule, so we can explicitly reexport
10// it only as `pub(crate)`. This avoids a ton of
11// crate-private-type-in-public-interface errors that aren't really too
12// interesting to deal with.
13#[derive(Copy, Clone, Debug, PartialEq, Eq)]
14pub struct InstanceId(u32);
15wasmtime_environ::entity_impl!(InstanceId);
16
17pub struct StoreData {
18    id: StoreId,
19    #[cfg(feature = "component-model")]
20    pub(crate) components: crate::component::ComponentStoreData,
21}
22
23impl StoreData {
24    pub fn new() -> StoreData {
25        StoreData {
26            id: StoreId::allocate(),
27            #[cfg(feature = "component-model")]
28            components: Default::default(),
29        }
30    }
31
32    pub fn id(&self) -> StoreId {
33        self.id
34    }
35}
36
37// forward StoreOpaque => StoreData
38impl<I> Index<I> for StoreOpaque
39where
40    StoreData: Index<I>,
41{
42    type Output = <StoreData as Index<I>>::Output;
43
44    #[inline]
45    fn index(&self, index: I) -> &Self::Output {
46        self.store_data.index(index)
47    }
48}
49
50impl<I> IndexMut<I> for StoreOpaque
51where
52    StoreData: IndexMut<I>,
53{
54    #[inline]
55    fn index_mut(&mut self, index: I) -> &mut Self::Output {
56        self.store_data.index_mut(index)
57    }
58}
59
60// forward StoreContext => StoreOpaque
61impl<I, T> Index<I> for StoreContext<'_, T>
62where
63    StoreOpaque: Index<I>,
64{
65    type Output = <StoreOpaque as Index<I>>::Output;
66
67    #[inline]
68    fn index(&self, index: I) -> &Self::Output {
69        self.0.index(index)
70    }
71}
72
73// forward StoreContextMut => StoreOpaque
74impl<I, T> Index<I> for StoreContextMut<'_, T>
75where
76    StoreOpaque: Index<I>,
77{
78    type Output = <StoreOpaque as Index<I>>::Output;
79
80    #[inline]
81    fn index(&self, index: I) -> &Self::Output {
82        self.0.index(index)
83    }
84}
85
86impl<I, T> IndexMut<I> for StoreContextMut<'_, T>
87where
88    StoreOpaque: IndexMut<I>,
89{
90    #[inline]
91    fn index_mut(&mut self, index: I) -> &mut Self::Output {
92        self.0.index_mut(index)
93    }
94}
95
96// forward dyn VMStore => StoreOpaque
97impl<I> Index<I> for dyn VMStore + '_
98where
99    StoreOpaque: Index<I>,
100{
101    type Output = <StoreOpaque as Index<I>>::Output;
102
103    fn index(&self, index: I) -> &Self::Output {
104        self.store_opaque().index(index)
105    }
106}
107
108impl<I> IndexMut<I> for dyn VMStore + '_
109where
110    StoreOpaque: IndexMut<I>,
111{
112    fn index_mut(&mut self, index: I) -> &mut Self::Output {
113        self.store_opaque_mut().index_mut(index)
114    }
115}
116
117/// A unique identifier to get attached to a store.
118///
119/// This identifier is embedded into the `Stored<T>` structure and is used to
120/// identify the original store that items come from. For example a `Memory` is
121/// owned by a `Store` and will embed a `StoreId` internally to say which store
122/// it came from. Comparisons with this value are how panics are generated for
123/// mismatching the item that a store belongs to.
124#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
125#[repr(transparent)] // NB: relied on in the C API
126pub struct StoreId(NonZeroU64);
127
128impl StoreId {
129    /// Allocates a new unique identifier for a store that has never before been
130    /// used in this process.
131    pub fn allocate() -> StoreId {
132        // When 64-bit atomics are allowed then allow 2^63 stores at which point
133        // we start panicking to prevent overflow.
134        //
135        // If a store is created once per microsecond then this will last the
136        // current process for 584,540 years before overflowing.
137        const OVERFLOW_THRESHOLD: u64 = 1 << 63;
138
139        #[cfg(target_has_atomic = "64")]
140        let id = {
141            use core::sync::atomic::{AtomicU64, Ordering::Relaxed};
142
143            // Note the usage of `Relaxed` ordering here which should be ok
144            // since we're only looking for atomicity on this counter and this
145            // otherwise isn't used to synchronize memory stored anywhere else.
146            static NEXT_ID: AtomicU64 = AtomicU64::new(0);
147            let id = NEXT_ID.fetch_add(1, Relaxed);
148            if id > OVERFLOW_THRESHOLD {
149                NEXT_ID.store(OVERFLOW_THRESHOLD, Relaxed);
150                panic!("store id allocator overflow");
151            }
152            id
153        };
154
155        // When 64-bit atomics are not allowed use a `RwLock<u64>`. This is
156        // already used elsewhere in Wasmtime and currently has the
157        // implementation of panic-on-contention, but it's at least no worse
158        // than what wasmtime had before and is at least correct and UB-free.
159        #[cfg(not(target_has_atomic = "64"))]
160        let id = {
161            use crate::sync::RwLock;
162            static NEXT_ID: RwLock<u64> = RwLock::new(0);
163
164            let mut lock = NEXT_ID.write();
165            if *lock > OVERFLOW_THRESHOLD {
166                panic!("store id allocator overflow");
167            }
168            let ret = *lock;
169            *lock += 1;
170            ret
171        };
172
173        StoreId(NonZeroU64::new(id + 1).unwrap())
174    }
175
176    #[inline]
177    pub fn assert_belongs_to(&self, store: StoreId) {
178        if *self == store {
179            return;
180        }
181        store_id_mismatch();
182    }
183
184    /// Raw accessor for the C API.
185    pub fn as_raw(&self) -> NonZeroU64 {
186        self.0
187    }
188
189    /// Raw constructor for the C API.
190    pub fn from_raw(id: NonZeroU64) -> StoreId {
191        StoreId(id)
192    }
193}
194
195#[cold]
196fn store_id_mismatch() {
197    panic!("object used with the wrong store");
198}
199
200/// A type used to represent an allocated `vm::Instance` located within a store.
201///
202/// This type is held in various locations as a "safe index" into a store. This
203/// encapsulates a `StoreId` which owns the instance as well as the index within
204/// the store's list of which instance it's pointing to.
205///
206/// This type can notably be used to index into a `StoreOpaque` to project out
207/// the `vm::Instance` that is associated with this id.
208#[repr(C)] // used by reference in the C API
209#[derive(Copy, Clone, Debug, PartialEq, Eq)]
210pub struct StoreInstanceId {
211    store_id: StoreId,
212    instance: InstanceId,
213}
214
215impl StoreInstanceId {
216    pub(crate) fn new(store_id: StoreId, instance: InstanceId) -> StoreInstanceId {
217        StoreInstanceId { store_id, instance }
218    }
219
220    #[inline]
221    pub fn assert_belongs_to(&self, store: StoreId) {
222        self.store_id.assert_belongs_to(store)
223    }
224
225    #[inline]
226    pub fn store_id(&self) -> StoreId {
227        self.store_id
228    }
229
230    #[inline]
231    pub(crate) fn instance(&self) -> InstanceId {
232        self.instance
233    }
234
235    /// Looks up the `vm::Instance` within `store` that this id points to.
236    ///
237    /// # Panics
238    ///
239    /// Panics if `self` does not belong to `store`.
240    #[inline]
241    pub(crate) fn get<'a>(&self, store: &'a StoreOpaque) -> &'a vm::Instance {
242        self.assert_belongs_to(store.id());
243        store.instance(self.instance)
244    }
245
246    /// Mutable version of `get` above.
247    ///
248    /// # Panics
249    ///
250    /// Panics if `self` does not belong to `store`.
251    #[inline]
252    pub(crate) fn get_mut<'a>(&self, store: &'a mut StoreOpaque) -> Pin<&'a mut vm::Instance> {
253        self.assert_belongs_to(store.id());
254        store.instance_mut(self.instance)
255    }
256
257    /// Get both an instance handle and a borrow to the module
258    /// registry in the store.
259    ///
260    /// # Panics
261    ///
262    /// Panics if `self` does not belong to `store`.
263    #[inline]
264    pub(crate) fn get_mut_and_module_registry<'a>(
265        &self,
266        store: &'a mut StoreOpaque,
267    ) -> (Pin<&'a mut vm::Instance>, &'a ModuleRegistry) {
268        self.assert_belongs_to(store.id());
269        store.instance_and_module_registry_mut(self.instance)
270    }
271
272    /// Same as [`Self::get_mut`], but also returns the `GcStore`.
273    #[inline]
274    pub(crate) fn get_with_gc_store_mut<'a>(
275        &self,
276        store: &'a mut StoreOpaque,
277    ) -> (Option<&'a mut GcStore>, Pin<&'a mut vm::Instance>) {
278        self.assert_belongs_to(store.id());
279        store.optional_gc_store_and_instance_mut(self.instance)
280    }
281}
282
283impl Index<StoreInstanceId> for StoreOpaque {
284    type Output = vm::Instance;
285
286    #[inline]
287    fn index(&self, id: StoreInstanceId) -> &Self::Output {
288        id.get(self)
289    }
290}