wasmtime/runtime/store/
data.rs1use crate::prelude::*;
2use crate::store::StoreOpaque;
3use crate::{StoreContext, StoreContextMut};
4use core::fmt;
5use core::marker;
6use core::num::NonZeroU64;
7use core::ops::{Index, IndexMut};
8use core::sync::atomic::{AtomicU64, Ordering::Relaxed};
9
10#[derive(Copy, Clone)]
15pub struct InstanceId(pub(super) usize);
16
17impl InstanceId {
18 pub fn from_index(idx: usize) -> InstanceId {
19 InstanceId(idx)
20 }
21}
22
23pub struct StoreData {
24 id: StoreId,
25 funcs: Vec<crate::func::FuncData>,
26 tables: Vec<crate::runtime::vm::ExportTable>,
27 globals: Vec<crate::runtime::vm::ExportGlobal>,
28 instances: Vec<crate::instance::InstanceData>,
29 memories: Vec<crate::runtime::vm::ExportMemory>,
30 #[cfg(feature = "component-model")]
31 pub(crate) components: crate::component::ComponentStoreData,
32}
33
34pub trait StoredData: Sized {
35 fn list(data: &StoreData) -> &Vec<Self>;
36 fn list_mut(data: &mut StoreData) -> &mut Vec<Self>;
37}
38
39macro_rules! impl_store_data {
40 ($($field:ident => $t:ty,)*) => ($(
41 impl StoredData for $t {
42 #[inline]
43 fn list(data: &StoreData) -> &Vec<Self> { &data.$field }
44 #[inline]
45 fn list_mut(data: &mut StoreData) -> &mut Vec<Self> { &mut data.$field }
46 }
47 )*)
48}
49
50impl_store_data! {
51 funcs => crate::func::FuncData,
52 tables => crate::runtime::vm::ExportTable,
53 globals => crate::runtime::vm::ExportGlobal,
54 instances => crate::instance::InstanceData,
55 memories => crate::runtime::vm::ExportMemory,
56}
57
58impl StoreData {
59 pub fn new() -> StoreData {
60 StoreData {
61 id: StoreId::allocate(),
62 funcs: Vec::new(),
63 tables: Vec::new(),
64 globals: Vec::new(),
65 instances: Vec::new(),
66 memories: Vec::new(),
67 #[cfg(feature = "component-model")]
68 components: Default::default(),
69 }
70 }
71
72 pub fn id(&self) -> StoreId {
73 self.id
74 }
75
76 pub fn insert<T>(&mut self, data: T) -> Stored<T>
77 where
78 T: StoredData,
79 {
80 let list = T::list_mut(self);
81 let index = list.len();
82 list.push(data);
83 Stored::new(self.id, index)
84 }
85
86 pub fn next_id<T>(&self) -> Stored<T>
87 where
88 T: StoredData,
89 {
90 Stored::new(self.id, T::list(self).len())
91 }
92
93 pub fn contains<T>(&self, id: Stored<T>) -> bool
94 where
95 T: StoredData,
96 {
97 if id.store_id != self.id {
98 return false;
99 }
100 debug_assert!(id.index() < T::list(self).len());
103 true
104 }
105
106 pub fn iter<T>(&self) -> impl ExactSizeIterator<Item = Stored<T>>
107 where
108 T: StoredData,
109 {
110 let id = self.id;
111 (0..T::list(self).len()).map(move |i| Stored::new(id, i))
112 }
113
114 pub(crate) fn reserve_funcs(&mut self, count: usize) {
115 self.funcs.reserve(count);
116 }
117}
118
119impl<T> Index<Stored<T>> for StoreData
120where
121 T: StoredData,
122{
123 type Output = T;
124
125 #[inline]
126 fn index(&self, index: Stored<T>) -> &Self::Output {
127 index.assert_belongs_to(self.id);
128 &T::list(self)[index.index()]
134 }
135}
136
137impl<T> IndexMut<Stored<T>> for StoreData
138where
139 T: StoredData,
140{
141 #[inline]
142 fn index_mut(&mut self, index: Stored<T>) -> &mut Self::Output {
143 index.assert_belongs_to(self.id);
144 &mut T::list_mut(self)[index.index()]
147 }
148}
149
150impl<I, T> Index<I> for StoreContext<'_, T>
152where
153 StoreData: Index<I>,
154{
155 type Output = <StoreData as Index<I>>::Output;
156
157 #[inline]
158 fn index(&self, index: I) -> &Self::Output {
159 self.0.store_data.index(index)
160 }
161}
162
163impl<I, T> Index<I> for StoreContextMut<'_, T>
165where
166 StoreData: Index<I>,
167{
168 type Output = <StoreData as Index<I>>::Output;
169
170 #[inline]
171 fn index(&self, index: I) -> &Self::Output {
172 self.0.store_data.index(index)
173 }
174}
175
176impl<I> Index<I> for StoreOpaque
178where
179 StoreData: Index<I>,
180{
181 type Output = <StoreData as Index<I>>::Output;
182
183 #[inline]
184 fn index(&self, index: I) -> &Self::Output {
185 self.store_data().index(index)
186 }
187}
188impl<I> IndexMut<I> for StoreOpaque
189where
190 StoreData: IndexMut<I>,
191{
192 #[inline]
193 fn index_mut(&mut self, index: I) -> &mut Self::Output {
194 self.store_data_mut().index_mut(index)
195 }
196}
197
198#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
206#[repr(transparent)] pub struct StoreId(NonZeroU64);
208
209impl StoreId {
210 pub fn allocate() -> StoreId {
213 static NEXT_ID: AtomicU64 = AtomicU64::new(0);
214
215 let id = NEXT_ID.fetch_add(1, Relaxed);
225 if id & (1 << 63) != 0 {
226 NEXT_ID.store(1 << 63, Relaxed);
227 panic!("store id allocator overflow");
228 }
229
230 StoreId(NonZeroU64::new(id + 1).unwrap())
231 }
232
233 #[inline]
234 pub fn assert_belongs_to(&self, store: StoreId) {
235 if *self == store {
236 return;
237 }
238 store_id_mismatch();
239 }
240
241 pub fn as_raw(&self) -> NonZeroU64 {
243 self.0
244 }
245
246 pub fn from_raw(id: NonZeroU64) -> StoreId {
248 StoreId(id)
249 }
250}
251
252#[repr(C)] pub struct Stored<T> {
254 store_id: StoreId,
255 index: usize,
256 _marker: marker::PhantomData<fn() -> T>,
257}
258
259impl<T> Stored<T> {
260 fn new(store_id: StoreId, index: usize) -> Stored<T> {
261 Stored {
262 store_id,
263 index,
264 _marker: marker::PhantomData,
265 }
266 }
267
268 #[inline]
269 pub fn assert_belongs_to(&self, store: StoreId) {
270 self.store_id.assert_belongs_to(store)
271 }
272
273 fn index(&self) -> usize {
274 self.index
275 }
276}
277
278#[cold]
279fn store_id_mismatch() {
280 panic!("object used with the wrong store");
281}
282
283impl<T> PartialEq for Stored<T> {
284 fn eq(&self, other: &Stored<T>) -> bool {
285 self.store_id == other.store_id && self.index == other.index
286 }
287}
288
289impl<T> Copy for Stored<T> {}
290
291impl<T> Clone for Stored<T> {
292 fn clone(&self) -> Self {
293 *self
294 }
295}
296
297impl<T> fmt::Debug for Stored<T> {
298 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
299 write!(f, "store={}, index={}", self.store_id.0, self.index())
300 }
301}