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