1 use crate::module::ModuleRegistry;
2 use crate::runtime::vm::{self, GcStore, VMStore};
3 use crate::store::StoreOpaque;
4 use crate::{StoreContext, StoreContextMut};
5 use core::num::NonZeroU64;
6 use core::ops::{Index, IndexMut};
7 use 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)]
14 pub struct InstanceId(u32);
15 wasmtime_environ::entity_impl!(InstanceId);
16 
17 pub struct StoreData {
18     id: StoreId,
19     #[cfg(feature = "component-model")]
20     pub(crate) components: crate::component::ComponentStoreData,
21 }
22 
23 impl 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
38 impl<I> Index<I> for StoreOpaque
39 where
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 
50 impl<I> IndexMut<I> for StoreOpaque
51 where
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
61 impl<I, T> Index<I> for StoreContext<'_, T>
62 where
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
74 impl<I, T> Index<I> for StoreContextMut<'_, T>
75 where
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 
86 impl<I, T> IndexMut<I> for StoreContextMut<'_, T>
87 where
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
97 impl<I> Index<I> for dyn VMStore + '_
98 where
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 
108 impl<I> IndexMut<I> for dyn VMStore + '_
109 where
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
126 pub struct StoreId(NonZeroU64);
127 
128 impl 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]
196 fn 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)]
210 pub struct StoreInstanceId {
211     store_id: StoreId,
212     instance: InstanceId,
213 }
214 
215 impl 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 
283 impl 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 }
291