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