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