wasmtime/runtime/store/
data.rs

1use crate::runtime::vm::{self, VMStore};
2use crate::store::StoreOpaque;
3use crate::{StoreContext, StoreContextMut};
4use core::num::NonZeroU64;
5use core::ops::{Index, IndexMut};
6use 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)]
13pub struct InstanceId(u32);
14wasmtime_environ::entity_impl!(InstanceId);
15
16pub struct StoreData {
17    id: StoreId,
18    #[cfg(feature = "component-model")]
19    pub(crate) components: crate::component::ComponentStoreData,
20}
21
22impl 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
37impl<I> Index<I> for StoreOpaque
38where
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
49impl<I> IndexMut<I> for StoreOpaque
50where
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
60impl<I, T> Index<I> for StoreContext<'_, T>
61where
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
73impl<I, T> Index<I> for StoreContextMut<'_, T>
74where
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
85impl<I, T> IndexMut<I> for StoreContextMut<'_, T>
86where
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
96impl<I> Index<I> for dyn VMStore + '_
97where
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
107impl<I> IndexMut<I> for dyn VMStore + '_
108where
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
125pub struct StoreId(NonZeroU64);
126
127impl 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]
195fn 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)]
209pub struct StoreInstanceId {
210    store_id: StoreId,
211    instance: InstanceId,
212}
213
214impl 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    pub(crate) fn get<'a>(&self, store: &'a StoreOpaque) -> &'a vm::Instance {
240        self.assert_belongs_to(store.id());
241        store.instance(self.instance)
242    }
243
244    /// Mutable version of `get` above.
245    ///
246    /// # Panics
247    ///
248    /// Panics if `self` does not belong to `store`.
249    pub(crate) fn get_mut<'a>(&self, store: &'a mut StoreOpaque) -> Pin<&'a mut vm::Instance> {
250        self.assert_belongs_to(store.id());
251        store.instance_mut(self.instance)
252    }
253}
254
255impl Index<StoreInstanceId> for StoreOpaque {
256    type Output = vm::Instance;
257
258    #[inline]
259    fn index(&self, id: StoreInstanceId) -> &Self::Output {
260        id.get(self)
261    }
262}