wasmi/
store.rs

1use crate::{
2    collections::arena::{Arena, ArenaIndex, GuardedEntity},
3    core::TrapCode,
4    engine::{DedupFuncType, FuelCosts},
5    externref::{ExternObject, ExternObjectEntity, ExternObjectIdx},
6    func::{Trampoline, TrampolineEntity, TrampolineIdx},
7    memory::{DataSegment, MemoryError},
8    module::InstantiationError,
9    table::TableError,
10    Config,
11    DataSegmentEntity,
12    DataSegmentIdx,
13    ElementSegment,
14    ElementSegmentEntity,
15    ElementSegmentIdx,
16    Engine,
17    Error,
18    Func,
19    FuncEntity,
20    FuncIdx,
21    FuncType,
22    Global,
23    GlobalEntity,
24    GlobalIdx,
25    Instance,
26    InstanceEntity,
27    InstanceIdx,
28    Memory,
29    MemoryEntity,
30    MemoryIdx,
31    ResourceLimiter,
32    Table,
33    TableEntity,
34    TableIdx,
35};
36use alloc::boxed::Box;
37use core::{
38    fmt::{self, Debug},
39    sync::atomic::{AtomicU32, Ordering},
40};
41
42/// A unique store index.
43///
44/// # Note
45///
46/// Used to protect against invalid entity indices.
47#[derive(Debug, Copy, Clone, PartialEq, Eq)]
48pub struct StoreIdx(u32);
49
50impl ArenaIndex for StoreIdx {
51    fn into_usize(self) -> usize {
52        self.0 as usize
53    }
54
55    fn from_usize(value: usize) -> Self {
56        let value = value.try_into().unwrap_or_else(|error| {
57            panic!("index {value} is out of bounds as store index: {error}")
58        });
59        Self(value)
60    }
61}
62
63impl StoreIdx {
64    /// Returns a new unique [`StoreIdx`].
65    fn new() -> Self {
66        /// A static store index counter.
67        static CURRENT_STORE_IDX: AtomicU32 = AtomicU32::new(0);
68        let next_idx = CURRENT_STORE_IDX.fetch_add(1, Ordering::AcqRel);
69        Self(next_idx)
70    }
71}
72
73/// A stored entity.
74pub type Stored<Idx> = GuardedEntity<StoreIdx, Idx>;
75
76/// A wrapper around an optional `&mut dyn` [`ResourceLimiter`], that exists
77/// both to make types a little easier to read and to provide a `Debug` impl so
78/// that `#[derive(Debug)]` works on structs that contain it.
79pub struct ResourceLimiterRef<'a>(Option<&'a mut (dyn ResourceLimiter)>);
80impl Debug for ResourceLimiterRef<'_> {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        write!(f, "ResourceLimiterRef(...)")
83    }
84}
85
86impl<'a> ResourceLimiterRef<'a> {
87    pub fn as_resource_limiter(&mut self) -> &mut Option<&'a mut dyn ResourceLimiter> {
88        &mut self.0
89    }
90}
91
92/// A wrapper around a boxed `dyn FnMut(&mut T)` returning a `&mut dyn`
93/// [`ResourceLimiter`]; in other words a function that one can call to retrieve
94/// a [`ResourceLimiter`] from the [`Store`] object's user data type `T`.
95///
96/// This wrapper exists both to make types a little easier to read and to
97/// provide a `Debug` impl so that `#[derive(Debug)]` works on structs that
98/// contain it.
99struct ResourceLimiterQuery<T>(Box<dyn FnMut(&mut T) -> &mut (dyn ResourceLimiter) + Send + Sync>);
100impl<T> Debug for ResourceLimiterQuery<T> {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        write!(f, "ResourceLimiterQuery(...)")
103    }
104}
105
106/// A wrapper used to store hooks added with [`Store::call_hook`], containing a
107/// boxed `FnMut(&mut T, CallHook) -> Result<(), Error>`.
108///
109/// This wrapper exists to provide a `Debug` impl so that `#[derive(Debug)]`
110/// works for [`Store`].
111#[allow(clippy::type_complexity)]
112struct CallHookWrapper<T>(Box<dyn FnMut(&mut T, CallHook) -> Result<(), Error> + Send + Sync>);
113impl<T> Debug for CallHookWrapper<T> {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        write!(f, "CallHook(...)")
116    }
117}
118
119/// The store that owns all data associated to Wasm modules.
120#[derive(Debug)]
121pub struct Store<T> {
122    /// All data that is not associated to `T`.
123    ///
124    /// # Note
125    ///
126    /// This is re-exported to the rest of the crate since
127    /// it is used directly by the engine's executor.
128    pub(crate) inner: StoreInner,
129    /// Stored host function trampolines.
130    trampolines: Arena<TrampolineIdx, TrampolineEntity<T>>,
131    /// User provided host data owned by the [`Store`].
132    data: T,
133    /// User provided hook to retrieve a [`ResourceLimiter`].
134    limiter: Option<ResourceLimiterQuery<T>>,
135    /// User provided callback called when a host calls a WebAssembly function
136    /// or a WebAssembly function calls a host function, or these functions
137    /// return.
138    call_hook: Option<CallHookWrapper<T>>,
139}
140
141/// The inner store that owns all data not associated to the host state.
142#[derive(Debug)]
143pub struct StoreInner {
144    /// The unique store index.
145    ///
146    /// Used to protect against invalid entity indices.
147    store_idx: StoreIdx,
148    /// Stored Wasm or host functions.
149    funcs: Arena<FuncIdx, FuncEntity>,
150    /// Stored linear memories.
151    memories: Arena<MemoryIdx, MemoryEntity>,
152    /// Stored tables.
153    tables: Arena<TableIdx, TableEntity>,
154    /// Stored global variables.
155    globals: Arena<GlobalIdx, GlobalEntity>,
156    /// Stored module instances.
157    instances: Arena<InstanceIdx, InstanceEntity>,
158    /// Stored data segments.
159    datas: Arena<DataSegmentIdx, DataSegmentEntity>,
160    /// Stored data segments.
161    elems: Arena<ElementSegmentIdx, ElementSegmentEntity>,
162    /// Stored external objects for [`ExternRef`] types.
163    ///
164    /// [`ExternRef`]: [`crate::ExternRef`]
165    extern_objects: Arena<ExternObjectIdx, ExternObjectEntity>,
166    /// The [`Engine`] in use by the [`Store`].
167    ///
168    /// Amongst others the [`Engine`] stores the Wasm function definitions.
169    engine: Engine,
170    /// The fuel of the [`Store`].
171    fuel: Fuel,
172}
173
174#[test]
175fn test_store_is_send_sync() {
176    const _: () = {
177        #[allow(clippy::extra_unused_type_parameters)]
178        fn assert_send<T: Send>() {}
179        #[allow(clippy::extra_unused_type_parameters)]
180        fn assert_sync<T: Sync>() {}
181        let _ = assert_send::<Store<()>>;
182        let _ = assert_sync::<Store<()>>;
183    };
184}
185
186/// Argument to the callback set by [`Store::call_hook`] to indicate why the
187/// callback was invoked.
188#[derive(Debug)]
189pub enum CallHook {
190    /// Indicates that a WebAssembly function is being called from the host.
191    CallingWasm,
192    /// Indicates that a WebAssembly function called from the host is returning.
193    ReturningFromWasm,
194    /// Indicates that a host function is being called from a WebAssembly function.
195    CallingHost,
196    /// Indicates that a host function called from a WebAssembly function is returning.
197    ReturningFromHost,
198}
199
200/// An error that may be encountered when operating on the [`Store`].
201#[derive(Debug, Clone)]
202pub enum FuelError {
203    /// Raised when trying to use any of the `fuel` methods while fuel metering is disabled.
204    FuelMeteringDisabled,
205    /// Raised when trying to consume more fuel than is available in the [`Store`].
206    OutOfFuel,
207}
208
209#[cfg(feature = "std")]
210impl std::error::Error for FuelError {}
211
212impl fmt::Display for FuelError {
213    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214        match self {
215            Self::FuelMeteringDisabled => write!(f, "fuel metering is disabled"),
216            Self::OutOfFuel => write!(f, "all fuel consumed"),
217        }
218    }
219}
220
221impl FuelError {
222    /// Returns an error indicating that fuel metering has been disabled.
223    ///
224    /// # Note
225    ///
226    /// This method exists to indicate that this execution path is cold.
227    #[cold]
228    pub fn fuel_metering_disabled() -> Self {
229        Self::FuelMeteringDisabled
230    }
231
232    /// Returns an error indicating that too much fuel has been consumed.
233    ///
234    /// # Note
235    ///
236    /// This method exists to indicate that this execution path is cold.
237    #[cold]
238    pub fn out_of_fuel() -> Self {
239        Self::OutOfFuel
240    }
241}
242
243/// The remaining and consumed fuel counters.
244#[derive(Debug, Copy, Clone)]
245pub struct Fuel {
246    /// The remaining fuel.
247    remaining: u64,
248    /// This is `true` if fuel metering is enabled for the [`Engine`].
249    enabled: bool,
250    /// The fuel costs provided by the [`Engine`]'s [`Config`].
251    ///
252    /// [`Config`]: crate::Config
253    costs: FuelCosts,
254}
255
256impl Fuel {
257    /// Creates a new [`Fuel`] for the [`Engine`].
258    pub fn new(config: &Config) -> Self {
259        let enabled = config.get_consume_fuel();
260        let costs = *config.fuel_costs();
261        Self {
262            remaining: 0,
263            enabled,
264            costs,
265        }
266    }
267
268    /// Returns `true` if fuel metering is enabled.
269    fn is_fuel_metering_enabled(&self) -> bool {
270        self.enabled
271    }
272
273    /// Returns `Ok` if fuel metering is enabled.
274    ///
275    /// Returns descriptive [`FuelError`] otherwise.
276    ///
277    /// # Errors
278    ///
279    /// If fuel metering is disabled.
280    fn check_fuel_metering_enabled(&self) -> Result<(), FuelError> {
281        if !self.is_fuel_metering_enabled() {
282            return Err(FuelError::fuel_metering_disabled());
283        }
284        Ok(())
285    }
286
287    /// Sets the remaining fuel to `fuel`.
288    ///
289    /// # Errors
290    ///
291    /// If fuel metering is disabled.
292    pub fn set_fuel(&mut self, fuel: u64) -> Result<(), FuelError> {
293        self.check_fuel_metering_enabled()?;
294        self.remaining = fuel;
295        Ok(())
296    }
297
298    /// Returns the remaining fuel.
299    ///
300    /// # Errors
301    ///
302    /// If fuel metering is disabled.
303    pub fn get_fuel(&self) -> Result<u64, FuelError> {
304        self.check_fuel_metering_enabled()?;
305        Ok(self.remaining)
306    }
307
308    /// Synthetically consumes an amount of [`Fuel`] from the [`Store`].
309    ///
310    /// Returns the remaining amount of [`Fuel`] after this operation.
311    ///
312    /// # Note
313    ///
314    /// - This does not check if fuel metering is enabled.
315    /// - This API is intended for use cases where it is clear that fuel metering is
316    ///   enabled and where a check would incur unnecessary overhead in a hot path.
317    ///   An example of this is the execution of consume fuel instructions since
318    ///   those only exist if fuel metering is enabled.
319    ///
320    /// # Errors
321    ///
322    /// If out of fuel.
323    pub(crate) fn consume_fuel_unchecked(&mut self, delta: u64) -> Result<u64, TrapCode> {
324        self.remaining = self
325            .remaining
326            .checked_sub(delta)
327            .ok_or(TrapCode::OutOfFuel)?;
328        Ok(self.remaining)
329    }
330
331    /// Synthetically consumes an amount of [`Fuel`] for the [`Store`].
332    ///
333    /// Returns the remaining amount of [`Fuel`] after this operation.
334    ///
335    /// # Errors
336    ///
337    /// - If fuel metering is disabled.
338    /// - If out of fuel.
339    pub(crate) fn consume_fuel(
340        &mut self,
341        f: impl FnOnce(&FuelCosts) -> u64,
342    ) -> Result<u64, FuelError> {
343        self.check_fuel_metering_enabled()?;
344        self.consume_fuel_unchecked(f(&self.costs))
345            .map_err(|_| FuelError::OutOfFuel)
346    }
347
348    /// Synthetically consumes an amount of [`Fuel`] from the [`Store`] if fuel metering is enabled.
349    ///
350    /// # Note
351    ///
352    /// This does nothing if fuel metering is disabled.
353    ///
354    /// # Errors
355    ///
356    /// - If out of fuel.
357    pub(crate) fn consume_fuel_if(
358        &mut self,
359        f: impl FnOnce(&FuelCosts) -> u64,
360    ) -> Result<(), TrapCode> {
361        match self.consume_fuel(f) {
362            Err(FuelError::OutOfFuel) => Err(TrapCode::OutOfFuel),
363            Err(FuelError::FuelMeteringDisabled) | Ok(_) => Ok(()),
364        }
365    }
366}
367
368impl StoreInner {
369    /// Creates a new [`StoreInner`] for the given [`Engine`].
370    pub fn new(engine: &Engine) -> Self {
371        let fuel = Fuel::new(engine.config());
372        StoreInner {
373            engine: engine.clone(),
374            store_idx: StoreIdx::new(),
375            funcs: Arena::new(),
376            memories: Arena::new(),
377            tables: Arena::new(),
378            globals: Arena::new(),
379            instances: Arena::new(),
380            datas: Arena::new(),
381            elems: Arena::new(),
382            extern_objects: Arena::new(),
383            fuel,
384        }
385    }
386
387    /// Returns the [`Engine`] that this store is associated with.
388    pub fn engine(&self) -> &Engine {
389        &self.engine
390    }
391
392    /// Returns an exclusive reference to the [`Fuel`] counters.
393    pub fn fuel_mut(&mut self) -> &mut Fuel {
394        &mut self.fuel
395    }
396
397    /// Wraps an entity `Idx` (index type) as a [`Stored<Idx>`] type.
398    ///
399    /// # Note
400    ///
401    /// [`Stored<Idx>`] associates an `Idx` type with the internal store index.
402    /// This way wrapped indices cannot be misused with incorrect [`Store`] instances.
403    fn wrap_stored<Idx>(&self, entity_idx: Idx) -> Stored<Idx> {
404        Stored::new(self.store_idx, entity_idx)
405    }
406
407    /// Unwraps the given [`Stored<Idx>`] reference and returns the `Idx`.
408    ///
409    /// # Panics
410    ///
411    /// If the [`Stored<Idx>`] does not originate from this [`Store`].
412    fn unwrap_stored<Idx>(&self, stored: &Stored<Idx>) -> Idx
413    where
414        Idx: ArenaIndex + Debug,
415    {
416        stored.entity_index(self.store_idx).unwrap_or_else(|| {
417            panic!(
418                "entity reference ({:?}) does not belong to store {:?}",
419                stored, self.store_idx,
420            )
421        })
422    }
423
424    /// Allocates a new [`GlobalEntity`] and returns a [`Global`] reference to it.
425    pub fn alloc_global(&mut self, global: GlobalEntity) -> Global {
426        let global = self.globals.alloc(global);
427        Global::from_inner(self.wrap_stored(global))
428    }
429
430    /// Allocates a new [`TableEntity`] and returns a [`Table`] reference to it.
431    pub fn alloc_table(&mut self, table: TableEntity) -> Table {
432        let table = self.tables.alloc(table);
433        Table::from_inner(self.wrap_stored(table))
434    }
435
436    /// Allocates a new [`MemoryEntity`] and returns a [`Memory`] reference to it.
437    pub fn alloc_memory(&mut self, memory: MemoryEntity) -> Memory {
438        let memory = self.memories.alloc(memory);
439        Memory::from_inner(self.wrap_stored(memory))
440    }
441
442    /// Allocates a new [`DataSegmentEntity`] and returns a [`DataSegment`] reference to it.
443    pub fn alloc_data_segment(&mut self, segment: DataSegmentEntity) -> DataSegment {
444        let segment = self.datas.alloc(segment);
445        DataSegment::from_inner(self.wrap_stored(segment))
446    }
447
448    /// Allocates a new [`ElementSegmentEntity`] and returns a [`ElementSegment`] reference to it.
449    pub(super) fn alloc_element_segment(
450        &mut self,
451        segment: ElementSegmentEntity,
452    ) -> ElementSegment {
453        let segment = self.elems.alloc(segment);
454        ElementSegment::from_inner(self.wrap_stored(segment))
455    }
456
457    /// Allocates a new [`ExternObjectEntity`] and returns a [`ExternObject`] reference to it.
458    pub(super) fn alloc_extern_object(&mut self, object: ExternObjectEntity) -> ExternObject {
459        let object = self.extern_objects.alloc(object);
460        ExternObject::from_inner(self.wrap_stored(object))
461    }
462
463    /// Allocates a new uninitialized [`InstanceEntity`] and returns an [`Instance`] reference to it.
464    ///
465    /// # Note
466    ///
467    /// - This will create an uninitialized dummy [`InstanceEntity`] as a place holder
468    ///   for the returned [`Instance`]. Using this uninitialized [`Instance`] will result
469    ///   in a runtime panic.
470    /// - The returned [`Instance`] must later be initialized via the [`StoreInner::initialize_instance`]
471    ///   method. Afterwards the [`Instance`] may be used.
472    pub fn alloc_instance(&mut self) -> Instance {
473        let instance = self.instances.alloc(InstanceEntity::uninitialized());
474        Instance::from_inner(self.wrap_stored(instance))
475    }
476
477    /// Initializes the [`Instance`] using the given [`InstanceEntity`].
478    ///
479    /// # Note
480    ///
481    /// After this operation the [`Instance`] is initialized and can be used.
482    ///
483    /// # Panics
484    ///
485    /// - If the [`Instance`] does not belong to the [`Store`].
486    /// - If the [`Instance`] is unknown to the [`Store`].
487    /// - If the [`Instance`] has already been initialized.
488    /// - If the given [`InstanceEntity`] is itself not initialized, yet.
489    pub fn initialize_instance(&mut self, instance: Instance, init: InstanceEntity) {
490        assert!(
491            init.is_initialized(),
492            "encountered an uninitialized new instance entity: {init:?}",
493        );
494        let idx = self.unwrap_stored(instance.as_inner());
495        let uninit = self
496            .instances
497            .get_mut(idx)
498            .unwrap_or_else(|| panic!("missing entity for the given instance: {instance:?}"));
499        assert!(
500            !uninit.is_initialized(),
501            "encountered an already initialized instance: {uninit:?}",
502        );
503        *uninit = init;
504    }
505
506    /// Returns a shared reference to the entity indexed by the given `idx`.
507    ///
508    /// # Panics
509    ///
510    /// - If the indexed entity does not originate from this [`Store`].
511    /// - If the entity index cannot be resolved to its entity.
512    fn resolve<'a, Idx, Entity>(
513        &self,
514        idx: &Stored<Idx>,
515        entities: &'a Arena<Idx, Entity>,
516    ) -> &'a Entity
517    where
518        Idx: ArenaIndex + Debug,
519    {
520        let idx = self.unwrap_stored(idx);
521        entities
522            .get(idx)
523            .unwrap_or_else(|| panic!("failed to resolve stored entity: {idx:?}"))
524    }
525
526    /// Returns an exclusive reference to the entity indexed by the given `idx`.
527    ///
528    /// # Note
529    ///
530    /// Due to borrow checking issues this method takes an already unwrapped
531    /// `Idx` unlike the [`StoreInner::resolve`] method.
532    ///
533    /// # Panics
534    ///
535    /// - If the entity index cannot be resolved to its entity.
536    fn resolve_mut<Idx, Entity>(idx: Idx, entities: &mut Arena<Idx, Entity>) -> &mut Entity
537    where
538        Idx: ArenaIndex + Debug,
539    {
540        entities
541            .get_mut(idx)
542            .unwrap_or_else(|| panic!("failed to resolve stored entity: {idx:?}"))
543    }
544
545    /// Returns the [`FuncType`] associated to the given [`DedupFuncType`].
546    ///
547    /// # Panics
548    ///
549    /// - If the [`DedupFuncType`] does not originate from this [`Store`].
550    /// - If the [`DedupFuncType`] cannot be resolved to its entity.
551    pub fn resolve_func_type(&self, func_type: &DedupFuncType) -> FuncType {
552        self.resolve_func_type_with(func_type, FuncType::clone)
553    }
554
555    /// Calls `f` on the [`FuncType`] associated to the given [`DedupFuncType`] and returns the result.
556    ///
557    /// # Panics
558    ///
559    /// - If the [`DedupFuncType`] does not originate from this [`Store`].
560    /// - If the [`DedupFuncType`] cannot be resolved to its entity.
561    pub fn resolve_func_type_with<R>(
562        &self,
563        func_type: &DedupFuncType,
564        f: impl FnOnce(&FuncType) -> R,
565    ) -> R {
566        self.engine.resolve_func_type(func_type, f)
567    }
568
569    /// Returns a shared reference to the [`GlobalEntity`] associated to the given [`Global`].
570    ///
571    /// # Panics
572    ///
573    /// - If the [`Global`] does not originate from this [`Store`].
574    /// - If the [`Global`] cannot be resolved to its entity.
575    pub fn resolve_global(&self, global: &Global) -> &GlobalEntity {
576        self.resolve(global.as_inner(), &self.globals)
577    }
578
579    /// Returns an exclusive reference to the [`GlobalEntity`] associated to the given [`Global`].
580    ///
581    /// # Panics
582    ///
583    /// - If the [`Global`] does not originate from this [`Store`].
584    /// - If the [`Global`] cannot be resolved to its entity.
585    pub fn resolve_global_mut(&mut self, global: &Global) -> &mut GlobalEntity {
586        let idx = self.unwrap_stored(global.as_inner());
587        Self::resolve_mut(idx, &mut self.globals)
588    }
589
590    /// Returns a shared reference to the [`TableEntity`] associated to the given [`Table`].
591    ///
592    /// # Panics
593    ///
594    /// - If the [`Table`] does not originate from this [`Store`].
595    /// - If the [`Table`] cannot be resolved to its entity.
596    pub fn resolve_table(&self, table: &Table) -> &TableEntity {
597        self.resolve(table.as_inner(), &self.tables)
598    }
599
600    /// Returns an exclusive reference to the [`TableEntity`] associated to the given [`Table`].
601    ///
602    /// # Panics
603    ///
604    /// - If the [`Table`] does not originate from this [`Store`].
605    /// - If the [`Table`] cannot be resolved to its entity.
606    pub fn resolve_table_mut(&mut self, table: &Table) -> &mut TableEntity {
607        let idx = self.unwrap_stored(table.as_inner());
608        Self::resolve_mut(idx, &mut self.tables)
609    }
610
611    /// Returns an exclusive reference to the [`TableEntity`] and [`ElementSegmentEntity`] associated to `table` and `elem`.
612    ///
613    /// # Panics
614    ///
615    /// - If the [`Table`] does not originate from this [`Store`].
616    /// - If the [`Table`] cannot be resolved to its entity.
617    /// - If the [`ElementSegment`] does not originate from this [`Store`].
618    /// - If the [`ElementSegment`] cannot be resolved to its entity.
619    pub fn resolve_table_and_element_mut(
620        &mut self,
621        table: &Table,
622        elem: &ElementSegment,
623    ) -> (&mut TableEntity, &mut ElementSegmentEntity) {
624        let table_idx = self.unwrap_stored(table.as_inner());
625        let elem_idx = self.unwrap_stored(elem.as_inner());
626        let table = Self::resolve_mut(table_idx, &mut self.tables);
627        let elem = Self::resolve_mut(elem_idx, &mut self.elems);
628        (table, elem)
629    }
630
631    /// Returns both
632    ///
633    /// - an exclusive reference to the [`TableEntity`] associated to the given [`Table`]
634    /// - an exclusive reference to the [`Fuel`] of the [`StoreInner`].
635    ///
636    /// # Panics
637    ///
638    /// - If the [`Table`] does not originate from this [`Store`].
639    /// - If the [`Table`] cannot be resolved to its entity.
640    pub fn resolve_table_and_fuel_mut(&mut self, table: &Table) -> (&mut TableEntity, &mut Fuel) {
641        let idx = self.unwrap_stored(table.as_inner());
642        let table = Self::resolve_mut(idx, &mut self.tables);
643        let fuel = &mut self.fuel;
644        (table, fuel)
645    }
646
647    /// Returns an exclusive reference to the [`TableEntity`] associated to the given [`Table`].
648    ///
649    /// # Panics
650    ///
651    /// - If the [`Table`] does not originate from this [`Store`].
652    /// - If the [`Table`] cannot be resolved to its entity.
653    pub fn resolve_table_pair_and_fuel(
654        &mut self,
655        fst: &Table,
656        snd: &Table,
657    ) -> (&mut TableEntity, &mut TableEntity, &mut Fuel) {
658        let fst = self.unwrap_stored(fst.as_inner());
659        let snd = self.unwrap_stored(snd.as_inner());
660        let (fst, snd) = self.tables.get_pair_mut(fst, snd).unwrap_or_else(|| {
661            panic!("failed to resolve stored pair of entities: {fst:?} and {snd:?}")
662        });
663        let fuel = &mut self.fuel;
664        (fst, snd, fuel)
665    }
666
667    /// Returns the following data:
668    ///
669    /// - A shared reference to the [`InstanceEntity`] associated to the given [`Instance`].
670    /// - An exclusive reference to the [`TableEntity`] associated to the given [`Table`].
671    /// - A shared reference to the [`ElementSegmentEntity`] associated to the given [`ElementSegment`].
672    /// - An exclusive reference to the [`Fuel`] of the [`StoreInner`].
673    ///
674    /// # Note
675    ///
676    /// This method exists to properly handle use cases where
677    /// otherwise the Rust borrow-checker would not accept.
678    ///
679    /// # Panics
680    ///
681    /// - If the [`Instance`] does not originate from this [`Store`].
682    /// - If the [`Instance`] cannot be resolved to its entity.
683    /// - If the [`Table`] does not originate from this [`Store`].
684    /// - If the [`Table`] cannot be resolved to its entity.
685    /// - If the [`ElementSegment`] does not originate from this [`Store`].
686    /// - If the [`ElementSegment`] cannot be resolved to its entity.
687    pub(super) fn resolve_table_init_params(
688        &mut self,
689        table: &Table,
690        segment: &ElementSegment,
691    ) -> (&mut TableEntity, &ElementSegmentEntity, &mut Fuel) {
692        let mem_idx = self.unwrap_stored(table.as_inner());
693        let elem_idx = segment.as_inner();
694        let elem = self.resolve(elem_idx, &self.elems);
695        let mem = Self::resolve_mut(mem_idx, &mut self.tables);
696        let fuel = &mut self.fuel;
697        (mem, elem, fuel)
698    }
699
700    /// Returns a shared reference to the [`ElementSegmentEntity`] associated to the given [`ElementSegment`].
701    ///
702    /// # Panics
703    ///
704    /// - If the [`ElementSegment`] does not originate from this [`Store`].
705    /// - If the [`ElementSegment`] cannot be resolved to its entity.
706    pub fn resolve_element_segment(&self, segment: &ElementSegment) -> &ElementSegmentEntity {
707        self.resolve(segment.as_inner(), &self.elems)
708    }
709
710    /// Returns an exclusive reference to the [`ElementSegmentEntity`] associated to the given [`ElementSegment`].
711    ///
712    /// # Panics
713    ///
714    /// - If the [`ElementSegment`] does not originate from this [`Store`].
715    /// - If the [`ElementSegment`] cannot be resolved to its entity.
716    pub fn resolve_element_segment_mut(
717        &mut self,
718        segment: &ElementSegment,
719    ) -> &mut ElementSegmentEntity {
720        let idx = self.unwrap_stored(segment.as_inner());
721        Self::resolve_mut(idx, &mut self.elems)
722    }
723
724    /// Returns a shared reference to the [`MemoryEntity`] associated to the given [`Memory`].
725    ///
726    /// # Panics
727    ///
728    /// - If the [`Memory`] does not originate from this [`Store`].
729    /// - If the [`Memory`] cannot be resolved to its entity.
730    pub fn resolve_memory<'a>(&'a self, memory: &Memory) -> &'a MemoryEntity {
731        self.resolve(memory.as_inner(), &self.memories)
732    }
733
734    /// Returns an exclusive reference to the [`MemoryEntity`] associated to the given [`Memory`].
735    ///
736    /// # Panics
737    ///
738    /// - If the [`Memory`] does not originate from this [`Store`].
739    /// - If the [`Memory`] cannot be resolved to its entity.
740    pub fn resolve_memory_mut<'a>(&'a mut self, memory: &Memory) -> &'a mut MemoryEntity {
741        let idx = self.unwrap_stored(memory.as_inner());
742        Self::resolve_mut(idx, &mut self.memories)
743    }
744
745    /// Returns an exclusive reference to the [`MemoryEntity`] associated to the given [`Memory`].
746    ///
747    /// # Panics
748    ///
749    /// - If the [`Memory`] does not originate from this [`Store`].
750    /// - If the [`Memory`] cannot be resolved to its entity.
751    pub fn resolve_memory_and_fuel_mut(
752        &mut self,
753        memory: &Memory,
754    ) -> (&mut MemoryEntity, &mut Fuel) {
755        let idx = self.unwrap_stored(memory.as_inner());
756        let memory = Self::resolve_mut(idx, &mut self.memories);
757        let fuel = &mut self.fuel;
758        (memory, fuel)
759    }
760
761    /// Returns the following data:
762    ///
763    /// - An exclusive reference to the [`MemoryEntity`] associated to the given [`Memory`].
764    /// - A shared reference to the [`DataSegmentEntity`] associated to the given [`DataSegment`].
765    /// - An exclusive reference to the [`Fuel`] of the [`StoreInner`].
766    ///
767    /// # Note
768    ///
769    /// This method exists to properly handle use cases where
770    /// otherwise the Rust borrow-checker would not accept.
771    ///
772    /// # Panics
773    ///
774    /// - If the [`Memory`] does not originate from this [`Store`].
775    /// - If the [`Memory`] cannot be resolved to its entity.
776    /// - If the [`DataSegment`] does not originate from this [`Store`].
777    /// - If the [`DataSegment`] cannot be resolved to its entity.
778    pub(super) fn resolve_memory_init_params(
779        &mut self,
780        memory: &Memory,
781        segment: &DataSegment,
782    ) -> (&mut MemoryEntity, &DataSegmentEntity, &mut Fuel) {
783        let mem_idx = self.unwrap_stored(memory.as_inner());
784        let data_idx = segment.as_inner();
785        let data = self.resolve(data_idx, &self.datas);
786        let mem = Self::resolve_mut(mem_idx, &mut self.memories);
787        let fuel = &mut self.fuel;
788        (mem, data, fuel)
789    }
790
791    /// Returns an exclusive pair of references to the [`MemoryEntity`] associated to the given [`Memory`]s.
792    ///
793    /// # Panics
794    ///
795    /// - If the [`Memory`] does not originate from this [`Store`].
796    /// - If the [`Memory`] cannot be resolved to its entity.
797    pub(super) fn resolve_memory_pair_and_fuel(
798        &mut self,
799        fst: &Memory,
800        snd: &Memory,
801    ) -> (&mut MemoryEntity, &mut MemoryEntity, &mut Fuel) {
802        let fst = self.unwrap_stored(fst.as_inner());
803        let snd = self.unwrap_stored(snd.as_inner());
804        let (fst, snd) = self.memories.get_pair_mut(fst, snd).unwrap_or_else(|| {
805            panic!("failed to resolve stored pair of entities: {fst:?} and {snd:?}")
806        });
807        let fuel = &mut self.fuel;
808        (fst, snd, fuel)
809    }
810
811    /// Returns an exclusive reference to the [`DataSegmentEntity`] associated to the given [`DataSegment`].
812    ///
813    /// # Panics
814    ///
815    /// - If the [`DataSegment`] does not originate from this [`Store`].
816    /// - If the [`DataSegment`] cannot be resolved to its entity.
817    pub fn resolve_data_segment_mut(&mut self, segment: &DataSegment) -> &mut DataSegmentEntity {
818        let idx = self.unwrap_stored(segment.as_inner());
819        Self::resolve_mut(idx, &mut self.datas)
820    }
821
822    /// Returns a shared reference to the [`InstanceEntity`] associated to the given [`Instance`].
823    ///
824    /// # Panics
825    ///
826    /// - If the [`Instance`] does not originate from this [`Store`].
827    /// - If the [`Instance`] cannot be resolved to its entity.
828    pub fn resolve_instance(&self, instance: &Instance) -> &InstanceEntity {
829        self.resolve(instance.as_inner(), &self.instances)
830    }
831
832    /// Returns a shared reference to the [`ExternObjectEntity`] associated to the given [`ExternObject`].
833    ///
834    /// # Panics
835    ///
836    /// - If the [`ExternObject`] does not originate from this [`Store`].
837    /// - If the [`ExternObject`] cannot be resolved to its entity.
838    pub fn resolve_external_object(&self, object: &ExternObject) -> &ExternObjectEntity {
839        self.resolve(object.as_inner(), &self.extern_objects)
840    }
841
842    /// Allocates a new Wasm or host [`FuncEntity`] and returns a [`Func`] reference to it.
843    pub fn alloc_func(&mut self, func: FuncEntity) -> Func {
844        let idx = self.funcs.alloc(func);
845        Func::from_inner(self.wrap_stored(idx))
846    }
847
848    /// Returns a shared reference to the associated entity of the Wasm or host function.
849    ///
850    /// # Panics
851    ///
852    /// - If the [`Func`] does not originate from this [`Store`].
853    /// - If the [`Func`] cannot be resolved to its entity.
854    pub fn resolve_func(&self, func: &Func) -> &FuncEntity {
855        let entity_index = self.unwrap_stored(func.as_inner());
856        self.funcs.get(entity_index).unwrap_or_else(|| {
857            panic!("failed to resolve stored Wasm or host function: {entity_index:?}")
858        })
859    }
860}
861
862impl<T> Default for Store<T>
863where
864    T: Default,
865{
866    fn default() -> Self {
867        let engine = Engine::default();
868        Self {
869            inner: StoreInner::new(&engine),
870            trampolines: Arena::new(),
871            data: T::default(),
872            limiter: None,
873            call_hook: None,
874        }
875    }
876}
877
878impl<T> Store<T> {
879    /// Creates a new store.
880    pub fn new(engine: &Engine, data: T) -> Self {
881        Self {
882            inner: StoreInner::new(engine),
883            trampolines: Arena::new(),
884            data,
885            limiter: None,
886            call_hook: None,
887        }
888    }
889
890    /// Returns the [`Engine`] that this store is associated with.
891    pub fn engine(&self) -> &Engine {
892        self.inner.engine()
893    }
894
895    /// Returns a shared reference to the user provided data owned by this [`Store`].
896    pub fn data(&self) -> &T {
897        &self.data
898    }
899
900    /// Returns an exclusive reference to the user provided data owned by this [`Store`].
901    pub fn data_mut(&mut self) -> &mut T {
902        &mut self.data
903    }
904
905    /// Consumes `self` and returns its user provided data.
906    pub fn into_data(self) -> T {
907        self.data
908    }
909
910    /// Installs a function into the [`Store`] that will be called with the user
911    /// data type `T` to retrieve a [`ResourceLimiter`] any time a limited,
912    /// growable resource such as a linear memory or table is grown.
913    pub fn limiter(
914        &mut self,
915        limiter: impl FnMut(&mut T) -> &mut (dyn ResourceLimiter) + Send + Sync + 'static,
916    ) {
917        self.limiter = Some(ResourceLimiterQuery(Box::new(limiter)))
918    }
919
920    pub(crate) fn check_new_instances_limit(
921        &mut self,
922        num_new_instances: usize,
923    ) -> Result<(), InstantiationError> {
924        let (inner, mut limiter) = self.store_inner_and_resource_limiter_ref();
925        if let Some(limiter) = limiter.as_resource_limiter() {
926            if inner.instances.len().saturating_add(num_new_instances) > limiter.instances() {
927                return Err(InstantiationError::TooManyInstances);
928            }
929        }
930        Ok(())
931    }
932
933    pub(crate) fn check_new_memories_limit(
934        &mut self,
935        num_new_memories: usize,
936    ) -> Result<(), MemoryError> {
937        let (inner, mut limiter) = self.store_inner_and_resource_limiter_ref();
938        if let Some(limiter) = limiter.as_resource_limiter() {
939            if inner.memories.len().saturating_add(num_new_memories) > limiter.memories() {
940                return Err(MemoryError::TooManyMemories);
941            }
942        }
943        Ok(())
944    }
945
946    pub(crate) fn check_new_tables_limit(
947        &mut self,
948        num_new_tables: usize,
949    ) -> Result<(), TableError> {
950        let (inner, mut limiter) = self.store_inner_and_resource_limiter_ref();
951        if let Some(limiter) = limiter.as_resource_limiter() {
952            if inner.tables.len().saturating_add(num_new_tables) > limiter.tables() {
953                return Err(TableError::TooManyTables);
954            }
955        }
956        Ok(())
957    }
958
959    pub(crate) fn store_inner_and_resource_limiter_ref(
960        &mut self,
961    ) -> (&mut StoreInner, ResourceLimiterRef) {
962        let resource_limiter = ResourceLimiterRef(match &mut self.limiter {
963            Some(q) => Some(q.0(&mut self.data)),
964            None => None,
965        });
966        (&mut self.inner, resource_limiter)
967    }
968
969    /// Returns the remaining fuel of the [`Store`] if fuel metering is enabled.
970    ///
971    /// # Note
972    ///
973    /// Enable fuel metering via [`Config::consume_fuel`](crate::Config::consume_fuel).
974    ///
975    /// # Errors
976    ///
977    /// If fuel metering is disabled.
978    pub fn get_fuel(&self) -> Result<u64, Error> {
979        self.inner.fuel.get_fuel().map_err(Into::into)
980    }
981
982    /// Sets the remaining fuel of the [`Store`] to `value` if fuel metering is enabled.
983    ///
984    /// # Note
985    ///
986    /// Enable fuel metering via [`Config::consume_fuel`](crate::Config::consume_fuel).
987    ///
988    /// # Errors
989    ///
990    /// If fuel metering is disabled.
991    pub fn set_fuel(&mut self, fuel: u64) -> Result<(), Error> {
992        self.inner.fuel.set_fuel(fuel).map_err(Into::into)
993    }
994
995    /// Allocates a new [`TrampolineEntity`] and returns a [`Trampoline`] reference to it.
996    pub(super) fn alloc_trampoline(&mut self, func: TrampolineEntity<T>) -> Trampoline {
997        let idx = self.trampolines.alloc(func);
998        Trampoline::from_inner(self.inner.wrap_stored(idx))
999    }
1000
1001    /// Returns an exclusive reference to the [`MemoryEntity`] associated to the given [`Memory`]
1002    /// and an exclusive reference to the user provided host state.
1003    ///
1004    /// # Note
1005    ///
1006    /// This method exists to properly handle use cases where
1007    /// otherwise the Rust borrow-checker would not accept.
1008    ///
1009    /// # Panics
1010    ///
1011    /// - If the [`Memory`] does not originate from this [`Store`].
1012    /// - If the [`Memory`] cannot be resolved to its entity.
1013    pub(super) fn resolve_memory_and_state_mut(
1014        &mut self,
1015        memory: &Memory,
1016    ) -> (&mut MemoryEntity, &mut T) {
1017        (self.inner.resolve_memory_mut(memory), &mut self.data)
1018    }
1019
1020    /// Returns a shared reference to the associated entity of the host function trampoline.
1021    ///
1022    /// # Panics
1023    ///
1024    /// - If the [`Trampoline`] does not originate from this [`Store`].
1025    /// - If the [`Trampoline`] cannot be resolved to its entity.
1026    pub(super) fn resolve_trampoline(&self, func: &Trampoline) -> &TrampolineEntity<T> {
1027        let entity_index = self.inner.unwrap_stored(func.as_inner());
1028        self.trampolines
1029            .get(entity_index)
1030            .unwrap_or_else(|| panic!("failed to resolve stored host function: {entity_index:?}"))
1031    }
1032
1033    /// Sets a callback function that is executed whenever a WebAssembly
1034    /// function is called from the host or a host function is called from
1035    /// WebAssembly, or these functions return.
1036    ///
1037    /// The function is passed a `&mut T` to the underlying store, and a
1038    /// [`CallHook`]. [`CallHook`] can be used to find out what kind of function
1039    /// is being called or returned from.
1040    ///
1041    /// The callback can either return `Ok(())` or an `Err` with an
1042    /// [`Error`]. If an error is returned, it is returned to the host
1043    /// caller. If there are nested calls, only the most recent host caller
1044    /// receives the error and it is not propagated further automatically. The
1045    /// hook may be invoked again as new functions are called and returned from.
1046    pub fn call_hook(
1047        &mut self,
1048        hook: impl FnMut(&mut T, CallHook) -> Result<(), Error> + Send + Sync + 'static,
1049    ) {
1050        self.call_hook = Some(CallHookWrapper(Box::new(hook)));
1051    }
1052
1053    /// Executes the callback set by [`Store::call_hook`] if any has been set.
1054    ///
1055    /// # Note
1056    ///
1057    /// - Returns the value returned by the call hook.
1058    /// - Returns `Ok(())` if no call hook exists.
1059    #[inline]
1060    pub(crate) fn invoke_call_hook(&mut self, call_type: CallHook) -> Result<(), Error> {
1061        match self.call_hook.as_mut() {
1062            None => Ok(()),
1063            Some(call_hook) => Self::invoke_call_hook_impl(&mut self.data, call_type, call_hook),
1064        }
1065    }
1066
1067    /// Utility function to invoke the [`Store::call_hook`] that is asserted to
1068    /// be available in this case.
1069    ///
1070    /// This is kept as a separate `#[cold]` function to help the compiler speed
1071    /// up the code path without any call hooks.
1072    #[cold]
1073    fn invoke_call_hook_impl(
1074        data: &mut T,
1075        call_type: CallHook,
1076        call_hook: &mut CallHookWrapper<T>,
1077    ) -> Result<(), Error> {
1078        call_hook.0(data, call_type)
1079    }
1080}
1081
1082/// A trait used to get shared access to a [`Store`] in Wasmi.
1083pub trait AsContext {
1084    /// The user state associated with the [`Store`], aka the `T` in `Store<T>`.
1085    type Data;
1086
1087    /// Returns the store context that this type provides access to.
1088    fn as_context(&self) -> StoreContext<Self::Data>;
1089}
1090
1091/// A trait used to get exclusive access to a [`Store`] in Wasmi.
1092pub trait AsContextMut: AsContext {
1093    /// Returns the store context that this type provides access to.
1094    fn as_context_mut(&mut self) -> StoreContextMut<Self::Data>;
1095}
1096
1097/// A temporary handle to a [`&Store<T>`][`Store`].
1098///
1099/// This type is suitable for [`AsContext`] trait bounds on methods if desired.
1100/// For more information, see [`Store`].
1101#[derive(Debug, Copy, Clone)]
1102#[repr(transparent)]
1103pub struct StoreContext<'a, T> {
1104    pub(crate) store: &'a Store<T>,
1105}
1106
1107impl<T> StoreContext<'_, T> {
1108    /// Returns the underlying [`Engine`] this store is connected to.
1109    pub fn engine(&self) -> &Engine {
1110        self.store.engine()
1111    }
1112
1113    /// Access the underlying data owned by this store.
1114    ///
1115    /// Same as [`Store::data`].
1116    pub fn data(&self) -> &T {
1117        self.store.data()
1118    }
1119
1120    /// Returns the remaining fuel of the [`Store`] if fuel metering is enabled.
1121    ///
1122    /// For more information see [`Store::get_fuel`](crate::Store::get_fuel).
1123    ///
1124    /// # Errors
1125    ///
1126    /// If fuel metering is disabled.
1127    pub fn get_fuel(&self) -> Result<u64, Error> {
1128        self.store.get_fuel()
1129    }
1130}
1131
1132impl<'a, T: AsContext> From<&'a T> for StoreContext<'a, T::Data> {
1133    #[inline]
1134    fn from(ctx: &'a T) -> Self {
1135        ctx.as_context()
1136    }
1137}
1138
1139impl<'a, T: AsContext> From<&'a mut T> for StoreContext<'a, T::Data> {
1140    #[inline]
1141    fn from(ctx: &'a mut T) -> Self {
1142        T::as_context(ctx)
1143    }
1144}
1145
1146impl<'a, T: AsContextMut> From<&'a mut T> for StoreContextMut<'a, T::Data> {
1147    #[inline]
1148    fn from(ctx: &'a mut T) -> Self {
1149        ctx.as_context_mut()
1150    }
1151}
1152
1153/// A temporary handle to a [`&mut Store<T>`][`Store`].
1154///
1155/// This type is suitable for [`AsContextMut`] or [`AsContext`] trait bounds on methods if desired.
1156/// For more information, see [`Store`].
1157#[derive(Debug)]
1158#[repr(transparent)]
1159pub struct StoreContextMut<'a, T> {
1160    pub(crate) store: &'a mut Store<T>,
1161}
1162
1163impl<T> StoreContextMut<'_, T> {
1164    /// Returns the underlying [`Engine`] this store is connected to.
1165    pub fn engine(&self) -> &Engine {
1166        self.store.engine()
1167    }
1168
1169    /// Access the underlying data owned by this store.
1170    ///
1171    /// Same as [`Store::data`].
1172    pub fn data(&self) -> &T {
1173        self.store.data()
1174    }
1175
1176    /// Access the underlying data owned by this store.
1177    ///
1178    /// Same as [`Store::data_mut`].
1179    pub fn data_mut(&mut self) -> &mut T {
1180        self.store.data_mut()
1181    }
1182
1183    /// Returns the remaining fuel of the [`Store`] if fuel metering is enabled.
1184    ///
1185    /// For more information see [`Store::get_fuel`](crate::Store::get_fuel).
1186    ///
1187    /// # Errors
1188    ///
1189    /// If fuel metering is disabled.
1190    pub fn get_fuel(&self) -> Result<u64, Error> {
1191        self.store.get_fuel()
1192    }
1193
1194    /// Sets the remaining fuel of the [`Store`] to `value` if fuel metering is enabled.
1195    ///
1196    /// For more information see [`Store::get_fuel`](crate::Store::set_fuel).
1197    ///
1198    /// # Errors
1199    ///
1200    /// If fuel metering is disabled.
1201    pub fn set_fuel(&mut self, fuel: u64) -> Result<(), Error> {
1202        self.store.set_fuel(fuel)
1203    }
1204}
1205
1206impl<T> AsContext for &'_ T
1207where
1208    T: AsContext,
1209{
1210    type Data = T::Data;
1211
1212    #[inline]
1213    fn as_context(&self) -> StoreContext<'_, T::Data> {
1214        T::as_context(*self)
1215    }
1216}
1217
1218impl<T> AsContext for &'_ mut T
1219where
1220    T: AsContext,
1221{
1222    type Data = T::Data;
1223
1224    #[inline]
1225    fn as_context(&self) -> StoreContext<'_, T::Data> {
1226        T::as_context(*self)
1227    }
1228}
1229
1230impl<T> AsContextMut for &'_ mut T
1231where
1232    T: AsContextMut,
1233{
1234    #[inline]
1235    fn as_context_mut(&mut self) -> StoreContextMut<'_, T::Data> {
1236        T::as_context_mut(*self)
1237    }
1238}
1239
1240impl<T> AsContext for StoreContext<'_, T> {
1241    type Data = T;
1242
1243    #[inline]
1244    fn as_context(&self) -> StoreContext<'_, Self::Data> {
1245        StoreContext { store: self.store }
1246    }
1247}
1248
1249impl<T> AsContext for StoreContextMut<'_, T> {
1250    type Data = T;
1251
1252    #[inline]
1253    fn as_context(&self) -> StoreContext<'_, Self::Data> {
1254        StoreContext { store: self.store }
1255    }
1256}
1257
1258impl<T> AsContextMut for StoreContextMut<'_, T> {
1259    #[inline]
1260    fn as_context_mut(&mut self) -> StoreContextMut<'_, Self::Data> {
1261        StoreContextMut {
1262            store: &mut *self.store,
1263        }
1264    }
1265}
1266
1267impl<T> AsContext for Store<T> {
1268    type Data = T;
1269
1270    #[inline]
1271    fn as_context(&self) -> StoreContext<'_, Self::Data> {
1272        StoreContext { store: self }
1273    }
1274}
1275
1276impl<T> AsContextMut for Store<T> {
1277    #[inline]
1278    fn as_context_mut(&mut self) -> StoreContextMut<'_, Self::Data> {
1279        StoreContextMut { store: self }
1280    }
1281}