wasmtime/runtime/
store.rs

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