1 //! Wasmtime's "store" type
2 //!
3 //! This module, and its submodules, contain the `Store` type and various types
4 //! used to interact with it. At first glance this is a pretty confusing module
5 //! where you need to know the difference between:
6 //!
7 //! * `Store<T>`
8 //! * `StoreContext<T>`
9 //! * `StoreContextMut<T>`
10 //! * `AsContext`
11 //! * `AsContextMut`
12 //! * `StoreInner<T>`
13 //! * `StoreOpaque`
14 //! * `StoreData`
15 //!
16 //! There's... quite a lot going on here, and it's easy to be confused. This
17 //! comment is ideally going to serve the purpose of clarifying what all these
18 //! types are for and why they're motivated.
19 //!
20 //! First it's important to know what's "internal" and what's "external". Almost
21 //! everything above is defined as `pub`, but only some of the items are
22 //! reexported to the outside world to be usable from this crate. Otherwise all
23 //! items are `pub` within this `store` module, and the `store` module is
24 //! private to the `wasmtime` crate. Notably `Store<T>`, `StoreContext<T>`,
25 //! `StoreContextMut<T>`, `AsContext`, and `AsContextMut` are all public
26 //! interfaces to the `wasmtime` crate. You can think of these as:
27 //!
28 //! * `Store<T>` - an owned reference to a store, the "root of everything"
29 //! * `StoreContext<T>` - basically `&StoreInner<T>`
30 //! * `StoreContextMut<T>` - more-or-less `&mut StoreInner<T>` with caveats.
31 //!   Explained later.
32 //! * `AsContext` - similar to `AsRef`, but produces `StoreContext<T>`
33 //! * `AsContextMut` - similar to `AsMut`, but produces `StoreContextMut<T>`
34 //!
35 //! Next comes the internal structure of the `Store<T>` itself. This looks like:
36 //!
37 //! * `Store<T>` - this type is just a pointer large. It's primarily just
38 //!   intended to be consumed by the outside world. Note that the "just a
39 //!   pointer large" is a load-bearing implementation detail in Wasmtime. This
40 //!   enables it to store a pointer to its own trait object which doesn't need
41 //!   to change over time.
42 //!
43 //! * `StoreInner<T>` - the first layer of the contents of a `Store<T>`, what's
44 //!   stored inside the `Box`. This is the general Rust pattern when one struct
45 //!   is a layer over another. The surprising part, though, is that this is
46 //!   further subdivided. This structure only contains things which actually
47 //!   need `T` itself. The downside of this structure is that it's always
48 //!   generic and means that code is monomorphized into consumer crates. We
49 //!   strive to have things be as monomorphic as possible in `wasmtime` so this
50 //!   type is not heavily used.
51 //!
52 //! * `StoreOpaque` - this is the primary contents of the `StoreInner<T>` type.
53 //!   Stored inline in the outer type the "opaque" here means that it's a
54 //!   "store" but it doesn't have access to the `T`. This is the primary
55 //!   "internal" reference that Wasmtime uses since `T` is rarely needed by the
56 //!   internals of Wasmtime.
57 //!
58 //! * `StoreData` - this is a final helper struct stored within `StoreOpaque`.
59 //!   All references of Wasm items into a `Store` are actually indices into a
60 //!   table in this structure, and the `StoreData` being separate makes it a bit
61 //!   easier to manage/define/work with. There's no real fundamental reason this
62 //!   is split out, although sometimes it's useful to have separate borrows into
63 //!   these tables than the `StoreOpaque`.
64 //!
65 //! A major caveat with these representations is that the internal `&mut
66 //! StoreInner<T>` is never handed out publicly to consumers of this crate, only
67 //! through a wrapper of `StoreContextMut<'_, T>`. The reason for this is that
68 //! we want to provide mutable, but not destructive, access to the contents of a
69 //! `Store`. For example if a `StoreInner<T>` were replaced with some other
70 //! `StoreInner<T>` then that would drop live instances, possibly those
71 //! currently executing beneath the current stack frame. This would not be a
72 //! safe operation.
73 //!
74 //! This means, though, that the `wasmtime` crate, which liberally uses `&mut
75 //! StoreOpaque` internally, has to be careful to never actually destroy the
76 //! contents of `StoreOpaque`. This is an invariant that we, as the authors of
77 //! `wasmtime`, must uphold for the public interface to be safe.
78 
79 use crate::RootSet;
80 #[cfg(feature = "component-model-async")]
81 use crate::component::ComponentStoreData;
82 #[cfg(feature = "component-model-async")]
83 use crate::component::concurrent;
84 #[cfg(feature = "async")]
85 use crate::fiber;
86 use crate::module::RegisteredModuleId;
87 use crate::prelude::*;
88 #[cfg(feature = "gc")]
89 use crate::runtime::vm::GcRootsList;
90 #[cfg(feature = "stack-switching")]
91 use crate::runtime::vm::VMContRef;
92 use crate::runtime::vm::mpk::ProtectionKey;
93 use crate::runtime::vm::{
94     self, GcStore, Imports, InstanceAllocationRequest, InstanceAllocator, InstanceHandle,
95     Interpreter, InterpreterRef, ModuleRuntimeInfo, OnDemandInstanceAllocator, SendSyncPtr,
96     SignalHandler, StoreBox, StorePtr, Unwind, VMContext, VMFuncRef, VMGcRef, VMStoreContext,
97 };
98 use crate::trampoline::VMHostGlobalContext;
99 use crate::{Engine, Module, Trap, Val, ValRaw, module::ModuleRegistry};
100 use crate::{Global, Instance, Memory, Table, Uninhabited};
101 use alloc::sync::Arc;
102 use core::fmt;
103 use core::marker;
104 use core::mem::{self, ManuallyDrop, MaybeUninit};
105 use core::num::NonZeroU64;
106 use core::ops::{Deref, DerefMut};
107 use core::pin::Pin;
108 use core::ptr::NonNull;
109 use wasmtime_environ::{DefinedGlobalIndex, DefinedTableIndex, EntityRef, PrimaryMap, TripleExt};
110 
111 mod context;
112 pub use self::context::*;
113 mod data;
114 pub use self::data::*;
115 mod func_refs;
116 use func_refs::FuncRefs;
117 #[cfg(feature = "async")]
118 mod token;
119 #[cfg(feature = "async")]
120 pub(crate) use token::StoreToken;
121 #[cfg(feature = "async")]
122 mod async_;
123 #[cfg(all(feature = "async", feature = "call-hook"))]
124 pub use self::async_::CallHookHandler;
125 #[cfg(feature = "gc")]
126 mod gc;
127 
128 /// A [`Store`] is a collection of WebAssembly instances and host-defined state.
129 ///
130 /// All WebAssembly instances and items will be attached to and refer to a
131 /// [`Store`]. For example instances, functions, globals, and tables are all
132 /// attached to a [`Store`]. Instances are created by instantiating a
133 /// [`Module`](crate::Module) within a [`Store`].
134 ///
135 /// A [`Store`] is intended to be a short-lived object in a program. No form
136 /// of GC is implemented at this time so once an instance is created within a
137 /// [`Store`] it will not be deallocated until the [`Store`] itself is dropped.
138 /// This makes [`Store`] unsuitable for creating an unbounded number of
139 /// instances in it because [`Store`] will never release this memory. It's
140 /// recommended to have a [`Store`] correspond roughly to the lifetime of a
141 /// "main instance" that an embedding is interested in executing.
142 ///
143 /// ## Type parameter `T`
144 ///
145 /// Each [`Store`] has a type parameter `T` associated with it. This `T`
146 /// represents state defined by the host. This state will be accessible through
147 /// the [`Caller`](crate::Caller) type that host-defined functions get access
148 /// to. This `T` is suitable for storing `Store`-specific information which
149 /// imported functions may want access to.
150 ///
151 /// The data `T` can be accessed through methods like [`Store::data`] and
152 /// [`Store::data_mut`].
153 ///
154 /// ## Stores, contexts, oh my
155 ///
156 /// Most methods in Wasmtime take something of the form
157 /// [`AsContext`](crate::AsContext) or [`AsContextMut`](crate::AsContextMut) as
158 /// the first argument. These two traits allow ergonomically passing in the
159 /// context you currently have to any method. The primary two sources of
160 /// contexts are:
161 ///
162 /// * `Store<T>`
163 /// * `Caller<'_, T>`
164 ///
165 /// corresponding to what you create and what you have access to in a host
166 /// function. You can also explicitly acquire a [`StoreContext`] or
167 /// [`StoreContextMut`] and pass that around as well.
168 ///
169 /// Note that all methods on [`Store`] are mirrored onto [`StoreContext`],
170 /// [`StoreContextMut`], and [`Caller`](crate::Caller). This way no matter what
171 /// form of context you have you can call various methods, create objects, etc.
172 ///
173 /// ## Stores and `Default`
174 ///
175 /// You can create a store with default configuration settings using
176 /// `Store::default()`. This will create a brand new [`Engine`] with default
177 /// configuration (see [`Config`](crate::Config) for more information).
178 ///
179 /// ## Cross-store usage of items
180 ///
181 /// In `wasmtime` wasm items such as [`Global`] and [`Memory`] "belong" to a
182 /// [`Store`]. The store they belong to is the one they were created with
183 /// (passed in as a parameter) or instantiated with. This store is the only
184 /// store that can be used to interact with wasm items after they're created.
185 ///
186 /// The `wasmtime` crate will panic if the [`Store`] argument passed in to these
187 /// operations is incorrect. In other words it's considered a programmer error
188 /// rather than a recoverable error for the wrong [`Store`] to be used when
189 /// calling APIs.
190 pub struct Store<T: 'static> {
191     // for comments about `ManuallyDrop`, see `Store::into_data`
192     inner: ManuallyDrop<Box<StoreInner<T>>>,
193 }
194 
195 #[derive(Copy, Clone, Debug)]
196 /// Passed to the argument of [`Store::call_hook`] to indicate a state transition in
197 /// the WebAssembly VM.
198 pub enum CallHook {
199     /// Indicates the VM is calling a WebAssembly function, from the host.
200     CallingWasm,
201     /// Indicates the VM is returning from a WebAssembly function, to the host.
202     ReturningFromWasm,
203     /// Indicates the VM is calling a host function, from WebAssembly.
204     CallingHost,
205     /// Indicates the VM is returning from a host function, to WebAssembly.
206     ReturningFromHost,
207 }
208 
209 impl CallHook {
210     /// Indicates the VM is entering host code (exiting WebAssembly code)
211     pub fn entering_host(&self) -> bool {
212         match self {
213             CallHook::ReturningFromWasm | CallHook::CallingHost => true,
214             _ => false,
215         }
216     }
217     /// Indicates the VM is exiting host code (entering WebAssembly code)
218     pub fn exiting_host(&self) -> bool {
219         match self {
220             CallHook::ReturningFromHost | CallHook::CallingWasm => true,
221             _ => false,
222         }
223     }
224 }
225 
226 /// Internal contents of a `Store<T>` that live on the heap.
227 ///
228 /// The members of this struct are those that need to be generic over `T`, the
229 /// store's internal type storage. Otherwise all things that don't rely on `T`
230 /// should go into `StoreOpaque`.
231 pub struct StoreInner<T: 'static> {
232     /// Generic metadata about the store that doesn't need access to `T`.
233     inner: StoreOpaque,
234 
235     limiter: Option<ResourceLimiterInner<T>>,
236     call_hook: Option<CallHookInner<T>>,
237     #[cfg(target_has_atomic = "64")]
238     epoch_deadline_behavior:
239         Option<Box<dyn FnMut(StoreContextMut<T>) -> Result<UpdateDeadline> + Send + Sync>>,
240     // for comments about `ManuallyDrop`, see `Store::into_data`
241     data: ManuallyDrop<T>,
242 }
243 
244 enum ResourceLimiterInner<T> {
245     Sync(Box<dyn (FnMut(&mut T) -> &mut dyn crate::ResourceLimiter) + Send + Sync>),
246     #[cfg(feature = "async")]
247     Async(Box<dyn (FnMut(&mut T) -> &mut dyn crate::ResourceLimiterAsync) + Send + Sync>),
248 }
249 
250 enum CallHookInner<T: 'static> {
251     #[cfg(feature = "call-hook")]
252     Sync(Box<dyn FnMut(StoreContextMut<'_, T>, CallHook) -> Result<()> + Send + Sync>),
253     #[cfg(all(feature = "async", feature = "call-hook"))]
254     Async(Box<dyn CallHookHandler<T> + Send + Sync>),
255     #[expect(
256         dead_code,
257         reason = "forcing, regardless of cfg, the type param to be used"
258     )]
259     ForceTypeParameterToBeUsed {
260         uninhabited: Uninhabited,
261         _marker: marker::PhantomData<T>,
262     },
263 }
264 
265 /// What to do after returning from a callback when the engine epoch reaches
266 /// the deadline for a Store during execution of a function using that store.
267 #[non_exhaustive]
268 pub enum UpdateDeadline {
269     /// Extend the deadline by the specified number of ticks.
270     Continue(u64),
271     /// Extend the deadline by the specified number of ticks after yielding to
272     /// the async executor loop. This can only be used with an async [`Store`]
273     /// configured via [`Config::async_support`](crate::Config::async_support).
274     #[cfg(feature = "async")]
275     Yield(u64),
276     /// Extend the deadline by the specified number of ticks after yielding to
277     /// the async executor loop. This can only be used with an async [`Store`]
278     /// configured via [`Config::async_support`](crate::Config::async_support).
279     ///
280     /// The yield will be performed by the future provided; when using `tokio`
281     /// it is recommended to provide [`tokio::task::yield_now`](https://docs.rs/tokio/latest/tokio/task/fn.yield_now.html)
282     /// here.
283     #[cfg(feature = "async")]
284     YieldCustom(
285         u64,
286         ::core::pin::Pin<Box<dyn ::core::future::Future<Output = ()> + Send>>,
287     ),
288 }
289 
290 // Forward methods on `StoreOpaque` to also being on `StoreInner<T>`
291 impl<T> Deref for StoreInner<T> {
292     type Target = StoreOpaque;
293     fn deref(&self) -> &Self::Target {
294         &self.inner
295     }
296 }
297 
298 impl<T> DerefMut for StoreInner<T> {
299     fn deref_mut(&mut self) -> &mut Self::Target {
300         &mut self.inner
301     }
302 }
303 
304 /// Monomorphic storage for a `Store<T>`.
305 ///
306 /// This structure contains the bulk of the metadata about a `Store`. This is
307 /// used internally in Wasmtime when dependence on the `T` of `Store<T>` isn't
308 /// necessary, allowing code to be monomorphic and compiled into the `wasmtime`
309 /// crate itself.
310 pub struct StoreOpaque {
311     // This `StoreOpaque` structure has references to itself. These aren't
312     // immediately evident, however, so we need to tell the compiler that it
313     // contains self-references. This notably suppresses `noalias` annotations
314     // when this shows up in compiled code because types of this structure do
315     // indeed alias itself. An example of this is `default_callee` holds a
316     // `*mut dyn Store` to the address of this `StoreOpaque` itself, indeed
317     // aliasing!
318     //
319     // It's somewhat unclear to me at this time if this is 100% sufficient to
320     // get all the right codegen in all the right places. For example does
321     // `Store` need to internally contain a `Pin<Box<StoreInner<T>>>`? Do the
322     // contexts need to contain `Pin<&mut StoreInner<T>>`? I'm not familiar
323     // enough with `Pin` to understand if it's appropriate here (we do, for
324     // example want to allow movement in and out of `data: T`, just not movement
325     // of most of the other members). It's also not clear if using `Pin` in a
326     // few places buys us much other than a bunch of `unsafe` that we already
327     // sort of hand-wave away.
328     //
329     // In any case this seems like a good mid-ground for now where we're at
330     // least telling the compiler something about all the aliasing happening
331     // within a `Store`.
332     _marker: marker::PhantomPinned,
333 
334     engine: Engine,
335     vm_store_context: VMStoreContext,
336 
337     // Contains all continuations ever allocated throughout the lifetime of this
338     // store.
339     #[cfg(feature = "stack-switching")]
340     continuations: Vec<Box<VMContRef>>,
341 
342     instances: PrimaryMap<InstanceId, StoreInstance>,
343 
344     #[cfg(feature = "component-model")]
345     num_component_instances: usize,
346     signal_handler: Option<SignalHandler>,
347     modules: ModuleRegistry,
348     func_refs: FuncRefs,
349     host_globals: PrimaryMap<DefinedGlobalIndex, StoreBox<VMHostGlobalContext>>,
350     // GC-related fields.
351     gc_store: Option<GcStore>,
352     gc_roots: RootSet,
353     #[cfg(feature = "gc")]
354     gc_roots_list: GcRootsList,
355     // Types for which the embedder has created an allocator for.
356     #[cfg(feature = "gc")]
357     gc_host_alloc_types: crate::hash_set::HashSet<crate::type_registry::RegisteredType>,
358 
359     // Numbers of resources instantiated in this store, and their limits
360     instance_count: usize,
361     instance_limit: usize,
362     memory_count: usize,
363     memory_limit: usize,
364     table_count: usize,
365     table_limit: usize,
366     #[cfg(feature = "async")]
367     async_state: fiber::AsyncState,
368 
369     // If fuel_yield_interval is enabled, then we store the remaining fuel (that isn't in
370     // runtime_limits) here. The total amount of fuel is the runtime limits and reserve added
371     // together. Then when we run out of gas, we inject the yield amount from the reserve
372     // until the reserve is empty.
373     fuel_reserve: u64,
374     fuel_yield_interval: Option<NonZeroU64>,
375     /// Indexed data within this `Store`, used to store information about
376     /// globals, functions, memories, etc.
377     store_data: StoreData,
378     traitobj: StorePtr,
379     default_caller_vmctx: SendSyncPtr<VMContext>,
380 
381     /// Used to optimized wasm->host calls when the host function is defined with
382     /// `Func::new` to avoid allocating a new vector each time a function is
383     /// called.
384     hostcall_val_storage: Vec<Val>,
385     /// Same as `hostcall_val_storage`, but for the direction of the host
386     /// calling wasm.
387     wasm_val_raw_storage: Vec<ValRaw>,
388 
389     /// Keep track of what protection key is being used during allocation so
390     /// that the right memory pages can be enabled when entering WebAssembly
391     /// guest code.
392     pkey: Option<ProtectionKey>,
393 
394     /// Runtime state for components used in the handling of resources, borrow,
395     /// and calls. These also interact with the `ResourceAny` type and its
396     /// internal representation.
397     #[cfg(feature = "component-model")]
398     component_host_table: vm::component::HandleTable,
399     #[cfg(feature = "component-model")]
400     component_calls: vm::component::CallContexts,
401     #[cfg(feature = "component-model")]
402     host_resource_data: crate::component::HostResourceData,
403 
404     #[cfg(feature = "component-model-async")]
405     concurrent_async_state: concurrent::AsyncState,
406 
407     /// State related to the executor of wasm code.
408     ///
409     /// For example if Pulley is enabled and configured then this will store a
410     /// Pulley interpreter.
411     executor: Executor,
412 }
413 
414 /// Executor state within `StoreOpaque`.
415 ///
416 /// Effectively stores Pulley interpreter state and handles conditional support
417 /// for Cranelift at compile time.
418 pub(crate) enum Executor {
419     Interpreter(Interpreter),
420     #[cfg(has_host_compiler_backend)]
421     Native,
422 }
423 
424 impl Executor {
425     pub(crate) fn new(engine: &Engine) -> Self {
426         #[cfg(has_host_compiler_backend)]
427         if cfg!(feature = "pulley") && engine.target().is_pulley() {
428             Executor::Interpreter(Interpreter::new(engine))
429         } else {
430             Executor::Native
431         }
432         #[cfg(not(has_host_compiler_backend))]
433         {
434             debug_assert!(engine.target().is_pulley());
435             Executor::Interpreter(Interpreter::new(engine))
436         }
437     }
438 }
439 
440 /// A borrowed reference to `Executor` above.
441 pub(crate) enum ExecutorRef<'a> {
442     Interpreter(InterpreterRef<'a>),
443     #[cfg(has_host_compiler_backend)]
444     Native,
445 }
446 
447 /// An RAII type to automatically mark a region of code as unsafe for GC.
448 #[doc(hidden)]
449 pub struct AutoAssertNoGc<'a> {
450     store: &'a mut StoreOpaque,
451     entered: bool,
452 }
453 
454 impl<'a> AutoAssertNoGc<'a> {
455     #[inline]
456     pub fn new(store: &'a mut StoreOpaque) -> Self {
457         let entered = if !cfg!(feature = "gc") {
458             false
459         } else if let Some(gc_store) = store.gc_store.as_mut() {
460             gc_store.gc_heap.enter_no_gc_scope();
461             true
462         } else {
463             false
464         };
465 
466         AutoAssertNoGc { store, entered }
467     }
468 
469     /// Creates an `AutoAssertNoGc` value which is forcibly "not entered" and
470     /// disables checks for no GC happening for the duration of this value.
471     ///
472     /// This is used when it is statically otherwise known that a GC doesn't
473     /// happen for the various types involved.
474     ///
475     /// # Unsafety
476     ///
477     /// This method is `unsafe` as it does not provide the same safety
478     /// guarantees as `AutoAssertNoGc::new`. It must be guaranteed by the
479     /// caller that a GC doesn't happen.
480     #[inline]
481     pub unsafe fn disabled(store: &'a mut StoreOpaque) -> Self {
482         if cfg!(debug_assertions) {
483             AutoAssertNoGc::new(store)
484         } else {
485             AutoAssertNoGc {
486                 store,
487                 entered: false,
488             }
489         }
490     }
491 }
492 
493 impl core::ops::Deref for AutoAssertNoGc<'_> {
494     type Target = StoreOpaque;
495 
496     #[inline]
497     fn deref(&self) -> &Self::Target {
498         &*self.store
499     }
500 }
501 
502 impl core::ops::DerefMut for AutoAssertNoGc<'_> {
503     #[inline]
504     fn deref_mut(&mut self) -> &mut Self::Target {
505         &mut *self.store
506     }
507 }
508 
509 impl Drop for AutoAssertNoGc<'_> {
510     #[inline]
511     fn drop(&mut self) {
512         if self.entered {
513             self.store.unwrap_gc_store_mut().gc_heap.exit_no_gc_scope();
514         }
515     }
516 }
517 
518 /// Used to associate instances with the store.
519 ///
520 /// This is needed to track if the instance was allocated explicitly with the on-demand
521 /// instance allocator.
522 struct StoreInstance {
523     handle: InstanceHandle,
524     kind: StoreInstanceKind,
525 }
526 
527 enum StoreInstanceKind {
528     /// An actual, non-dummy instance.
529     Real {
530         /// The id of this instance's module inside our owning store's
531         /// `ModuleRegistry`.
532         module_id: RegisteredModuleId,
533     },
534 
535     /// This is a dummy instance that is just an implementation detail for
536     /// something else. For example, host-created memories internally create a
537     /// dummy instance.
538     ///
539     /// Regardless of the configured instance allocator for the engine, dummy
540     /// instances always use the on-demand allocator to deallocate the instance.
541     Dummy,
542 }
543 
544 impl<T> Store<T> {
545     /// Creates a new [`Store`] to be associated with the given [`Engine`] and
546     /// `data` provided.
547     ///
548     /// The created [`Store`] will place no additional limits on the size of
549     /// linear memories or tables at runtime. Linear memories and tables will
550     /// be allowed to grow to any upper limit specified in their definitions.
551     /// The store will limit the number of instances, linear memories, and
552     /// tables created to 10,000. This can be overridden with the
553     /// [`Store::limiter`] configuration method.
554     pub fn new(engine: &Engine, data: T) -> Self {
555         let store_data = StoreData::new();
556         log::trace!("creating new store {:?}", store_data.id());
557 
558         let pkey = engine.allocator().next_available_pkey();
559 
560         let inner = StoreOpaque {
561             _marker: marker::PhantomPinned,
562             engine: engine.clone(),
563             vm_store_context: Default::default(),
564             #[cfg(feature = "stack-switching")]
565             continuations: Vec::new(),
566             instances: PrimaryMap::new(),
567             #[cfg(feature = "component-model")]
568             num_component_instances: 0,
569             signal_handler: None,
570             gc_store: None,
571             gc_roots: RootSet::default(),
572             #[cfg(feature = "gc")]
573             gc_roots_list: GcRootsList::default(),
574             #[cfg(feature = "gc")]
575             gc_host_alloc_types: Default::default(),
576             modules: ModuleRegistry::default(),
577             func_refs: FuncRefs::default(),
578             host_globals: PrimaryMap::new(),
579             instance_count: 0,
580             instance_limit: crate::DEFAULT_INSTANCE_LIMIT,
581             memory_count: 0,
582             memory_limit: crate::DEFAULT_MEMORY_LIMIT,
583             table_count: 0,
584             table_limit: crate::DEFAULT_TABLE_LIMIT,
585             #[cfg(feature = "async")]
586             async_state: Default::default(),
587             fuel_reserve: 0,
588             fuel_yield_interval: None,
589             store_data,
590             traitobj: StorePtr::empty(),
591             default_caller_vmctx: SendSyncPtr::new(NonNull::dangling()),
592             hostcall_val_storage: Vec::new(),
593             wasm_val_raw_storage: Vec::new(),
594             pkey,
595             #[cfg(feature = "component-model")]
596             component_host_table: Default::default(),
597             #[cfg(feature = "component-model")]
598             component_calls: Default::default(),
599             #[cfg(feature = "component-model")]
600             host_resource_data: Default::default(),
601             executor: Executor::new(engine),
602             #[cfg(feature = "component-model-async")]
603             concurrent_async_state: Default::default(),
604         };
605         let mut inner = Box::new(StoreInner {
606             inner,
607             limiter: None,
608             call_hook: None,
609             #[cfg(target_has_atomic = "64")]
610             epoch_deadline_behavior: None,
611             data: ManuallyDrop::new(data),
612         });
613 
614         inner.traitobj = StorePtr::new(NonNull::from(&mut *inner));
615 
616         // Wasmtime uses the callee argument to host functions to learn about
617         // the original pointer to the `Store` itself, allowing it to
618         // reconstruct a `StoreContextMut<T>`. When we initially call a `Func`,
619         // however, there's no "callee" to provide. To fix this we allocate a
620         // single "default callee" for the entire `Store`. This is then used as
621         // part of `Func::call` to guarantee that the `callee: *mut VMContext`
622         // is never null.
623         let module = Arc::new(wasmtime_environ::Module::default());
624         let shim = ModuleRuntimeInfo::bare(module);
625         let allocator = OnDemandInstanceAllocator::default();
626 
627         allocator
628             .validate_module(shim.env_module(), shim.offsets())
629             .unwrap();
630 
631         unsafe {
632             let id = inner
633                 .allocate_instance(
634                     AllocateInstanceKind::Dummy {
635                         allocator: &allocator,
636                     },
637                     &shim,
638                     Default::default(),
639                 )
640                 .expect("failed to allocate default callee");
641             let default_caller_vmctx = inner.instance(id).vmctx();
642             inner.default_caller_vmctx = default_caller_vmctx.into();
643         }
644 
645         Self {
646             inner: ManuallyDrop::new(inner),
647         }
648     }
649 
650     /// Access the underlying data owned by this `Store`.
651     #[inline]
652     pub fn data(&self) -> &T {
653         self.inner.data()
654     }
655 
656     /// Access the underlying data owned by this `Store`.
657     #[inline]
658     pub fn data_mut(&mut self) -> &mut T {
659         self.inner.data_mut()
660     }
661 
662     fn run_manual_drop_routines(&mut self) {
663         // We need to drop the fibers of each component instance before
664         // attempting to drop the instances themselves since the fibers may need
665         // to be resumed and allowed to exit cleanly before we yank the state
666         // out from under them.
667         //
668         // This will also drop any futures which might use a `&Accessor` fields
669         // in their `Drop::drop` implementations, in which case they'll need to
670         // be called from with in the context of a `tls::set` closure.
671         #[cfg(feature = "component-model-async")]
672         ComponentStoreData::drop_fibers_and_futures(&mut self.inner);
673 
674         // Ensure all fiber stacks, even cached ones, are all flushed out to the
675         // instance allocator.
676         self.inner.flush_fiber_stack();
677     }
678 
679     /// Consumes this [`Store`], destroying it, and returns the underlying data.
680     pub fn into_data(mut self) -> T {
681         self.run_manual_drop_routines();
682 
683         // This is an unsafe operation because we want to avoid having a runtime
684         // check or boolean for whether the data is actually contained within a
685         // `Store`. The data itself is stored as `ManuallyDrop` since we're
686         // manually managing the memory here, and there's also a `ManuallyDrop`
687         // around the `Box<StoreInner<T>>`. The way this works though is a bit
688         // tricky, so here's how things get dropped appropriately:
689         //
690         // * When a `Store<T>` is normally dropped, the custom destructor for
691         //   `Store<T>` will drop `T`, then the `self.inner` field. The
692         //   rustc-glue destructor runs for `Box<StoreInner<T>>` which drops
693         //   `StoreInner<T>`. This cleans up all internal fields and doesn't
694         //   touch `T` because it's wrapped in `ManuallyDrop`.
695         //
696         // * When calling this method we skip the top-level destructor for
697         //   `Store<T>` with `mem::forget`. This skips both the destructor for
698         //   `T` and the destructor for `StoreInner<T>`. We do, however, run the
699         //   destructor for `Box<StoreInner<T>>` which, like above, will skip
700         //   the destructor for `T` since it's `ManuallyDrop`.
701         //
702         // In both cases all the other fields of `StoreInner<T>` should all get
703         // dropped, and the manual management of destructors is basically
704         // between this method and `Drop for Store<T>`. Note that this also
705         // means that `Drop for StoreInner<T>` cannot access `self.data`, so
706         // there is a comment indicating this as well.
707         unsafe {
708             let mut inner = ManuallyDrop::take(&mut self.inner);
709             core::mem::forget(self);
710             ManuallyDrop::take(&mut inner.data)
711         }
712     }
713 
714     /// Configures the [`ResourceLimiter`] used to limit resource creation
715     /// within this [`Store`].
716     ///
717     /// Whenever resources such as linear memory, tables, or instances are
718     /// allocated the `limiter` specified here is invoked with the store's data
719     /// `T` and the returned [`ResourceLimiter`] is used to limit the operation
720     /// being allocated. The returned [`ResourceLimiter`] is intended to live
721     /// within the `T` itself, for example by storing a
722     /// [`StoreLimits`](crate::StoreLimits).
723     ///
724     /// Note that this limiter is only used to limit the creation/growth of
725     /// resources in the future, this does not retroactively attempt to apply
726     /// limits to the [`Store`].
727     ///
728     /// # Examples
729     ///
730     /// ```
731     /// use wasmtime::*;
732     ///
733     /// struct MyApplicationState {
734     ///     my_state: u32,
735     ///     limits: StoreLimits,
736     /// }
737     ///
738     /// let engine = Engine::default();
739     /// let my_state = MyApplicationState {
740     ///     my_state: 42,
741     ///     limits: StoreLimitsBuilder::new()
742     ///         .memory_size(1 << 20 /* 1 MB */)
743     ///         .instances(2)
744     ///         .build(),
745     /// };
746     /// let mut store = Store::new(&engine, my_state);
747     /// store.limiter(|state| &mut state.limits);
748     ///
749     /// // Creation of smaller memories is allowed
750     /// Memory::new(&mut store, MemoryType::new(1, None)).unwrap();
751     ///
752     /// // Creation of a larger memory, however, will exceed the 1MB limit we've
753     /// // configured
754     /// assert!(Memory::new(&mut store, MemoryType::new(1000, None)).is_err());
755     ///
756     /// // The number of instances in this store is limited to 2, so the third
757     /// // instance here should fail.
758     /// let module = Module::new(&engine, "(module)").unwrap();
759     /// assert!(Instance::new(&mut store, &module, &[]).is_ok());
760     /// assert!(Instance::new(&mut store, &module, &[]).is_ok());
761     /// assert!(Instance::new(&mut store, &module, &[]).is_err());
762     /// ```
763     ///
764     /// [`ResourceLimiter`]: crate::ResourceLimiter
765     pub fn limiter(
766         &mut self,
767         mut limiter: impl (FnMut(&mut T) -> &mut dyn crate::ResourceLimiter) + Send + Sync + 'static,
768     ) {
769         // Apply the limits on instances, tables, and memory given by the limiter:
770         let inner = &mut self.inner;
771         let (instance_limit, table_limit, memory_limit) = {
772             let l = limiter(&mut inner.data);
773             (l.instances(), l.tables(), l.memories())
774         };
775         let innermost = &mut inner.inner;
776         innermost.instance_limit = instance_limit;
777         innermost.table_limit = table_limit;
778         innermost.memory_limit = memory_limit;
779 
780         // Save the limiter accessor function:
781         inner.limiter = Some(ResourceLimiterInner::Sync(Box::new(limiter)));
782     }
783 
784     /// Configure a function that runs on calls and returns between WebAssembly
785     /// and host code.
786     ///
787     /// The function is passed a [`CallHook`] argument, which indicates which
788     /// state transition the VM is making.
789     ///
790     /// This function may return a [`Trap`]. If a trap is returned when an
791     /// import was called, it is immediately raised as-if the host import had
792     /// returned the trap. If a trap is returned after wasm returns to the host
793     /// then the wasm function's result is ignored and this trap is returned
794     /// instead.
795     ///
796     /// After this function returns a trap, it may be called for subsequent returns
797     /// to host or wasm code as the trap propagates to the root call.
798     #[cfg(feature = "call-hook")]
799     pub fn call_hook(
800         &mut self,
801         hook: impl FnMut(StoreContextMut<'_, T>, CallHook) -> Result<()> + Send + Sync + 'static,
802     ) {
803         self.inner.call_hook = Some(CallHookInner::Sync(Box::new(hook)));
804     }
805 
806     /// Returns the [`Engine`] that this store is associated with.
807     pub fn engine(&self) -> &Engine {
808         self.inner.engine()
809     }
810 
811     /// Perform garbage collection.
812     ///
813     /// Note that it is not required to actively call this function. GC will
814     /// automatically happen according to various internal heuristics. This is
815     /// provided if fine-grained control over the GC is desired.
816     ///
817     /// If you are calling this method after an attempted allocation failed, you
818     /// may pass in the [`GcHeapOutOfMemory`][crate::GcHeapOutOfMemory] error.
819     /// When you do so, this method will attempt to create enough space in the
820     /// GC heap for that allocation, so that it will succeed on the next
821     /// attempt.
822     ///
823     /// This method is only available when the `gc` Cargo feature is enabled.
824     #[cfg(feature = "gc")]
825     pub fn gc(&mut self, why: Option<&crate::GcHeapOutOfMemory<()>>) {
826         assert!(!self.inner.async_support());
827         self.inner.gc(why);
828     }
829 
830     /// Returns the amount fuel in this [`Store`]. When fuel is enabled, it must
831     /// be configured via [`Store::set_fuel`].
832     ///
833     /// # Errors
834     ///
835     /// This function will return an error if fuel consumption is not enabled
836     /// via [`Config::consume_fuel`](crate::Config::consume_fuel).
837     pub fn get_fuel(&self) -> Result<u64> {
838         self.inner.get_fuel()
839     }
840 
841     /// Set the fuel to this [`Store`] for wasm to consume while executing.
842     ///
843     /// For this method to work fuel consumption must be enabled via
844     /// [`Config::consume_fuel`](crate::Config::consume_fuel). By default a
845     /// [`Store`] starts with 0 fuel for wasm to execute with (meaning it will
846     /// immediately trap). This function must be called for the store to have
847     /// some fuel to allow WebAssembly to execute.
848     ///
849     /// Most WebAssembly instructions consume 1 unit of fuel. Some
850     /// instructions, such as `nop`, `drop`, `block`, and `loop`, consume 0
851     /// units, as any execution cost associated with them involves other
852     /// instructions which do consume fuel.
853     ///
854     /// Note that when fuel is entirely consumed it will cause wasm to trap.
855     ///
856     /// # Errors
857     ///
858     /// This function will return an error if fuel consumption is not enabled via
859     /// [`Config::consume_fuel`](crate::Config::consume_fuel).
860     pub fn set_fuel(&mut self, fuel: u64) -> Result<()> {
861         self.inner.set_fuel(fuel)
862     }
863 
864     /// Configures a [`Store`] to yield execution of async WebAssembly code
865     /// periodically.
866     ///
867     /// When a [`Store`] is configured to consume fuel with
868     /// [`Config::consume_fuel`](crate::Config::consume_fuel) this method will
869     /// configure WebAssembly to be suspended and control will be yielded back to the
870     /// caller every `interval` units of fuel consumed. This is only suitable with use of
871     /// a store associated with an [async config](crate::Config::async_support) because
872     /// only then are futures used and yields are possible.
873     ///
874     /// The purpose of this behavior is to ensure that futures which represent
875     /// execution of WebAssembly do not execute too long inside their
876     /// `Future::poll` method. This allows for some form of cooperative
877     /// multitasking where WebAssembly will voluntarily yield control
878     /// periodically (based on fuel consumption) back to the running thread.
879     ///
880     /// Note that futures returned by this crate will automatically flag
881     /// themselves to get re-polled if a yield happens. This means that
882     /// WebAssembly will continue to execute, just after giving the host an
883     /// opportunity to do something else.
884     ///
885     /// The `interval` parameter indicates how much fuel should be
886     /// consumed between yields of an async future. When fuel runs out wasm will trap.
887     ///
888     /// # Error
889     ///
890     /// This method will error if it is not called on a store associated with an [async
891     /// config](crate::Config::async_support).
892     pub fn fuel_async_yield_interval(&mut self, interval: Option<u64>) -> Result<()> {
893         self.inner.fuel_async_yield_interval(interval)
894     }
895 
896     /// Sets the epoch deadline to a certain number of ticks in the future.
897     ///
898     /// When the Wasm guest code is compiled with epoch-interruption
899     /// instrumentation
900     /// ([`Config::epoch_interruption()`](crate::Config::epoch_interruption)),
901     /// and when the `Engine`'s epoch is incremented
902     /// ([`Engine::increment_epoch()`](crate::Engine::increment_epoch))
903     /// past a deadline, execution can be configured to either trap or
904     /// yield and then continue.
905     ///
906     /// This deadline is always set relative to the current epoch:
907     /// `ticks_beyond_current` ticks in the future. The deadline can
908     /// be set explicitly via this method, or refilled automatically
909     /// on a yield if configured via
910     /// [`epoch_deadline_async_yield_and_update()`](Store::epoch_deadline_async_yield_and_update). After
911     /// this method is invoked, the deadline is reached when
912     /// [`Engine::increment_epoch()`] has been invoked at least
913     /// `ticks_beyond_current` times.
914     ///
915     /// By default a store will trap immediately with an epoch deadline of 0
916     /// (which has always "elapsed"). This method is required to be configured
917     /// for stores with epochs enabled to some future epoch deadline.
918     ///
919     /// See documentation on
920     /// [`Config::epoch_interruption()`](crate::Config::epoch_interruption)
921     /// for an introduction to epoch-based interruption.
922     #[cfg(target_has_atomic = "64")]
923     pub fn set_epoch_deadline(&mut self, ticks_beyond_current: u64) {
924         self.inner.set_epoch_deadline(ticks_beyond_current);
925     }
926 
927     /// Configures epoch-deadline expiration to trap.
928     ///
929     /// When epoch-interruption-instrumented code is executed on this
930     /// store and the epoch deadline is reached before completion,
931     /// with the store configured in this way, execution will
932     /// terminate with a trap as soon as an epoch check in the
933     /// instrumented code is reached.
934     ///
935     /// This behavior is the default if the store is not otherwise
936     /// configured via
937     /// [`epoch_deadline_trap()`](Store::epoch_deadline_trap),
938     /// [`epoch_deadline_callback()`](Store::epoch_deadline_callback) or
939     /// [`epoch_deadline_async_yield_and_update()`](Store::epoch_deadline_async_yield_and_update).
940     ///
941     /// This setting is intended to allow for coarse-grained
942     /// interruption, but not a deterministic deadline of a fixed,
943     /// finite interval. For deterministic interruption, see the
944     /// "fuel" mechanism instead.
945     ///
946     /// Note that when this is used it's required to call
947     /// [`Store::set_epoch_deadline`] or otherwise wasm will always immediately
948     /// trap.
949     ///
950     /// See documentation on
951     /// [`Config::epoch_interruption()`](crate::Config::epoch_interruption)
952     /// for an introduction to epoch-based interruption.
953     #[cfg(target_has_atomic = "64")]
954     pub fn epoch_deadline_trap(&mut self) {
955         self.inner.epoch_deadline_trap();
956     }
957 
958     /// Configures epoch-deadline expiration to invoke a custom callback
959     /// function.
960     ///
961     /// When epoch-interruption-instrumented code is executed on this
962     /// store and the epoch deadline is reached before completion, the
963     /// provided callback function is invoked.
964     ///
965     /// This callback should either return an [`UpdateDeadline`], or
966     /// return an error, which will terminate execution with a trap.
967     ///
968     /// The [`UpdateDeadline`] is a positive number of ticks to
969     /// add to the epoch deadline, as well as indicating what
970     /// to do after the callback returns. If the [`Store`] is
971     /// configured with async support, then the callback may return
972     /// [`UpdateDeadline::Yield`] or [`UpdateDeadline::YieldCustom`]
973     /// to yield to the async executor before updating the epoch deadline.
974     /// Alternatively, the callback may return [`UpdateDeadline::Continue`] to
975     /// update the epoch deadline immediately.
976     ///
977     /// This setting is intended to allow for coarse-grained
978     /// interruption, but not a deterministic deadline of a fixed,
979     /// finite interval. For deterministic interruption, see the
980     /// "fuel" mechanism instead.
981     ///
982     /// See documentation on
983     /// [`Config::epoch_interruption()`](crate::Config::epoch_interruption)
984     /// for an introduction to epoch-based interruption.
985     #[cfg(target_has_atomic = "64")]
986     pub fn epoch_deadline_callback(
987         &mut self,
988         callback: impl FnMut(StoreContextMut<T>) -> Result<UpdateDeadline> + Send + Sync + 'static,
989     ) {
990         self.inner.epoch_deadline_callback(Box::new(callback));
991     }
992 }
993 
994 impl<'a, T> StoreContext<'a, T> {
995     pub(crate) fn async_support(&self) -> bool {
996         self.0.async_support()
997     }
998 
999     /// Returns the underlying [`Engine`] this store is connected to.
1000     pub fn engine(&self) -> &Engine {
1001         self.0.engine()
1002     }
1003 
1004     /// Access the underlying data owned by this `Store`.
1005     ///
1006     /// Same as [`Store::data`].
1007     pub fn data(&self) -> &'a T {
1008         self.0.data()
1009     }
1010 
1011     /// Returns the remaining fuel in this store.
1012     ///
1013     /// For more information see [`Store::get_fuel`].
1014     pub fn get_fuel(&self) -> Result<u64> {
1015         self.0.get_fuel()
1016     }
1017 }
1018 
1019 impl<'a, T> StoreContextMut<'a, T> {
1020     /// Access the underlying data owned by this `Store`.
1021     ///
1022     /// Same as [`Store::data`].
1023     pub fn data(&self) -> &T {
1024         self.0.data()
1025     }
1026 
1027     /// Access the underlying data owned by this `Store`.
1028     ///
1029     /// Same as [`Store::data_mut`].
1030     pub fn data_mut(&mut self) -> &mut T {
1031         self.0.data_mut()
1032     }
1033 
1034     /// Returns the underlying [`Engine`] this store is connected to.
1035     pub fn engine(&self) -> &Engine {
1036         self.0.engine()
1037     }
1038 
1039     /// Perform garbage collection of `ExternRef`s.
1040     ///
1041     /// Same as [`Store::gc`].
1042     ///
1043     /// This method is only available when the `gc` Cargo feature is enabled.
1044     #[cfg(feature = "gc")]
1045     pub fn gc(&mut self, why: Option<&crate::GcHeapOutOfMemory<()>>) {
1046         self.0.gc(why);
1047     }
1048 
1049     /// Returns remaining fuel in this store.
1050     ///
1051     /// For more information see [`Store::get_fuel`]
1052     pub fn get_fuel(&self) -> Result<u64> {
1053         self.0.get_fuel()
1054     }
1055 
1056     /// Set the amount of fuel in this store.
1057     ///
1058     /// For more information see [`Store::set_fuel`]
1059     pub fn set_fuel(&mut self, fuel: u64) -> Result<()> {
1060         self.0.set_fuel(fuel)
1061     }
1062 
1063     /// Configures this `Store` to periodically yield while executing futures.
1064     ///
1065     /// For more information see [`Store::fuel_async_yield_interval`]
1066     pub fn fuel_async_yield_interval(&mut self, interval: Option<u64>) -> Result<()> {
1067         self.0.fuel_async_yield_interval(interval)
1068     }
1069 
1070     /// Sets the epoch deadline to a certain number of ticks in the future.
1071     ///
1072     /// For more information see [`Store::set_epoch_deadline`].
1073     #[cfg(target_has_atomic = "64")]
1074     pub fn set_epoch_deadline(&mut self, ticks_beyond_current: u64) {
1075         self.0.set_epoch_deadline(ticks_beyond_current);
1076     }
1077 
1078     /// Configures epoch-deadline expiration to trap.
1079     ///
1080     /// For more information see [`Store::epoch_deadline_trap`].
1081     #[cfg(target_has_atomic = "64")]
1082     pub fn epoch_deadline_trap(&mut self) {
1083         self.0.epoch_deadline_trap();
1084     }
1085 }
1086 
1087 impl<T> StoreInner<T> {
1088     #[inline]
1089     fn data(&self) -> &T {
1090         &self.data
1091     }
1092 
1093     #[inline]
1094     fn data_mut(&mut self) -> &mut T {
1095         &mut self.data
1096     }
1097 
1098     #[inline]
1099     pub fn call_hook(&mut self, s: CallHook) -> Result<()> {
1100         if self.inner.pkey.is_none() && self.call_hook.is_none() {
1101             Ok(())
1102         } else {
1103             self.call_hook_slow_path(s)
1104         }
1105     }
1106 
1107     fn call_hook_slow_path(&mut self, s: CallHook) -> Result<()> {
1108         if let Some(pkey) = &self.inner.pkey {
1109             let allocator = self.engine().allocator();
1110             match s {
1111                 CallHook::CallingWasm | CallHook::ReturningFromHost => {
1112                     allocator.restrict_to_pkey(*pkey)
1113                 }
1114                 CallHook::ReturningFromWasm | CallHook::CallingHost => allocator.allow_all_pkeys(),
1115             }
1116         }
1117 
1118         // Temporarily take the configured behavior to avoid mutably borrowing
1119         // multiple times.
1120         if let Some(mut call_hook) = self.call_hook.take() {
1121             let result = self.invoke_call_hook(&mut call_hook, s);
1122             self.call_hook = Some(call_hook);
1123             return result;
1124         }
1125 
1126         Ok(())
1127     }
1128 
1129     fn invoke_call_hook(&mut self, call_hook: &mut CallHookInner<T>, s: CallHook) -> Result<()> {
1130         match call_hook {
1131             #[cfg(feature = "call-hook")]
1132             CallHookInner::Sync(hook) => hook((&mut *self).as_context_mut(), s),
1133 
1134             #[cfg(all(feature = "async", feature = "call-hook"))]
1135             CallHookInner::Async(handler) => {
1136                 if !self.can_block() {
1137                     bail!("couldn't grab async_cx for call hook")
1138                 }
1139                 return (&mut *self)
1140                     .as_context_mut()
1141                     .with_blocking(|store, cx| cx.block_on(handler.handle_call_event(store, s)))?;
1142             }
1143 
1144             CallHookInner::ForceTypeParameterToBeUsed { uninhabited, .. } => {
1145                 let _ = s;
1146                 match *uninhabited {}
1147             }
1148         }
1149     }
1150 
1151     #[cfg(not(feature = "async"))]
1152     fn flush_fiber_stack(&mut self) {
1153         // noop shim so code can assume this always exists.
1154     }
1155 }
1156 
1157 fn get_fuel(injected_fuel: i64, fuel_reserve: u64) -> u64 {
1158     fuel_reserve.saturating_add_signed(-injected_fuel)
1159 }
1160 
1161 // Add remaining fuel from the reserve into the active fuel if there is any left.
1162 fn refuel(
1163     injected_fuel: &mut i64,
1164     fuel_reserve: &mut u64,
1165     yield_interval: Option<NonZeroU64>,
1166 ) -> bool {
1167     let fuel = get_fuel(*injected_fuel, *fuel_reserve);
1168     if fuel > 0 {
1169         set_fuel(injected_fuel, fuel_reserve, yield_interval, fuel);
1170         true
1171     } else {
1172         false
1173     }
1174 }
1175 
1176 fn set_fuel(
1177     injected_fuel: &mut i64,
1178     fuel_reserve: &mut u64,
1179     yield_interval: Option<NonZeroU64>,
1180     new_fuel_amount: u64,
1181 ) {
1182     let interval = yield_interval.unwrap_or(NonZeroU64::MAX).get();
1183     // If we're yielding periodically we only store the "active" amount of fuel into consumed_ptr
1184     // for the VM to use.
1185     let injected = core::cmp::min(interval, new_fuel_amount);
1186     // Fuel in the VM is stored as an i64, so we have to cap the amount of fuel we inject into the
1187     // VM at once to be i64 range.
1188     let injected = core::cmp::min(injected, i64::MAX as u64);
1189     // Add whatever is left over after injection to the reserve for later use.
1190     *fuel_reserve = new_fuel_amount - injected;
1191     // Within the VM we increment to count fuel, so inject a negative amount. The VM will halt when
1192     // this counter is positive.
1193     *injected_fuel = -(injected as i64);
1194 }
1195 
1196 #[doc(hidden)]
1197 impl StoreOpaque {
1198     pub fn id(&self) -> StoreId {
1199         self.store_data.id()
1200     }
1201 
1202     pub fn bump_resource_counts(&mut self, module: &Module) -> Result<()> {
1203         fn bump(slot: &mut usize, max: usize, amt: usize, desc: &str) -> Result<()> {
1204             let new = slot.saturating_add(amt);
1205             if new > max {
1206                 bail!(
1207                     "resource limit exceeded: {} count too high at {}",
1208                     desc,
1209                     new
1210                 );
1211             }
1212             *slot = new;
1213             Ok(())
1214         }
1215 
1216         let module = module.env_module();
1217         let memories = module.num_defined_memories();
1218         let tables = module.num_defined_tables();
1219 
1220         bump(&mut self.instance_count, self.instance_limit, 1, "instance")?;
1221         bump(
1222             &mut self.memory_count,
1223             self.memory_limit,
1224             memories,
1225             "memory",
1226         )?;
1227         bump(&mut self.table_count, self.table_limit, tables, "table")?;
1228 
1229         Ok(())
1230     }
1231 
1232     #[inline]
1233     pub fn async_support(&self) -> bool {
1234         cfg!(feature = "async") && self.engine().config().async_support
1235     }
1236 
1237     #[inline]
1238     pub fn engine(&self) -> &Engine {
1239         &self.engine
1240     }
1241 
1242     #[inline]
1243     pub fn store_data(&self) -> &StoreData {
1244         &self.store_data
1245     }
1246 
1247     #[inline]
1248     pub fn store_data_mut(&mut self) -> &mut StoreData {
1249         &mut self.store_data
1250     }
1251 
1252     #[inline]
1253     pub(crate) fn modules(&self) -> &ModuleRegistry {
1254         &self.modules
1255     }
1256 
1257     #[inline]
1258     pub(crate) fn modules_mut(&mut self) -> &mut ModuleRegistry {
1259         &mut self.modules
1260     }
1261 
1262     pub(crate) fn func_refs_and_modules(&mut self) -> (&mut FuncRefs, &ModuleRegistry) {
1263         (&mut self.func_refs, &self.modules)
1264     }
1265 
1266     pub(crate) fn host_globals(
1267         &self,
1268     ) -> &PrimaryMap<DefinedGlobalIndex, StoreBox<VMHostGlobalContext>> {
1269         &self.host_globals
1270     }
1271 
1272     pub(crate) fn host_globals_mut(
1273         &mut self,
1274     ) -> &mut PrimaryMap<DefinedGlobalIndex, StoreBox<VMHostGlobalContext>> {
1275         &mut self.host_globals
1276     }
1277 
1278     pub fn module_for_instance(&self, instance: StoreInstanceId) -> Option<&'_ Module> {
1279         instance.store_id().assert_belongs_to(self.id());
1280         match self.instances[instance.instance()].kind {
1281             StoreInstanceKind::Dummy => None,
1282             StoreInstanceKind::Real { module_id } => {
1283                 let module = self
1284                     .modules()
1285                     .lookup_module_by_id(module_id)
1286                     .expect("should always have a registered module for real instances");
1287                 Some(module)
1288             }
1289         }
1290     }
1291 
1292     /// Accessor from `InstanceId` to `&vm::Instance`.
1293     ///
1294     /// Note that if you have a `StoreInstanceId` you should use
1295     /// `StoreInstanceId::get` instead. This assumes that `id` has been
1296     /// validated to already belong to this store.
1297     #[inline]
1298     pub fn instance(&self, id: InstanceId) -> &vm::Instance {
1299         self.instances[id].handle.get()
1300     }
1301 
1302     /// Accessor from `InstanceId` to `Pin<&mut vm::Instance>`.
1303     ///
1304     /// Note that if you have a `StoreInstanceId` you should use
1305     /// `StoreInstanceId::get_mut` instead. This assumes that `id` has been
1306     /// validated to already belong to this store.
1307     #[inline]
1308     pub fn instance_mut(&mut self, id: InstanceId) -> Pin<&mut vm::Instance> {
1309         self.instances[id].handle.get_mut()
1310     }
1311 
1312     /// Access multiple instances specified via `ids`.
1313     ///
1314     /// # Panics
1315     ///
1316     /// This method will panic if any indices in `ids` overlap.
1317     ///
1318     /// # Safety
1319     ///
1320     /// This method is not safe if the returned instances are used to traverse
1321     /// "laterally" between other instances. For example accessing imported
1322     /// items in an instance may traverse laterally to a sibling instance thus
1323     /// aliasing a returned value here. The caller must ensure that only defined
1324     /// items within the instances themselves are accessed.
1325     #[inline]
1326     pub unsafe fn optional_gc_store_and_instances_mut<const N: usize>(
1327         &mut self,
1328         ids: [InstanceId; N],
1329     ) -> (Option<&mut GcStore>, [Pin<&mut vm::Instance>; N]) {
1330         let instances = self
1331             .instances
1332             .get_disjoint_mut(ids)
1333             .unwrap()
1334             .map(|h| h.handle.get_mut());
1335         (self.gc_store.as_mut(), instances)
1336     }
1337 
1338     /// Pair of `Self::optional_gc_store_mut` and `Self::instance_mut`
1339     pub fn optional_gc_store_and_instance_mut(
1340         &mut self,
1341         id: InstanceId,
1342     ) -> (Option<&mut GcStore>, Pin<&mut vm::Instance>) {
1343         (self.gc_store.as_mut(), self.instances[id].handle.get_mut())
1344     }
1345 
1346     /// Get all instances (ignoring dummy instances) within this store.
1347     pub fn all_instances<'a>(&'a mut self) -> impl ExactSizeIterator<Item = Instance> + 'a {
1348         let instances = self
1349             .instances
1350             .iter()
1351             .filter_map(|(id, inst)| {
1352                 if let StoreInstanceKind::Dummy = inst.kind {
1353                     None
1354                 } else {
1355                     Some(id)
1356                 }
1357             })
1358             .collect::<Vec<_>>();
1359         instances
1360             .into_iter()
1361             .map(|i| Instance::from_wasmtime(i, self))
1362     }
1363 
1364     /// Get all memories (host- or Wasm-defined) within this store.
1365     pub fn all_memories<'a>(&'a self) -> impl Iterator<Item = Memory> + 'a {
1366         // NB: Host-created memories have dummy instances. Therefore, we can get
1367         // all memories in the store by iterating over all instances (including
1368         // dummy instances) and getting each of their defined memories.
1369         let id = self.id();
1370         self.instances
1371             .iter()
1372             .flat_map(move |(_, instance)| instance.handle.get().defined_memories(id))
1373     }
1374 
1375     /// Iterate over all tables (host- or Wasm-defined) within this store.
1376     pub fn for_each_table(&mut self, mut f: impl FnMut(&mut Self, Table)) {
1377         // NB: Host-created tables have dummy instances. Therefore, we can get
1378         // all tables in the store by iterating over all instances (including
1379         // dummy instances) and getting each of their defined memories.
1380         for id in self.instances.keys() {
1381             let instance = StoreInstanceId::new(self.id(), id);
1382             for table in 0..self.instance(id).env_module().num_defined_tables() {
1383                 let table = DefinedTableIndex::new(table);
1384                 f(self, Table::from_raw(instance, table));
1385             }
1386         }
1387     }
1388 
1389     /// Iterate over all globals (host- or Wasm-defined) within this store.
1390     pub fn for_each_global(&mut self, mut f: impl FnMut(&mut Self, Global)) {
1391         // First enumerate all the host-created globals.
1392         for global in self.host_globals.keys() {
1393             let global = Global::new_host(self, global);
1394             f(self, global);
1395         }
1396 
1397         // Then enumerate all instances' defined globals.
1398         for id in self.instances.keys() {
1399             for index in 0..self.instance(id).env_module().num_defined_globals() {
1400                 let index = DefinedGlobalIndex::new(index);
1401                 let global = Global::new_instance(self, id, index);
1402                 f(self, global);
1403             }
1404         }
1405     }
1406 
1407     #[cfg(all(feature = "std", any(unix, windows)))]
1408     pub fn set_signal_handler(&mut self, handler: Option<SignalHandler>) {
1409         self.signal_handler = handler;
1410     }
1411 
1412     #[inline]
1413     pub fn vm_store_context(&self) -> &VMStoreContext {
1414         &self.vm_store_context
1415     }
1416 
1417     #[inline]
1418     pub fn vm_store_context_mut(&mut self) -> &mut VMStoreContext {
1419         &mut self.vm_store_context
1420     }
1421 
1422     /// Performs a lazy allocation of the `GcStore` within this store, returning
1423     /// the previous allocation if it's already present.
1424     ///
1425     /// This method will, if necessary, allocate a new `GcStore` -- linear
1426     /// memory and all. This is a blocking operation due to
1427     /// `ResourceLimiterAsync` which means that this should only be executed
1428     /// in a fiber context at this time.
1429     #[inline]
1430     pub(crate) fn ensure_gc_store(&mut self) -> Result<&mut GcStore> {
1431         if self.gc_store.is_some() {
1432             return Ok(self.gc_store.as_mut().unwrap());
1433         }
1434         self.allocate_gc_store()
1435     }
1436 
1437     #[inline(never)]
1438     fn allocate_gc_store(&mut self) -> Result<&mut GcStore> {
1439         log::trace!("allocating GC heap for store {:?}", self.id());
1440 
1441         assert!(self.gc_store.is_none());
1442         assert_eq!(
1443             self.vm_store_context.gc_heap.base.as_non_null(),
1444             NonNull::dangling(),
1445         );
1446         assert_eq!(self.vm_store_context.gc_heap.current_length(), 0);
1447 
1448         let vmstore = self.traitobj();
1449         let gc_store = allocate_gc_store(self.engine(), vmstore, self.get_pkey())?;
1450         self.vm_store_context.gc_heap = gc_store.vmmemory_definition();
1451         return Ok(self.gc_store.insert(gc_store));
1452 
1453         #[cfg(feature = "gc")]
1454         fn allocate_gc_store(
1455             engine: &Engine,
1456             vmstore: NonNull<dyn vm::VMStore>,
1457             pkey: Option<ProtectionKey>,
1458         ) -> Result<GcStore> {
1459             use wasmtime_environ::packed_option::ReservedValue;
1460 
1461             ensure!(
1462                 engine.features().gc_types(),
1463                 "cannot allocate a GC store when GC is disabled at configuration time"
1464             );
1465 
1466             // First, allocate the memory that will be our GC heap's storage.
1467             let mut request = InstanceAllocationRequest {
1468                 id: InstanceId::reserved_value(),
1469                 runtime_info: &ModuleRuntimeInfo::bare(Arc::new(
1470                     wasmtime_environ::Module::default(),
1471                 )),
1472                 imports: vm::Imports::default(),
1473                 store: StorePtr::new(vmstore),
1474                 #[cfg(feature = "wmemcheck")]
1475                 wmemcheck: false,
1476                 pkey,
1477                 tunables: engine.tunables(),
1478             };
1479             let mem_ty = engine.tunables().gc_heap_memory_type();
1480             let tunables = engine.tunables();
1481 
1482             let (mem_alloc_index, mem) =
1483                 engine
1484                     .allocator()
1485                     .allocate_memory(&mut request, &mem_ty, tunables, None)?;
1486 
1487             // Then, allocate the actual GC heap, passing in that memory
1488             // storage.
1489             let gc_runtime = engine
1490                 .gc_runtime()
1491                 .context("no GC runtime: GC disabled at compile time or configuration time")?;
1492             let (index, heap) =
1493                 engine
1494                     .allocator()
1495                     .allocate_gc_heap(engine, &**gc_runtime, mem_alloc_index, mem)?;
1496 
1497             Ok(GcStore::new(index, heap))
1498         }
1499 
1500         #[cfg(not(feature = "gc"))]
1501         fn allocate_gc_store(
1502             _engine: &Engine,
1503             _vmstore: NonNull<dyn vm::VMStore>,
1504             _pkey: Option<ProtectionKey>,
1505         ) -> Result<GcStore> {
1506             bail!("cannot allocate a GC store: the `gc` feature was disabled at compile time")
1507         }
1508     }
1509 
1510     /// Helper method to require that a `GcStore` was previously allocated for
1511     /// this store, failing if it has not yet been allocated.
1512     ///
1513     /// Note that this should only be used in a context where allocation of a
1514     /// `GcStore` is sure to have already happened prior, otherwise this may
1515     /// return a confusing error to embedders which is a bug in Wasmtime.
1516     ///
1517     /// Some situations where it's safe to call this method:
1518     ///
1519     /// * There's already a non-null and non-i31 `VMGcRef` in scope. By existing
1520     ///   this shows proof that the `GcStore` was previously allocated.
1521     /// * During instantiation and instance's `needs_gc_heap` flag will be
1522     ///   handled and instantiation will automatically create a GC store.
1523     #[inline]
1524     #[cfg(feature = "gc")]
1525     pub(crate) fn require_gc_store(&self) -> Result<&GcStore> {
1526         match &self.gc_store {
1527             Some(gc_store) => Ok(gc_store),
1528             None => bail!("GC heap not initialized yet"),
1529         }
1530     }
1531 
1532     /// Same as [`Self::require_gc_store`], but mutable.
1533     #[inline]
1534     #[cfg(feature = "gc")]
1535     pub(crate) fn require_gc_store_mut(&mut self) -> Result<&mut GcStore> {
1536         match &mut self.gc_store {
1537             Some(gc_store) => Ok(gc_store),
1538             None => bail!("GC heap not initialized yet"),
1539         }
1540     }
1541 
1542     /// Attempts to access the GC store that has been previously allocated.
1543     ///
1544     /// This method will return `Some` if the GC store was previously allocated.
1545     /// A `None` return value means either that the GC heap hasn't yet been
1546     /// allocated or that it does not need to be allocated for this store. Note
1547     /// that to require a GC store in a particular situation it's recommended to
1548     /// use [`Self::require_gc_store_mut`] instead.
1549     #[inline]
1550     pub(crate) fn optional_gc_store_mut(&mut self) -> Option<&mut GcStore> {
1551         if cfg!(not(feature = "gc")) || !self.engine.features().gc_types() {
1552             debug_assert!(self.gc_store.is_none());
1553             None
1554         } else {
1555             self.gc_store.as_mut()
1556         }
1557     }
1558 
1559     /// Helper to assert that a GC store was previously allocated and is
1560     /// present.
1561     ///
1562     /// # Panics
1563     ///
1564     /// This method will panic if the GC store has not yet been allocated. This
1565     /// should only be used in a context where there's an existing GC reference,
1566     /// for example, or if `ensure_gc_store` has already been called.
1567     #[inline]
1568     #[track_caller]
1569     pub(crate) fn unwrap_gc_store(&self) -> &GcStore {
1570         self.gc_store
1571             .as_ref()
1572             .expect("attempted to access the store's GC heap before it has been allocated")
1573     }
1574 
1575     /// Same as [`Self::unwrap_gc_store`], but mutable.
1576     #[inline]
1577     #[track_caller]
1578     pub(crate) fn unwrap_gc_store_mut(&mut self) -> &mut GcStore {
1579         self.gc_store
1580             .as_mut()
1581             .expect("attempted to access the store's GC heap before it has been allocated")
1582     }
1583 
1584     #[inline]
1585     pub(crate) fn gc_roots(&self) -> &RootSet {
1586         &self.gc_roots
1587     }
1588 
1589     #[inline]
1590     #[cfg(feature = "gc")]
1591     pub(crate) fn gc_roots_mut(&mut self) -> &mut RootSet {
1592         &mut self.gc_roots
1593     }
1594 
1595     #[inline]
1596     pub(crate) fn exit_gc_lifo_scope(&mut self, scope: usize) {
1597         self.gc_roots.exit_lifo_scope(self.gc_store.as_mut(), scope);
1598     }
1599 
1600     #[cfg(feature = "gc")]
1601     fn do_gc(&mut self) {
1602         assert!(
1603             !self.async_support(),
1604             "must use `store.gc_async()` instead of `store.gc()` for async stores"
1605         );
1606 
1607         // If the GC heap hasn't been initialized, there is nothing to collect.
1608         if self.gc_store.is_none() {
1609             return;
1610         }
1611 
1612         log::trace!("============ Begin GC ===========");
1613 
1614         // Take the GC roots out of `self` so we can borrow it mutably but still
1615         // call mutable methods on `self`.
1616         let mut roots = core::mem::take(&mut self.gc_roots_list);
1617 
1618         self.trace_roots(&mut roots);
1619         self.unwrap_gc_store_mut().gc(unsafe { roots.iter() });
1620 
1621         // Restore the GC roots for the next GC.
1622         roots.clear();
1623         self.gc_roots_list = roots;
1624 
1625         log::trace!("============ End GC ===========");
1626     }
1627 
1628     #[cfg(feature = "gc")]
1629     fn trace_roots(&mut self, gc_roots_list: &mut GcRootsList) {
1630         log::trace!("Begin trace GC roots");
1631 
1632         // We shouldn't have any leftover, stale GC roots.
1633         assert!(gc_roots_list.is_empty());
1634 
1635         self.trace_wasm_stack_roots(gc_roots_list);
1636         #[cfg(feature = "stack-switching")]
1637         self.trace_wasm_continuation_roots(gc_roots_list);
1638         self.trace_vmctx_roots(gc_roots_list);
1639         self.trace_user_roots(gc_roots_list);
1640 
1641         log::trace!("End trace GC roots")
1642     }
1643 
1644     #[cfg(feature = "gc")]
1645     fn trace_wasm_stack_frame(
1646         &self,
1647         gc_roots_list: &mut GcRootsList,
1648         frame: crate::runtime::vm::Frame,
1649     ) {
1650         use crate::runtime::vm::SendSyncPtr;
1651         use core::ptr::NonNull;
1652 
1653         let pc = frame.pc();
1654         debug_assert!(pc != 0, "we should always get a valid PC for Wasm frames");
1655 
1656         let fp = frame.fp() as *mut usize;
1657         debug_assert!(
1658             !fp.is_null(),
1659             "we should always get a valid frame pointer for Wasm frames"
1660         );
1661 
1662         let module_info = self
1663             .modules()
1664             .lookup_module_by_pc(pc)
1665             .expect("should have module info for Wasm frame");
1666 
1667         let stack_map = match module_info.lookup_stack_map(pc) {
1668             Some(sm) => sm,
1669             None => {
1670                 log::trace!("No stack map for this Wasm frame");
1671                 return;
1672             }
1673         };
1674         log::trace!(
1675             "We have a stack map that maps {} bytes in this Wasm frame",
1676             stack_map.frame_size()
1677         );
1678 
1679         let sp = unsafe { stack_map.sp(fp) };
1680         for stack_slot in unsafe { stack_map.live_gc_refs(sp) } {
1681             let raw: u32 = unsafe { core::ptr::read(stack_slot) };
1682             log::trace!("Stack slot @ {stack_slot:p} = {raw:#x}");
1683 
1684             let gc_ref = vm::VMGcRef::from_raw_u32(raw);
1685             if gc_ref.is_some() {
1686                 unsafe {
1687                     gc_roots_list
1688                         .add_wasm_stack_root(SendSyncPtr::new(NonNull::new(stack_slot).unwrap()));
1689                 }
1690             }
1691         }
1692     }
1693 
1694     #[cfg(feature = "gc")]
1695     fn trace_wasm_stack_roots(&mut self, gc_roots_list: &mut GcRootsList) {
1696         use crate::runtime::vm::Backtrace;
1697         log::trace!("Begin trace GC roots :: Wasm stack");
1698 
1699         Backtrace::trace(self, |frame| {
1700             self.trace_wasm_stack_frame(gc_roots_list, frame);
1701             core::ops::ControlFlow::Continue(())
1702         });
1703 
1704         log::trace!("End trace GC roots :: Wasm stack");
1705     }
1706 
1707     #[cfg(all(feature = "gc", feature = "stack-switching"))]
1708     fn trace_wasm_continuation_roots(&mut self, gc_roots_list: &mut GcRootsList) {
1709         use crate::{runtime::vm::Backtrace, vm::VMStackState};
1710         log::trace!("Begin trace GC roots :: continuations");
1711 
1712         for continuation in &self.continuations {
1713             let state = continuation.common_stack_information.state;
1714 
1715             // FIXME(frank-emrich) In general, it is not enough to just trace
1716             // through the stacks of continuations; we also need to look through
1717             // their `cont.bind` arguments. However, we don't currently have
1718             // enough RTTI information to check if any of the values in the
1719             // buffers used by `cont.bind` are GC values. As a workaround, note
1720             // that we currently disallow cont.bind-ing GC values altogether.
1721             // This way, it is okay not to check them here.
1722             match state {
1723                 VMStackState::Suspended => {
1724                     Backtrace::trace_suspended_continuation(self, continuation.deref(), |frame| {
1725                         self.trace_wasm_stack_frame(gc_roots_list, frame);
1726                         core::ops::ControlFlow::Continue(())
1727                     });
1728                 }
1729                 VMStackState::Running => {
1730                     // Handled by `trace_wasm_stack_roots`.
1731                 }
1732                 VMStackState::Parent => {
1733                     // We don't know whether our child is suspended or running, but in
1734                     // either case things should be hanlded correctly when traversing
1735                     // further along in the chain, nothing required at this point.
1736                 }
1737                 VMStackState::Fresh | VMStackState::Returned => {
1738                     // Fresh/Returned continuations have no gc values on their stack.
1739                 }
1740             }
1741         }
1742 
1743         log::trace!("End trace GC roots :: continuations");
1744     }
1745 
1746     #[cfg(feature = "gc")]
1747     fn trace_vmctx_roots(&mut self, gc_roots_list: &mut GcRootsList) {
1748         log::trace!("Begin trace GC roots :: vmctx");
1749         self.for_each_global(|store, global| global.trace_root(store, gc_roots_list));
1750         self.for_each_table(|store, table| table.trace_roots(store, gc_roots_list));
1751         log::trace!("End trace GC roots :: vmctx");
1752     }
1753 
1754     #[cfg(feature = "gc")]
1755     fn trace_user_roots(&mut self, gc_roots_list: &mut GcRootsList) {
1756         log::trace!("Begin trace GC roots :: user");
1757         self.gc_roots.trace_roots(gc_roots_list);
1758         log::trace!("End trace GC roots :: user");
1759     }
1760 
1761     /// Insert a host-allocated GC type into this store.
1762     ///
1763     /// This makes it suitable for the embedder to allocate instances of this
1764     /// type in this store, and we don't have to worry about the type being
1765     /// reclaimed (since it is possible that none of the Wasm modules in this
1766     /// store are holding it alive).
1767     #[cfg(feature = "gc")]
1768     pub(crate) fn insert_gc_host_alloc_type(&mut self, ty: crate::type_registry::RegisteredType) {
1769         self.gc_host_alloc_types.insert(ty);
1770     }
1771 
1772     /// Helper function execute a `init_gc_ref` when placing `gc_ref` in `dest`.
1773     ///
1774     /// This avoids allocating `GcStore` where possible.
1775     pub(crate) fn init_gc_ref(
1776         &mut self,
1777         dest: &mut MaybeUninit<Option<VMGcRef>>,
1778         gc_ref: Option<&VMGcRef>,
1779     ) {
1780         if GcStore::needs_init_barrier(gc_ref) {
1781             self.unwrap_gc_store_mut().init_gc_ref(dest, gc_ref)
1782         } else {
1783             dest.write(gc_ref.map(|r| r.copy_i31()));
1784         }
1785     }
1786 
1787     /// Helper function execute a write barrier when placing `gc_ref` in `dest`.
1788     ///
1789     /// This avoids allocating `GcStore` where possible.
1790     pub(crate) fn write_gc_ref(&mut self, dest: &mut Option<VMGcRef>, gc_ref: Option<&VMGcRef>) {
1791         GcStore::write_gc_ref_optional_store(self.optional_gc_store_mut(), dest, gc_ref)
1792     }
1793 
1794     /// Helper function to clone `gc_ref` notably avoiding allocating a
1795     /// `GcStore` where possible.
1796     pub(crate) fn clone_gc_ref(&mut self, gc_ref: &VMGcRef) -> VMGcRef {
1797         if gc_ref.is_i31() {
1798             gc_ref.copy_i31()
1799         } else {
1800             self.unwrap_gc_store_mut().clone_gc_ref(gc_ref)
1801         }
1802     }
1803 
1804     pub fn get_fuel(&self) -> Result<u64> {
1805         anyhow::ensure!(
1806             self.engine().tunables().consume_fuel,
1807             "fuel is not configured in this store"
1808         );
1809         let injected_fuel = unsafe { *self.vm_store_context.fuel_consumed.get() };
1810         Ok(get_fuel(injected_fuel, self.fuel_reserve))
1811     }
1812 
1813     fn refuel(&mut self) -> bool {
1814         let injected_fuel = unsafe { &mut *self.vm_store_context.fuel_consumed.get() };
1815         refuel(
1816             injected_fuel,
1817             &mut self.fuel_reserve,
1818             self.fuel_yield_interval,
1819         )
1820     }
1821 
1822     pub fn set_fuel(&mut self, fuel: u64) -> Result<()> {
1823         anyhow::ensure!(
1824             self.engine().tunables().consume_fuel,
1825             "fuel is not configured in this store"
1826         );
1827         let injected_fuel = unsafe { &mut *self.vm_store_context.fuel_consumed.get() };
1828         set_fuel(
1829             injected_fuel,
1830             &mut self.fuel_reserve,
1831             self.fuel_yield_interval,
1832             fuel,
1833         );
1834         Ok(())
1835     }
1836 
1837     pub fn fuel_async_yield_interval(&mut self, interval: Option<u64>) -> Result<()> {
1838         anyhow::ensure!(
1839             self.engine().tunables().consume_fuel,
1840             "fuel is not configured in this store"
1841         );
1842         anyhow::ensure!(
1843             self.engine().config().async_support,
1844             "async support is not configured in this store"
1845         );
1846         anyhow::ensure!(
1847             interval != Some(0),
1848             "fuel_async_yield_interval must not be 0"
1849         );
1850         self.fuel_yield_interval = interval.and_then(|i| NonZeroU64::new(i));
1851         // Reset the fuel active + reserve states by resetting the amount.
1852         self.set_fuel(self.get_fuel()?)
1853     }
1854 
1855     #[inline]
1856     pub fn signal_handler(&self) -> Option<*const SignalHandler> {
1857         let handler = self.signal_handler.as_ref()?;
1858         Some(handler)
1859     }
1860 
1861     #[inline]
1862     pub fn vm_store_context_ptr(&self) -> NonNull<VMStoreContext> {
1863         NonNull::from(&self.vm_store_context)
1864     }
1865 
1866     #[inline]
1867     pub fn default_caller(&self) -> NonNull<VMContext> {
1868         self.default_caller_vmctx.as_non_null()
1869     }
1870 
1871     #[inline]
1872     pub fn traitobj(&self) -> NonNull<dyn vm::VMStore> {
1873         self.traitobj.as_raw().unwrap()
1874     }
1875 
1876     #[inline]
1877     pub fn traitobj_mut(&mut self) -> &mut dyn vm::VMStore {
1878         unsafe { self.traitobj().as_mut() }
1879     }
1880 
1881     /// Takes the cached `Vec<Val>` stored internally across hostcalls to get
1882     /// used as part of calling the host in a `Func::new` method invocation.
1883     #[inline]
1884     pub fn take_hostcall_val_storage(&mut self) -> Vec<Val> {
1885         mem::take(&mut self.hostcall_val_storage)
1886     }
1887 
1888     /// Restores the vector previously taken by `take_hostcall_val_storage`
1889     /// above back into the store, allowing it to be used in the future for the
1890     /// next wasm->host call.
1891     #[inline]
1892     pub fn save_hostcall_val_storage(&mut self, storage: Vec<Val>) {
1893         if storage.capacity() > self.hostcall_val_storage.capacity() {
1894             self.hostcall_val_storage = storage;
1895         }
1896     }
1897 
1898     /// Same as `take_hostcall_val_storage`, but for the direction of the host
1899     /// calling wasm.
1900     #[inline]
1901     pub fn take_wasm_val_raw_storage(&mut self) -> Vec<ValRaw> {
1902         mem::take(&mut self.wasm_val_raw_storage)
1903     }
1904 
1905     /// Same as `save_hostcall_val_storage`, but for the direction of the host
1906     /// calling wasm.
1907     #[inline]
1908     pub fn save_wasm_val_raw_storage(&mut self, storage: Vec<ValRaw>) {
1909         if storage.capacity() > self.wasm_val_raw_storage.capacity() {
1910             self.wasm_val_raw_storage = storage;
1911         }
1912     }
1913 
1914     /// Translates a WebAssembly fault at the native `pc` and native `addr` to a
1915     /// WebAssembly-relative fault.
1916     ///
1917     /// This function may abort the process if `addr` is not found to actually
1918     /// reside in any linear memory. In such a situation it means that the
1919     /// segfault was erroneously caught by Wasmtime and is possibly indicative
1920     /// of a code generator bug.
1921     ///
1922     /// This function returns `None` for dynamically-bounds-checked-memories
1923     /// with spectre mitigations enabled since the hardware fault address is
1924     /// always zero in these situations which means that the trapping context
1925     /// doesn't have enough information to report the fault address.
1926     pub(crate) fn wasm_fault(&self, pc: usize, addr: usize) -> Option<vm::WasmFault> {
1927         // There are a few instances where a "close to zero" pointer is loaded
1928         // and we expect that to happen:
1929         //
1930         // * Explicitly bounds-checked memories with spectre-guards enabled will
1931         //   cause out-of-bounds accesses to get routed to address 0, so allow
1932         //   wasm instructions to fault on the null address.
1933         // * `call_indirect` when invoking a null function pointer may load data
1934         //   from the a `VMFuncRef` whose address is null, meaning any field of
1935         //   `VMFuncRef` could be the address of the fault.
1936         //
1937         // In these situations where the address is so small it won't be in any
1938         // instance, so skip the checks below.
1939         if addr <= mem::size_of::<VMFuncRef>() {
1940             const _: () = {
1941                 // static-assert that `VMFuncRef` isn't too big to ensure that
1942                 // it lives solely within the first page as we currently only
1943                 // have the guarantee that the first page of memory is unmapped,
1944                 // no more.
1945                 assert!(mem::size_of::<VMFuncRef>() <= 512);
1946             };
1947             return None;
1948         }
1949 
1950         // Search all known instances in this store for this address. Note that
1951         // this is probably not the speediest way to do this. Traps, however,
1952         // are generally not expected to be super fast and additionally stores
1953         // probably don't have all that many instances or memories.
1954         //
1955         // If this loop becomes hot in the future, however, it should be
1956         // possible to precompute maps about linear memories in a store and have
1957         // a quicker lookup.
1958         let mut fault = None;
1959         for (_, instance) in self.instances.iter() {
1960             if let Some(f) = instance.handle.get().wasm_fault(addr) {
1961                 assert!(fault.is_none());
1962                 fault = Some(f);
1963             }
1964         }
1965         if fault.is_some() {
1966             return fault;
1967         }
1968 
1969         cfg_if::cfg_if! {
1970             if #[cfg(feature = "std")] {
1971                 // With the standard library a rich error can be printed here
1972                 // to stderr and the native abort path is used.
1973                 eprintln!(
1974                     "\
1975 Wasmtime caught a segfault for a wasm program because the faulting instruction
1976 is allowed to segfault due to how linear memories are implemented. The address
1977 that was accessed, however, is not known to any linear memory in use within this
1978 Store. This may be indicative of a critical bug in Wasmtime's code generation
1979 because all addresses which are known to be reachable from wasm won't reach this
1980 message.
1981 
1982     pc:      0x{pc:x}
1983     address: 0x{addr:x}
1984 
1985 This is a possible security issue because WebAssembly has accessed something it
1986 shouldn't have been able to. Other accesses may have succeeded and this one just
1987 happened to be caught. The process will now be aborted to prevent this damage
1988 from going any further and to alert what's going on. If this is a security
1989 issue please reach out to the Wasmtime team via its security policy
1990 at https://bytecodealliance.org/security.
1991 "
1992                 );
1993                 std::process::abort();
1994             } else if #[cfg(panic = "abort")] {
1995                 // Without the standard library but with `panic=abort` then
1996                 // it's safe to panic as that's known to halt execution. For
1997                 // now avoid the above error message as well since without
1998                 // `std` it's probably best to be a bit more size-conscious.
1999                 let _ = pc;
2000                 panic!("invalid fault");
2001             } else {
2002                 // Without `std` and with `panic = "unwind"` there's no
2003                 // dedicated API to abort the process portably, so manufacture
2004                 // this with a double-panic.
2005                 let _ = pc;
2006 
2007                 struct PanicAgainOnDrop;
2008 
2009                 impl Drop for PanicAgainOnDrop {
2010                     fn drop(&mut self) {
2011                         panic!("panicking again to trigger a process abort");
2012                     }
2013 
2014                 }
2015 
2016                 let _bomb = PanicAgainOnDrop;
2017 
2018                 panic!("invalid fault");
2019             }
2020         }
2021     }
2022 
2023     /// Retrieve the store's protection key.
2024     #[inline]
2025     pub(crate) fn get_pkey(&self) -> Option<ProtectionKey> {
2026         self.pkey
2027     }
2028 
2029     #[inline]
2030     #[cfg(feature = "component-model")]
2031     pub(crate) fn component_resource_state(
2032         &mut self,
2033     ) -> (
2034         &mut vm::component::CallContexts,
2035         &mut vm::component::HandleTable,
2036         &mut crate::component::HostResourceData,
2037     ) {
2038         (
2039             &mut self.component_calls,
2040             &mut self.component_host_table,
2041             &mut self.host_resource_data,
2042         )
2043     }
2044 
2045     #[cfg(feature = "component-model")]
2046     pub(crate) fn push_component_instance(&mut self, instance: crate::component::Instance) {
2047         // We don't actually need the instance itself right now, but it seems
2048         // like something we will almost certainly eventually want to keep
2049         // around, so force callers to provide it.
2050         let _ = instance;
2051 
2052         self.num_component_instances += 1;
2053     }
2054 
2055     #[inline]
2056     #[cfg(feature = "component-model")]
2057     pub(crate) fn component_resource_state_with_instance(
2058         &mut self,
2059         instance: crate::component::Instance,
2060     ) -> (
2061         &mut vm::component::CallContexts,
2062         &mut vm::component::HandleTable,
2063         &mut crate::component::HostResourceData,
2064         Pin<&mut vm::component::ComponentInstance>,
2065     ) {
2066         (
2067             &mut self.component_calls,
2068             &mut self.component_host_table,
2069             &mut self.host_resource_data,
2070             instance.id().from_data_get_mut(&mut self.store_data),
2071         )
2072     }
2073 
2074     #[cfg(feature = "async")]
2075     pub(crate) fn fiber_async_state_mut(&mut self) -> &mut fiber::AsyncState {
2076         &mut self.async_state
2077     }
2078 
2079     #[cfg(feature = "component-model-async")]
2080     pub(crate) fn concurrent_async_state_mut(&mut self) -> &mut concurrent::AsyncState {
2081         &mut self.concurrent_async_state
2082     }
2083 
2084     #[cfg(feature = "async")]
2085     pub(crate) fn has_pkey(&self) -> bool {
2086         self.pkey.is_some()
2087     }
2088 
2089     pub(crate) fn executor(&mut self) -> ExecutorRef<'_> {
2090         match &mut self.executor {
2091             Executor::Interpreter(i) => ExecutorRef::Interpreter(i.as_interpreter_ref()),
2092             #[cfg(has_host_compiler_backend)]
2093             Executor::Native => ExecutorRef::Native,
2094         }
2095     }
2096 
2097     #[cfg(feature = "async")]
2098     pub(crate) fn swap_executor(&mut self, executor: &mut Executor) {
2099         mem::swap(&mut self.executor, executor);
2100     }
2101 
2102     pub(crate) fn unwinder(&self) -> &'static dyn Unwind {
2103         match &self.executor {
2104             Executor::Interpreter(i) => i.unwinder(),
2105             #[cfg(has_host_compiler_backend)]
2106             Executor::Native => &vm::UnwindHost,
2107         }
2108     }
2109 
2110     /// Allocates a new continuation. Note that we currently don't support
2111     /// deallocating them. Instead, all continuations remain allocated
2112     /// throughout the store's lifetime.
2113     #[cfg(feature = "stack-switching")]
2114     pub fn allocate_continuation(&mut self) -> Result<*mut VMContRef> {
2115         // FIXME(frank-emrich) Do we need to pin this?
2116         let mut continuation = Box::new(VMContRef::empty());
2117         let stack_size = self.engine.config().async_stack_size;
2118         let stack = crate::vm::VMContinuationStack::new(stack_size)?;
2119         continuation.stack = stack;
2120         let ptr = continuation.deref_mut() as *mut VMContRef;
2121         self.continuations.push(continuation);
2122         Ok(ptr)
2123     }
2124 
2125     /// Constructs and executes an `InstanceAllocationRequest` and pushes the
2126     /// returned instance into the store.
2127     ///
2128     /// This is a helper method for invoking
2129     /// `InstanceAllocator::allocate_module` with the appropriate parameters
2130     /// from this store's own configuration. The `kind` provided is used to
2131     /// distinguish between "real" modules and dummy ones that are synthesized
2132     /// for embedder-created memories, globals, tables, etc. The `kind` will
2133     /// also use a different instance allocator by default, the one passed in,
2134     /// rather than the engine's default allocator.
2135     ///
2136     /// This method will push the instance within `StoreOpaque` onto the
2137     /// `instances` array and return the `InstanceId` which can be use to look
2138     /// it up within the store.
2139     ///
2140     /// # Safety
2141     ///
2142     /// The `imports` provided must be correctly sized/typed for the module
2143     /// being allocated.
2144     pub(crate) unsafe fn allocate_instance(
2145         &mut self,
2146         kind: AllocateInstanceKind<'_>,
2147         runtime_info: &ModuleRuntimeInfo,
2148         imports: Imports<'_>,
2149     ) -> Result<InstanceId> {
2150         let id = self.instances.next_key();
2151 
2152         let allocator = match kind {
2153             AllocateInstanceKind::Module(_) => self.engine().allocator(),
2154             AllocateInstanceKind::Dummy { allocator } => allocator,
2155         };
2156         // SAFETY: this function's own contract is the same as
2157         // `allocate_module`, namely the imports provided are valid.
2158         let handle = unsafe {
2159             allocator.allocate_module(InstanceAllocationRequest {
2160                 id,
2161                 runtime_info,
2162                 imports,
2163                 store: StorePtr::new(self.traitobj()),
2164                 #[cfg(feature = "wmemcheck")]
2165                 wmemcheck: self.engine().config().wmemcheck,
2166                 pkey: self.get_pkey(),
2167                 tunables: self.engine().tunables(),
2168             })?
2169         };
2170 
2171         let actual = match kind {
2172             AllocateInstanceKind::Module(module_id) => {
2173                 log::trace!(
2174                     "Adding instance to store: store={:?}, module={module_id:?}, instance={id:?}",
2175                     self.id()
2176                 );
2177                 self.instances.push(StoreInstance {
2178                     handle,
2179                     kind: StoreInstanceKind::Real { module_id },
2180                 })
2181             }
2182             AllocateInstanceKind::Dummy { .. } => {
2183                 log::trace!(
2184                     "Adding dummy instance to store: store={:?}, instance={id:?}",
2185                     self.id()
2186                 );
2187                 self.instances.push(StoreInstance {
2188                     handle,
2189                     kind: StoreInstanceKind::Dummy,
2190                 })
2191             }
2192         };
2193 
2194         // double-check we didn't accidentally allocate two instances and our
2195         // prediction of what the id would be is indeed the id it should be.
2196         assert_eq!(id, actual);
2197 
2198         Ok(id)
2199     }
2200 }
2201 
2202 /// Helper parameter to [`StoreOpaque::allocate_instance`].
2203 pub(crate) enum AllocateInstanceKind<'a> {
2204     /// An embedder-provided module is being allocated meaning that the default
2205     /// engine's allocator will be used.
2206     Module(RegisteredModuleId),
2207 
2208     /// Add a dummy instance that to the store.
2209     ///
2210     /// These are instances that are just implementation details of something
2211     /// else (e.g. host-created memories that are not actually defined in any
2212     /// Wasm module) and therefore shouldn't show up in things like core dumps.
2213     ///
2214     /// A custom, typically OnDemand-flavored, allocator is provided to execute
2215     /// the allocation.
2216     Dummy {
2217         allocator: &'a dyn InstanceAllocator,
2218     },
2219 }
2220 
2221 unsafe impl<T> vm::VMStore for StoreInner<T> {
2222     #[cfg(feature = "component-model-async")]
2223     fn component_async_store(
2224         &mut self,
2225     ) -> &mut dyn crate::runtime::component::VMComponentAsyncStore {
2226         self
2227     }
2228 
2229     fn store_opaque(&self) -> &StoreOpaque {
2230         &self.inner
2231     }
2232 
2233     fn store_opaque_mut(&mut self) -> &mut StoreOpaque {
2234         &mut self.inner
2235     }
2236 
2237     fn memory_growing(
2238         &mut self,
2239         current: usize,
2240         desired: usize,
2241         maximum: Option<usize>,
2242     ) -> Result<bool, anyhow::Error> {
2243         match self.limiter {
2244             Some(ResourceLimiterInner::Sync(ref mut limiter)) => {
2245                 limiter(&mut self.data).memory_growing(current, desired, maximum)
2246             }
2247             #[cfg(feature = "async")]
2248             Some(ResourceLimiterInner::Async(_)) => self.block_on(|store| {
2249                 let limiter = match &mut store.0.limiter {
2250                     Some(ResourceLimiterInner::Async(limiter)) => limiter,
2251                     _ => unreachable!(),
2252                 };
2253                 limiter(&mut store.0.data).memory_growing(current, desired, maximum)
2254             })?,
2255             None => Ok(true),
2256         }
2257     }
2258 
2259     fn memory_grow_failed(&mut self, error: anyhow::Error) -> Result<()> {
2260         match self.limiter {
2261             Some(ResourceLimiterInner::Sync(ref mut limiter)) => {
2262                 limiter(&mut self.data).memory_grow_failed(error)
2263             }
2264             #[cfg(feature = "async")]
2265             Some(ResourceLimiterInner::Async(ref mut limiter)) => {
2266                 limiter(&mut self.data).memory_grow_failed(error)
2267             }
2268             None => {
2269                 log::debug!("ignoring memory growth failure error: {error:?}");
2270                 Ok(())
2271             }
2272         }
2273     }
2274 
2275     fn table_growing(
2276         &mut self,
2277         current: usize,
2278         desired: usize,
2279         maximum: Option<usize>,
2280     ) -> Result<bool, anyhow::Error> {
2281         match self.limiter {
2282             Some(ResourceLimiterInner::Sync(ref mut limiter)) => {
2283                 limiter(&mut self.data).table_growing(current, desired, maximum)
2284             }
2285             #[cfg(feature = "async")]
2286             Some(ResourceLimiterInner::Async(_)) => self.block_on(|store| {
2287                 let limiter = match &mut store.0.limiter {
2288                     Some(ResourceLimiterInner::Async(limiter)) => limiter,
2289                     _ => unreachable!(),
2290                 };
2291                 limiter(&mut store.0.data).table_growing(current, desired, maximum)
2292             })?,
2293             None => Ok(true),
2294         }
2295     }
2296 
2297     fn table_grow_failed(&mut self, error: anyhow::Error) -> Result<()> {
2298         match self.limiter {
2299             Some(ResourceLimiterInner::Sync(ref mut limiter)) => {
2300                 limiter(&mut self.data).table_grow_failed(error)
2301             }
2302             #[cfg(feature = "async")]
2303             Some(ResourceLimiterInner::Async(ref mut limiter)) => {
2304                 limiter(&mut self.data).table_grow_failed(error)
2305             }
2306             None => {
2307                 log::debug!("ignoring table growth failure: {error:?}");
2308                 Ok(())
2309             }
2310         }
2311     }
2312 
2313     fn out_of_gas(&mut self) -> Result<()> {
2314         if !self.refuel() {
2315             return Err(Trap::OutOfFuel.into());
2316         }
2317         #[cfg(feature = "async")]
2318         if self.fuel_yield_interval.is_some() {
2319             self.async_yield_impl()?;
2320         }
2321         Ok(())
2322     }
2323 
2324     #[cfg(target_has_atomic = "64")]
2325     fn new_epoch(&mut self) -> Result<u64, anyhow::Error> {
2326         // Temporarily take the configured behavior to avoid mutably borrowing
2327         // multiple times.
2328         let mut behavior = self.epoch_deadline_behavior.take();
2329         let delta_result = match &mut behavior {
2330             None => Err(Trap::Interrupt.into()),
2331             Some(callback) => callback((&mut *self).as_context_mut()).and_then(|update| {
2332                 let delta = match update {
2333                     UpdateDeadline::Continue(delta) => delta,
2334                     #[cfg(feature = "async")]
2335                     UpdateDeadline::Yield(delta) => {
2336                         assert!(
2337                             self.async_support(),
2338                             "cannot use `UpdateDeadline::Yield` without enabling async support in the config"
2339                         );
2340                         // Do the async yield. May return a trap if future was
2341                         // canceled while we're yielded.
2342                         self.async_yield_impl()?;
2343                         delta
2344                     }
2345                     #[cfg(feature = "async")]
2346                     UpdateDeadline::YieldCustom(delta, future) => {
2347                         assert!(
2348                             self.async_support(),
2349                             "cannot use `UpdateDeadline::YieldCustom` without enabling async support in the config"
2350                         );
2351 
2352                         // When control returns, we have a `Result<()>` passed
2353                         // in from the host fiber. If this finished successfully then
2354                         // we were resumed normally via a `poll`, so keep going.  If
2355                         // the future was dropped while we were yielded, then we need
2356                         // to clean up this fiber. Do so by raising a trap which will
2357                         // abort all wasm and get caught on the other side to clean
2358                         // things up.
2359                         self.block_on(|_| future)?;
2360                         delta
2361                     }
2362                 };
2363 
2364                 // Set a new deadline and return the new epoch deadline so
2365                 // the Wasm code doesn't have to reload it.
2366                 self.set_epoch_deadline(delta);
2367                 Ok(self.get_epoch_deadline())
2368             })
2369         };
2370 
2371         // Put back the original behavior which was replaced by `take`.
2372         self.epoch_deadline_behavior = behavior;
2373         delta_result
2374     }
2375 
2376     #[cfg(feature = "component-model")]
2377     fn component_calls(&mut self) -> &mut vm::component::CallContexts {
2378         &mut self.component_calls
2379     }
2380 }
2381 
2382 impl<T> StoreInner<T> {
2383     #[cfg(target_has_atomic = "64")]
2384     pub(crate) fn set_epoch_deadline(&mut self, delta: u64) {
2385         // Set a new deadline based on the "epoch deadline delta".
2386         //
2387         // Also, note that when this update is performed while Wasm is
2388         // on the stack, the Wasm will reload the new value once we
2389         // return into it.
2390         let current_epoch = self.engine().current_epoch();
2391         let epoch_deadline = self.vm_store_context.epoch_deadline.get_mut();
2392         *epoch_deadline = current_epoch + delta;
2393     }
2394 
2395     #[cfg(target_has_atomic = "64")]
2396     fn epoch_deadline_trap(&mut self) {
2397         self.epoch_deadline_behavior = None;
2398     }
2399 
2400     #[cfg(target_has_atomic = "64")]
2401     fn epoch_deadline_callback(
2402         &mut self,
2403         callback: Box<dyn FnMut(StoreContextMut<T>) -> Result<UpdateDeadline> + Send + Sync>,
2404     ) {
2405         self.epoch_deadline_behavior = Some(callback);
2406     }
2407 
2408     fn get_epoch_deadline(&mut self) -> u64 {
2409         *self.vm_store_context.epoch_deadline.get_mut()
2410     }
2411 }
2412 
2413 impl<T: Default> Default for Store<T> {
2414     fn default() -> Store<T> {
2415         Store::new(&Engine::default(), T::default())
2416     }
2417 }
2418 
2419 impl<T: fmt::Debug> fmt::Debug for Store<T> {
2420     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2421         let inner = &**self.inner as *const StoreInner<T>;
2422         f.debug_struct("Store")
2423             .field("inner", &inner)
2424             .field("data", &self.inner.data)
2425             .finish()
2426     }
2427 }
2428 
2429 impl<T> Drop for Store<T> {
2430     fn drop(&mut self) {
2431         self.run_manual_drop_routines();
2432 
2433         // for documentation on this `unsafe`, see `into_data`.
2434         unsafe {
2435             ManuallyDrop::drop(&mut self.inner.data);
2436             ManuallyDrop::drop(&mut self.inner);
2437         }
2438     }
2439 }
2440 
2441 impl Drop for StoreOpaque {
2442     fn drop(&mut self) {
2443         // NB it's important that this destructor does not access `self.data`.
2444         // That is deallocated by `Drop for Store<T>` above.
2445 
2446         unsafe {
2447             let allocator = self.engine.allocator();
2448             let ondemand = OnDemandInstanceAllocator::default();
2449             let store_id = self.id();
2450 
2451             #[cfg(feature = "gc")]
2452             if let Some(gc_store) = self.gc_store.take() {
2453                 let gc_alloc_index = gc_store.allocation_index;
2454                 log::trace!("store {store_id:?} is deallocating GC heap {gc_alloc_index:?}");
2455                 debug_assert!(self.engine.features().gc_types());
2456                 let (mem_alloc_index, mem) =
2457                     allocator.deallocate_gc_heap(gc_alloc_index, gc_store.gc_heap);
2458                 allocator.deallocate_memory(None, mem_alloc_index, mem);
2459             }
2460 
2461             for (id, instance) in self.instances.iter_mut() {
2462                 log::trace!("store {store_id:?} is deallocating {id:?}");
2463                 if let StoreInstanceKind::Dummy = instance.kind {
2464                     ondemand.deallocate_module(&mut instance.handle);
2465                 } else {
2466                     allocator.deallocate_module(&mut instance.handle);
2467                 }
2468             }
2469 
2470             #[cfg(feature = "component-model")]
2471             {
2472                 for _ in 0..self.num_component_instances {
2473                     allocator.decrement_component_instance_count();
2474                 }
2475             }
2476         }
2477     }
2478 }
2479 
2480 #[cfg(test)]
2481 mod tests {
2482     use super::{get_fuel, refuel, set_fuel};
2483     use std::num::NonZeroU64;
2484 
2485     struct FuelTank {
2486         pub consumed_fuel: i64,
2487         pub reserve_fuel: u64,
2488         pub yield_interval: Option<NonZeroU64>,
2489     }
2490 
2491     impl FuelTank {
2492         fn new() -> Self {
2493             FuelTank {
2494                 consumed_fuel: 0,
2495                 reserve_fuel: 0,
2496                 yield_interval: None,
2497             }
2498         }
2499         fn get_fuel(&self) -> u64 {
2500             get_fuel(self.consumed_fuel, self.reserve_fuel)
2501         }
2502         fn refuel(&mut self) -> bool {
2503             refuel(
2504                 &mut self.consumed_fuel,
2505                 &mut self.reserve_fuel,
2506                 self.yield_interval,
2507             )
2508         }
2509         fn set_fuel(&mut self, fuel: u64) {
2510             set_fuel(
2511                 &mut self.consumed_fuel,
2512                 &mut self.reserve_fuel,
2513                 self.yield_interval,
2514                 fuel,
2515             );
2516         }
2517     }
2518 
2519     #[test]
2520     fn smoke() {
2521         let mut tank = FuelTank::new();
2522         tank.set_fuel(10);
2523         assert_eq!(tank.consumed_fuel, -10);
2524         assert_eq!(tank.reserve_fuel, 0);
2525 
2526         tank.yield_interval = NonZeroU64::new(10);
2527         tank.set_fuel(25);
2528         assert_eq!(tank.consumed_fuel, -10);
2529         assert_eq!(tank.reserve_fuel, 15);
2530     }
2531 
2532     #[test]
2533     fn does_not_lose_precision() {
2534         let mut tank = FuelTank::new();
2535         tank.set_fuel(u64::MAX);
2536         assert_eq!(tank.get_fuel(), u64::MAX);
2537 
2538         tank.set_fuel(i64::MAX as u64);
2539         assert_eq!(tank.get_fuel(), i64::MAX as u64);
2540 
2541         tank.set_fuel(i64::MAX as u64 + 1);
2542         assert_eq!(tank.get_fuel(), i64::MAX as u64 + 1);
2543     }
2544 
2545     #[test]
2546     fn yielding_does_not_lose_precision() {
2547         let mut tank = FuelTank::new();
2548 
2549         tank.yield_interval = NonZeroU64::new(10);
2550         tank.set_fuel(u64::MAX);
2551         assert_eq!(tank.get_fuel(), u64::MAX);
2552         assert_eq!(tank.consumed_fuel, -10);
2553         assert_eq!(tank.reserve_fuel, u64::MAX - 10);
2554 
2555         tank.yield_interval = NonZeroU64::new(u64::MAX);
2556         tank.set_fuel(u64::MAX);
2557         assert_eq!(tank.get_fuel(), u64::MAX);
2558         assert_eq!(tank.consumed_fuel, -i64::MAX);
2559         assert_eq!(tank.reserve_fuel, u64::MAX - (i64::MAX as u64));
2560 
2561         tank.yield_interval = NonZeroU64::new((i64::MAX as u64) + 1);
2562         tank.set_fuel(u64::MAX);
2563         assert_eq!(tank.get_fuel(), u64::MAX);
2564         assert_eq!(tank.consumed_fuel, -i64::MAX);
2565         assert_eq!(tank.reserve_fuel, u64::MAX - (i64::MAX as u64));
2566     }
2567 
2568     #[test]
2569     fn refueling() {
2570         // It's possible to fuel to have consumed over the limit as some instructions can consume
2571         // multiple units of fuel at once. Refueling should be strict in it's consumption and not
2572         // add more fuel than there is.
2573         let mut tank = FuelTank::new();
2574 
2575         tank.yield_interval = NonZeroU64::new(10);
2576         tank.reserve_fuel = 42;
2577         tank.consumed_fuel = 4;
2578         assert!(tank.refuel());
2579         assert_eq!(tank.reserve_fuel, 28);
2580         assert_eq!(tank.consumed_fuel, -10);
2581 
2582         tank.yield_interval = NonZeroU64::new(1);
2583         tank.reserve_fuel = 8;
2584         tank.consumed_fuel = 4;
2585         assert_eq!(tank.get_fuel(), 4);
2586         assert!(tank.refuel());
2587         assert_eq!(tank.reserve_fuel, 3);
2588         assert_eq!(tank.consumed_fuel, -1);
2589         assert_eq!(tank.get_fuel(), 4);
2590 
2591         tank.yield_interval = NonZeroU64::new(10);
2592         tank.reserve_fuel = 3;
2593         tank.consumed_fuel = 4;
2594         assert_eq!(tank.get_fuel(), 0);
2595         assert!(!tank.refuel());
2596         assert_eq!(tank.reserve_fuel, 3);
2597         assert_eq!(tank.consumed_fuel, 4);
2598         assert_eq!(tank.get_fuel(), 0);
2599     }
2600 }
2601