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 { 24 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 34 pub fn id(&self) -> StoreId { 35 self.id 36 } 37 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 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] 61 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] 71 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] 84 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] 97 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] 107 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 119 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 { 128 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. 147 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] 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. 201 pub fn as_raw(&self) -> NonZeroU64 { 202 self.0 203 } 204 205 /// Raw constructor for the C API. 206 pub fn from_raw(id: NonZeroU64) -> StoreId { 207 StoreId(id) 208 } 209 } 210 211 #[cold] 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 { 232 pub(crate) fn new(store_id: StoreId, instance: InstanceId) -> StoreInstanceId { 233 StoreInstanceId { store_id, instance } 234 } 235 236 #[inline] 237 pub fn assert_belongs_to(&self, store: StoreId) { 238 self.store_id.assert_belongs_to(store) 239 } 240 241 #[inline] 242 pub fn store_id(&self) -> StoreId { 243 self.store_id 244 } 245 246 #[inline] 247 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] 257 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] 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] 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] 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] 303 fn index(&self, id: StoreInstanceId) -> &Self::Output { 304 id.get(self) 305 } 306 } 307