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