Skip to main content

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