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 /// # Error
1045 ///
1046 /// This method will error if fuel is not enabled or `interval` is
1047 /// `Some(0)`.
1048 #[cfg(feature = "async")]
1049 pub fn fuel_async_yield_interval(&mut self, interval: Option<u64>) -> Result<()> {
1050 self.inner.fuel_async_yield_interval(interval)
1051 }
1052
1053 /// Sets the epoch deadline to a certain number of ticks in the future.
1054 ///
1055 /// When the Wasm guest code is compiled with epoch-interruption
1056 /// instrumentation
1057 /// ([`Config::epoch_interruption()`](crate::Config::epoch_interruption)),
1058 /// and when the `Engine`'s epoch is incremented
1059 /// ([`Engine::increment_epoch()`](crate::Engine::increment_epoch))
1060 /// past a deadline, execution can be configured to either trap or
1061 /// yield and then continue.
1062 ///
1063 /// This deadline is always set relative to the current epoch:
1064 /// `ticks_beyond_current` ticks in the future. The deadline can
1065 /// be set explicitly via this method, or refilled automatically
1066 /// on a yield if configured via
1067 /// [`epoch_deadline_async_yield_and_update()`](Store::epoch_deadline_async_yield_and_update). After
1068 /// this method is invoked, the deadline is reached when
1069 /// [`Engine::increment_epoch()`] has been invoked at least
1070 /// `ticks_beyond_current` times.
1071 ///
1072 /// By default a store will trap immediately with an epoch deadline of 0
1073 /// (which has always "elapsed"). This method is required to be configured
1074 /// for stores with epochs enabled to some future epoch deadline.
1075 ///
1076 /// See documentation on
1077 /// [`Config::epoch_interruption()`](crate::Config::epoch_interruption)
1078 /// for an introduction to epoch-based interruption.
1079 #[cfg(target_has_atomic = "64")]
1080 pub fn set_epoch_deadline(&mut self, ticks_beyond_current: u64) {
1081 self.inner.set_epoch_deadline(ticks_beyond_current);
1082 }
1083
1084 /// Configures epoch-deadline expiration to trap.
1085 ///
1086 /// When epoch-interruption-instrumented code is executed on this
1087 /// store and the epoch deadline is reached before completion,
1088 /// with the store configured in this way, execution will
1089 /// terminate with a trap as soon as an epoch check in the
1090 /// instrumented code is reached.
1091 ///
1092 /// This behavior is the default if the store is not otherwise
1093 /// configured via
1094 /// [`epoch_deadline_trap()`](Store::epoch_deadline_trap),
1095 /// [`epoch_deadline_callback()`](Store::epoch_deadline_callback) or
1096 /// [`epoch_deadline_async_yield_and_update()`](Store::epoch_deadline_async_yield_and_update).
1097 ///
1098 /// This setting is intended to allow for coarse-grained
1099 /// interruption, but not a deterministic deadline of a fixed,
1100 /// finite interval. For deterministic interruption, see the
1101 /// "fuel" mechanism instead.
1102 ///
1103 /// Note that when this is used it's required to call
1104 /// [`Store::set_epoch_deadline`] or otherwise wasm will always immediately
1105 /// trap.
1106 ///
1107 /// See documentation on
1108 /// [`Config::epoch_interruption()`](crate::Config::epoch_interruption)
1109 /// for an introduction to epoch-based interruption.
1110 #[cfg(target_has_atomic = "64")]
1111 pub fn epoch_deadline_trap(&mut self) {
1112 self.inner.epoch_deadline_trap();
1113 }
1114
1115 /// Configures epoch-deadline expiration to invoke a custom callback
1116 /// function.
1117 ///
1118 /// When epoch-interruption-instrumented code is executed on this
1119 /// store and the epoch deadline is reached before completion, the
1120 /// provided callback function is invoked.
1121 ///
1122 /// This callback should either return an [`UpdateDeadline`], or
1123 /// return an error, which will terminate execution with a trap.
1124 ///
1125 /// The [`UpdateDeadline`] is a positive number of ticks to
1126 /// add to the epoch deadline, as well as indicating what
1127 /// to do after the callback returns. If the [`Store`] is
1128 /// configured with async support, then the callback may return
1129 /// [`UpdateDeadline::Yield`] or [`UpdateDeadline::YieldCustom`]
1130 /// to yield to the async executor before updating the epoch deadline.
1131 /// Alternatively, the callback may return [`UpdateDeadline::Continue`] to
1132 /// update the epoch deadline immediately.
1133 ///
1134 /// This setting is intended to allow for coarse-grained
1135 /// interruption, but not a deterministic deadline of a fixed,
1136 /// finite interval. For deterministic interruption, see the
1137 /// "fuel" mechanism instead.
1138 ///
1139 /// See documentation on
1140 /// [`Config::epoch_interruption()`](crate::Config::epoch_interruption)
1141 /// for an introduction to epoch-based interruption.
1142 #[cfg(target_has_atomic = "64")]
1143 pub fn epoch_deadline_callback(
1144 &mut self,
1145 callback: impl FnMut(StoreContextMut<T>) -> Result<UpdateDeadline> + Send + Sync + 'static,
1146 ) {
1147 self.inner.epoch_deadline_callback(Box::new(callback));
1148 }
1149
1150 /// Tests whether there is a pending exception.
1151 ///
1152 /// Ordinarily, a pending exception will be set on a store if and
1153 /// only if a host-side callstack is propagating a
1154 /// [`crate::ThrownException`] error. The final consumer that
1155 /// catches the exception takes it; it may re-place it to re-throw
1156 /// (using [`Self::throw`]) if it chooses not to actually handle the
1157 /// exception.
1158 ///
1159 /// This method is useful to tell whether a store is in this
1160 /// state, but should not be used as part of the ordinary
1161 /// exception-handling flow. For the most idiomatic handling, see
1162 /// [`StoreContextMut::throw`].
1163 pub fn has_pending_exception(&self) -> bool {
1164 self.inner.has_pending_exception()
1165 }
1166
1167 /// Return all breakpoints.
1168 #[cfg(feature = "debug")]
1169 pub fn breakpoints(&self) -> Option<impl Iterator<Item = crate::Breakpoint> + '_> {
1170 self.as_context().breakpoints()
1171 }
1172
1173 /// Indicate whether single-step mode is enabled.
1174 #[cfg(feature = "debug")]
1175 pub fn is_single_step(&self) -> bool {
1176 self.as_context().is_single_step()
1177 }
1178
1179 /// Set the debug callback on this store.
1180 ///
1181 /// See [`crate::DebugHandler`] for more documentation.
1182 ///
1183 /// # Panics
1184 ///
1185 /// - Will panic if guest-debug support was not enabled via
1186 /// [`crate::Config::guest_debug`].
1187 #[cfg(feature = "debug")]
1188 pub fn set_debug_handler(&mut self, handler: impl DebugHandler<Data = T>)
1189 where
1190 // We require `Send` here because the debug handler becomes
1191 // referenced from a future: when `DebugHandler::handle` is
1192 // invoked, its `self` references the `handler` with the
1193 // user's state. Note that we are careful to keep this bound
1194 // constrained to debug-handler-related code only and not
1195 // propagate it outward to the store in general. The presence
1196 // of the trait implementation serves as a witness that `T:
1197 // Send`. This is required in particular because we will have
1198 // a `&mut dyn VMStore` on the stack when we pause a fiber
1199 // with `block_on` to run a debugger hook; that `VMStore` must
1200 // be a `Store<T> where T: Send`.
1201 T: Send,
1202 {
1203 // Debug hooks rely on async support, so async entrypoints are required.
1204 self.inner.set_async_required(Asyncness::Yes);
1205
1206 assert!(
1207 self.engine().tunables().debug_guest,
1208 "debug hooks require guest debugging to be enabled"
1209 );
1210 self.inner.debug_handler = Some(Box::new(handler));
1211 }
1212
1213 /// Clear the debug handler on this store. If any existed, it will
1214 /// be dropped.
1215 #[cfg(feature = "debug")]
1216 pub fn clear_debug_handler(&mut self) {
1217 self.inner.debug_handler = None;
1218 }
1219
1220 /// Register a [`Module`] with this store's module registry for
1221 /// debugging, without instantiating it.
1222 ///
1223 /// This makes the module visible to debuggers (via
1224 /// `debug_all_modules`) before the module is actually
1225 /// instantiated. This is useful for guest-debug workflows where
1226 /// the debugger needs to see modules to set breakpoints before
1227 /// the first Wasm instruction executes.
1228 #[cfg(feature = "debug")]
1229 pub fn debug_register_module(&mut self, module: &crate::Module) -> crate::Result<()> {
1230 let (modules, engine, breakpoints) = self.inner.modules_and_engine_and_breakpoints_mut();
1231 modules.register_module(module, engine, breakpoints)?;
1232 Ok(())
1233 }
1234
1235 /// Register all inner modules of a [`Component`](crate::component::Component)
1236 /// with this store's module registry for debugging, without instantiating
1237 /// the component.
1238 #[cfg(all(feature = "debug", feature = "component-model"))]
1239 pub fn debug_register_component(
1240 &mut self,
1241 component: &crate::component::Component,
1242 ) -> crate::Result<()> {
1243 for module in component.static_modules() {
1244 self.debug_register_module(module)?;
1245 }
1246 Ok(())
1247 }
1248}
1249
1250impl<'a, T> StoreContext<'a, T> {
1251 /// Returns the underlying [`Engine`] this store is connected to.
1252 pub fn engine(&self) -> &Engine {
1253 self.0.engine()
1254 }
1255
1256 /// Access the underlying data owned by this `Store`.
1257 ///
1258 /// Same as [`Store::data`].
1259 pub fn data(&self) -> &'a T {
1260 self.0.data()
1261 }
1262
1263 /// Returns the remaining fuel in this store.
1264 ///
1265 /// For more information see [`Store::get_fuel`].
1266 pub fn get_fuel(&self) -> Result<u64> {
1267 self.0.get_fuel()
1268 }
1269}
1270
1271impl<'a, T> StoreContextMut<'a, T> {
1272 /// Access the underlying data owned by this `Store`.
1273 ///
1274 /// Same as [`Store::data`].
1275 pub fn data(&self) -> &T {
1276 self.0.data()
1277 }
1278
1279 /// Access the underlying data owned by this `Store`.
1280 ///
1281 /// Same as [`Store::data_mut`].
1282 pub fn data_mut(&mut self) -> &mut T {
1283 self.0.data_mut()
1284 }
1285
1286 /// Returns the underlying [`Engine`] this store is connected to.
1287 pub fn engine(&self) -> &Engine {
1288 self.0.engine()
1289 }
1290
1291 /// Returns remaining fuel in this store.
1292 ///
1293 /// For more information see [`Store::get_fuel`]
1294 pub fn get_fuel(&self) -> Result<u64> {
1295 self.0.get_fuel()
1296 }
1297
1298 /// Set the amount of fuel in this store.
1299 ///
1300 /// For more information see [`Store::set_fuel`]
1301 pub fn set_fuel(&mut self, fuel: u64) -> Result<()> {
1302 self.0.set_fuel(fuel)
1303 }
1304
1305 /// Configures this `Store` to periodically yield while executing futures.
1306 ///
1307 /// For more information see [`Store::fuel_async_yield_interval`]
1308 #[cfg(feature = "async")]
1309 pub fn fuel_async_yield_interval(&mut self, interval: Option<u64>) -> Result<()> {
1310 self.0.fuel_async_yield_interval(interval)
1311 }
1312
1313 /// Sets the epoch deadline to a certain number of ticks in the future.
1314 ///
1315 /// For more information see [`Store::set_epoch_deadline`].
1316 #[cfg(target_has_atomic = "64")]
1317 pub fn set_epoch_deadline(&mut self, ticks_beyond_current: u64) {
1318 self.0.set_epoch_deadline(ticks_beyond_current);
1319 }
1320
1321 /// Configures epoch-deadline expiration to trap.
1322 ///
1323 /// For more information see [`Store::epoch_deadline_trap`].
1324 #[cfg(target_has_atomic = "64")]
1325 pub fn epoch_deadline_trap(&mut self) {
1326 self.0.epoch_deadline_trap();
1327 }
1328
1329 /// Tests whether there is a pending exception.
1330 ///
1331 /// See [`Store::has_pending_exception`] for more details.
1332 pub fn has_pending_exception(&self) -> bool {
1333 self.0.inner.has_pending_exception()
1334 }
1335}
1336
1337impl<T> StoreInner<T> {
1338 #[inline]
1339 fn data(&self) -> &T {
1340 // We are actually just accessing `&self.data_no_provenance` but we must
1341 // do so with the `VMStoreContext::store_data` pointer's provenance. If
1342 // we did otherwise, i.e. directly accessed the field, we would
1343 // invalidate that pointer, which would in turn invalidate any direct
1344 // `T` accesses that Wasm code makes via unsafe intrinsics.
1345 let data: *const ManuallyDrop<T> = &raw const self.data_no_provenance;
1346 let provenance = self.inner.vm_store_context.store_data.as_ptr().cast::<T>();
1347 let ptr = provenance.with_addr(data.addr());
1348
1349 // SAFETY: The pointer is non-null, points to our `T` data, and is valid
1350 // to access because of our `&self` borrow.
1351 debug_assert_ne!(ptr, core::ptr::null_mut());
1352 debug_assert_eq!(ptr.addr(), (&raw const self.data_no_provenance).addr());
1353 unsafe { &*ptr }
1354 }
1355
1356 #[inline]
1357 fn data_limiter_and_opaque(
1358 &mut self,
1359 ) -> (
1360 &mut T,
1361 Option<&mut ResourceLimiterInner<T>>,
1362 &mut StoreOpaque,
1363 ) {
1364 // See the comments about provenance in `StoreInner::data` above.
1365 let data: *mut ManuallyDrop<T> = &raw mut self.data_no_provenance;
1366 let provenance = self.inner.vm_store_context.store_data.as_ptr().cast::<T>();
1367 let ptr = provenance.with_addr(data.addr());
1368
1369 // SAFETY: The pointer is non-null, points to our `T` data, and is valid
1370 // to access because of our `&mut self` borrow.
1371 debug_assert_ne!(ptr, core::ptr::null_mut());
1372 debug_assert_eq!(ptr.addr(), (&raw const self.data_no_provenance).addr());
1373 let data = unsafe { &mut *ptr };
1374
1375 let limiter = self.limiter.as_mut();
1376
1377 (data, limiter, &mut self.inner)
1378 }
1379
1380 #[inline]
1381 fn data_mut(&mut self) -> &mut T {
1382 self.data_limiter_and_opaque().0
1383 }
1384
1385 #[inline]
1386 pub fn call_hook(&mut self, s: CallHook) -> Result<()> {
1387 if self.inner.pkey.is_none() && self.call_hook.is_none() {
1388 Ok(())
1389 } else {
1390 self.call_hook_slow_path(s)
1391 }
1392 }
1393
1394 fn call_hook_slow_path(&mut self, s: CallHook) -> Result<()> {
1395 if let Some(pkey) = &self.inner.pkey {
1396 let allocator = self.engine().allocator();
1397 match s {
1398 CallHook::CallingWasm | CallHook::ReturningFromHost => {
1399 allocator.restrict_to_pkey(*pkey)
1400 }
1401 CallHook::ReturningFromWasm | CallHook::CallingHost => allocator.allow_all_pkeys(),
1402 }
1403 }
1404
1405 // Temporarily take the configured behavior to avoid mutably borrowing
1406 // multiple times.
1407 if let Some(mut call_hook) = self.call_hook.take() {
1408 let result = self.invoke_call_hook(&mut call_hook, s);
1409 self.call_hook = Some(call_hook);
1410 return result;
1411 }
1412
1413 Ok(())
1414 }
1415
1416 fn invoke_call_hook(&mut self, call_hook: &mut CallHookInner<T>, s: CallHook) -> Result<()> {
1417 match call_hook {
1418 #[cfg(feature = "call-hook")]
1419 CallHookInner::Sync(hook) => hook((&mut *self).as_context_mut(), s),
1420
1421 #[cfg(all(feature = "async", feature = "call-hook"))]
1422 CallHookInner::Async(handler) => {
1423 if !self.can_block() {
1424 bail!("couldn't grab async_cx for call hook")
1425 }
1426 return (&mut *self)
1427 .as_context_mut()
1428 .with_blocking(|store, cx| cx.block_on(handler.handle_call_event(store, s)))?;
1429 }
1430
1431 CallHookInner::ForceTypeParameterToBeUsed { uninhabited, .. } => {
1432 let _ = s;
1433 match *uninhabited {}
1434 }
1435 }
1436 }
1437
1438 #[cfg(not(feature = "async"))]
1439 fn flush_fiber_stack(&mut self) {
1440 // noop shim so code can assume this always exists.
1441 }
1442
1443 /// Splits this `StoreInner<T>` into a `limiter`/`StoreOpaque` borrow while
1444 /// validating that an async limiter is not configured.
1445 ///
1446 /// This is used for sync entrypoints which need to fail if an async limiter
1447 /// is configured as otherwise the async entrypoint must be used instead.
1448 pub(crate) fn validate_sync_resource_limiter_and_store_opaque(
1449 &mut self,
1450 ) -> Result<(Option<StoreResourceLimiter<'_>>, &mut StoreOpaque)> {
1451 let (limiter, store) = self.resource_limiter_and_store_opaque();
1452 if !matches!(limiter, None | Some(StoreResourceLimiter::Sync(_))) {
1453 bail!(
1454 "when using an async resource limiter `*_async` functions must \
1455 be used instead"
1456 );
1457 }
1458 Ok((limiter, store))
1459 }
1460}
1461
1462fn get_fuel(injected_fuel: i64, fuel_reserve: u64) -> u64 {
1463 fuel_reserve.saturating_add_signed(-injected_fuel)
1464}
1465
1466// Add remaining fuel from the reserve into the active fuel if there is any left.
1467fn refuel(
1468 injected_fuel: &mut i64,
1469 fuel_reserve: &mut u64,
1470 yield_interval: Option<NonZeroU64>,
1471) -> bool {
1472 let fuel = get_fuel(*injected_fuel, *fuel_reserve);
1473 if fuel > 0 {
1474 set_fuel(injected_fuel, fuel_reserve, yield_interval, fuel);
1475 true
1476 } else {
1477 false
1478 }
1479}
1480
1481fn set_fuel(
1482 injected_fuel: &mut i64,
1483 fuel_reserve: &mut u64,
1484 yield_interval: Option<NonZeroU64>,
1485 new_fuel_amount: u64,
1486) {
1487 let interval = yield_interval.unwrap_or(NonZeroU64::MAX).get();
1488 // If we're yielding periodically we only store the "active" amount of fuel into consumed_ptr
1489 // for the VM to use.
1490 let injected = core::cmp::min(interval, new_fuel_amount);
1491 // Fuel in the VM is stored as an i64, so we have to cap the amount of fuel we inject into the
1492 // VM at once to be i64 range.
1493 let injected = core::cmp::min(injected, i64::MAX as u64);
1494 // Add whatever is left over after injection to the reserve for later use.
1495 *fuel_reserve = new_fuel_amount - injected;
1496 // Within the VM we increment to count fuel, so inject a negative amount. The VM will halt when
1497 // this counter is positive.
1498 *injected_fuel = -(injected as i64);
1499}
1500
1501#[doc(hidden)]
1502impl StoreOpaque {
1503 pub fn id(&self) -> StoreId {
1504 self.store_data.id()
1505 }
1506
1507 pub fn bump_resource_counts(&mut self, module: &Module) -> Result<()> {
1508 fn bump(slot: &mut usize, max: usize, amt: usize, desc: &str) -> Result<()> {
1509 let new = slot.saturating_add(amt);
1510 if new > max {
1511 bail!("resource limit exceeded: {desc} count too high at {new}");
1512 }
1513 *slot = new;
1514 Ok(())
1515 }
1516
1517 let module = module.env_module();
1518 let memories = module.num_defined_memories();
1519 let tables = module.num_defined_tables();
1520
1521 bump(&mut self.instance_count, self.instance_limit, 1, "instance")?;
1522 bump(
1523 &mut self.memory_count,
1524 self.memory_limit,
1525 memories,
1526 "memory",
1527 )?;
1528 bump(&mut self.table_count, self.table_limit, tables, "table")?;
1529
1530 Ok(())
1531 }
1532
1533 #[inline]
1534 pub fn engine(&self) -> &Engine {
1535 &self.engine
1536 }
1537
1538 #[inline]
1539 pub fn store_data(&self) -> &StoreData {
1540 &self.store_data
1541 }
1542
1543 #[inline]
1544 pub fn store_data_mut(&mut self) -> &mut StoreData {
1545 &mut self.store_data
1546 }
1547
1548 pub fn store_data_mut_and_registry(&mut self) -> (&mut StoreData, &ModuleRegistry) {
1549 (&mut self.store_data, &self.modules)
1550 }
1551
1552 #[cfg(feature = "debug")]
1553 pub(crate) fn breakpoints_and_registry_mut(
1554 &mut self,
1555 ) -> (&mut BreakpointState, &mut ModuleRegistry) {
1556 (&mut self.breakpoints, &mut self.modules)
1557 }
1558
1559 #[cfg(feature = "debug")]
1560 pub(crate) fn breakpoints_and_registry(&self) -> (&BreakpointState, &ModuleRegistry) {
1561 (&self.breakpoints, &self.modules)
1562 }
1563
1564 #[cfg(feature = "debug")]
1565 pub(crate) fn frame_data_cache_mut_and_registry(
1566 &mut self,
1567 ) -> (&mut FrameDataCache, &ModuleRegistry) {
1568 (&mut self.frame_data_cache, &self.modules)
1569 }
1570
1571 #[inline]
1572 pub(crate) fn modules(&self) -> &ModuleRegistry {
1573 &self.modules
1574 }
1575
1576 #[inline]
1577 pub(crate) fn modules_and_engine_and_breakpoints_mut(
1578 &mut self,
1579 ) -> (&mut ModuleRegistry, &Engine, RegisterBreakpointState<'_>) {
1580 #[cfg(feature = "debug")]
1581 let breakpoints = RegisterBreakpointState(&self.breakpoints);
1582 #[cfg(not(feature = "debug"))]
1583 let breakpoints = RegisterBreakpointState(core::marker::PhantomData);
1584
1585 (&mut self.modules, &self.engine, breakpoints)
1586 }
1587
1588 pub(crate) fn func_refs_and_modules(&mut self) -> (&mut FuncRefs, &ModuleRegistry) {
1589 (&mut self.func_refs, &self.modules)
1590 }
1591
1592 pub(crate) fn host_globals(
1593 &self,
1594 ) -> &TryPrimaryMap<DefinedGlobalIndex, StoreBox<VMHostGlobalContext>> {
1595 &self.host_globals
1596 }
1597
1598 pub(crate) fn host_globals_mut(
1599 &mut self,
1600 ) -> &mut TryPrimaryMap<DefinedGlobalIndex, StoreBox<VMHostGlobalContext>> {
1601 &mut self.host_globals
1602 }
1603
1604 pub fn module_for_instance(&self, instance: StoreInstanceId) -> Option<&'_ Module> {
1605 instance.store_id().assert_belongs_to(self.id());
1606 match self.instances[instance.instance()].kind {
1607 StoreInstanceKind::Dummy => None,
1608 StoreInstanceKind::Real { module_id } => {
1609 let module = self
1610 .modules()
1611 .module_by_id(module_id)
1612 .expect("should always have a registered module for real instances");
1613 Some(module)
1614 }
1615 }
1616 }
1617
1618 /// Accessor from `InstanceId` to `&vm::Instance`.
1619 ///
1620 /// Note that if you have a `StoreInstanceId` you should use
1621 /// `StoreInstanceId::get` instead. This assumes that `id` has been
1622 /// validated to already belong to this store.
1623 #[inline]
1624 pub fn instance(&self, id: InstanceId) -> &vm::Instance {
1625 self.instances[id].handle.get()
1626 }
1627
1628 /// Accessor from `InstanceId` to `Pin<&mut vm::Instance>`.
1629 ///
1630 /// Note that if you have a `StoreInstanceId` you should use
1631 /// `StoreInstanceId::get_mut` instead. This assumes that `id` has been
1632 /// validated to already belong to this store.
1633 #[inline]
1634 pub fn instance_mut(&mut self, id: InstanceId) -> Pin<&mut vm::Instance> {
1635 self.instances[id].handle.get_mut()
1636 }
1637
1638 /// Accessor from `InstanceId` to both `Pin<&mut vm::Instance>`
1639 /// and `&ModuleRegistry`.
1640 #[inline]
1641 pub fn instance_and_module_registry_mut(
1642 &mut self,
1643 id: InstanceId,
1644 ) -> (Pin<&mut vm::Instance>, &ModuleRegistry) {
1645 (self.instances[id].handle.get_mut(), &self.modules)
1646 }
1647
1648 /// Access multiple instances specified via `ids`.
1649 ///
1650 /// # Panics
1651 ///
1652 /// This method will panic if any indices in `ids` overlap.
1653 ///
1654 /// # Safety
1655 ///
1656 /// This method is not safe if the returned instances are used to traverse
1657 /// "laterally" between other instances. For example accessing imported
1658 /// items in an instance may traverse laterally to a sibling instance thus
1659 /// aliasing a returned value here. The caller must ensure that only defined
1660 /// items within the instances themselves are accessed.
1661 #[inline]
1662 pub unsafe fn optional_gc_store_and_instances_mut<const N: usize>(
1663 &mut self,
1664 ids: [InstanceId; N],
1665 ) -> (Option<&mut GcStore>, [Pin<&mut vm::Instance>; N]) {
1666 let instances = self
1667 .instances
1668 .get_disjoint_mut(ids)
1669 .unwrap()
1670 .map(|h| h.handle.get_mut());
1671 (self.gc_store.as_mut(), instances)
1672 }
1673
1674 /// Pair of `Self::optional_gc_store_mut` and `Self::instance_mut`
1675 pub fn optional_gc_store_and_instance_mut(
1676 &mut self,
1677 id: InstanceId,
1678 ) -> (Option<&mut GcStore>, Pin<&mut vm::Instance>) {
1679 (self.gc_store.as_mut(), self.instances[id].handle.get_mut())
1680 }
1681
1682 /// Tuple of `Self::optional_gc_store_mut`, `Self::modules`, and
1683 /// `Self::instance_mut`.
1684 pub fn optional_gc_store_and_registry_and_instance_mut(
1685 &mut self,
1686 id: InstanceId,
1687 ) -> (
1688 Option<&mut GcStore>,
1689 &ModuleRegistry,
1690 Pin<&mut vm::Instance>,
1691 ) {
1692 (
1693 self.gc_store.as_mut(),
1694 &self.modules,
1695 self.instances[id].handle.get_mut(),
1696 )
1697 }
1698
1699 /// Get all instances (ignoring dummy instances) within this store.
1700 pub fn all_instances<'a>(&'a mut self) -> impl ExactSizeIterator<Item = Instance> + 'a {
1701 let instances = self
1702 .instances
1703 .iter()
1704 .filter_map(|(id, inst)| {
1705 if let StoreInstanceKind::Dummy = inst.kind {
1706 None
1707 } else {
1708 Some(id)
1709 }
1710 })
1711 .collect::<Vec<_>>();
1712 instances
1713 .into_iter()
1714 .map(|i| Instance::from_wasmtime(i, self))
1715 }
1716
1717 /// Get all memories (host- or Wasm-defined) within this store.
1718 pub fn all_memories<'a>(&'a self) -> impl Iterator<Item = ExportMemory> + 'a {
1719 // NB: Host-created memories have dummy instances. Therefore, we can get
1720 // all memories in the store by iterating over all instances (including
1721 // dummy instances) and getting each of their defined memories.
1722 let id = self.id();
1723 self.instances
1724 .iter()
1725 .flat_map(move |(_, instance)| instance.handle.get().defined_memories(id))
1726 }
1727
1728 /// Iterate over all tables (host- or Wasm-defined) within this store.
1729 pub fn for_each_table(&mut self, mut f: impl FnMut(&mut Self, Table)) {
1730 // NB: Host-created tables have dummy instances. Therefore, we can get
1731 // all tables in the store by iterating over all instances (including
1732 // dummy instances) and getting each of their defined memories.
1733 for id in self.instances.keys() {
1734 let instance = StoreInstanceId::new(self.id(), id);
1735 for table in 0..self.instance(id).env_module().num_defined_tables() {
1736 let table = DefinedTableIndex::new(table);
1737 f(self, Table::from_raw(instance, table));
1738 }
1739 }
1740 }
1741
1742 /// Iterate over all globals (host- or Wasm-defined) within this store.
1743 pub fn for_each_global(&mut self, mut f: impl FnMut(&mut Self, Global)) {
1744 // First enumerate all the host-created globals.
1745 for global in self.host_globals.keys() {
1746 let global = Global::new_host(self, global);
1747 f(self, global);
1748 }
1749
1750 // Then enumerate all instances' defined globals.
1751 for id in self.instances.keys() {
1752 for index in 0..self.instance(id).env_module().num_defined_globals() {
1753 let index = DefinedGlobalIndex::new(index);
1754 let global = Global::new_instance(self, id, index);
1755 f(self, global);
1756 }
1757 }
1758 }
1759
1760 #[cfg(all(feature = "std", any(unix, windows)))]
1761 pub fn set_signal_handler(&mut self, handler: Option<SignalHandler>) {
1762 self.signal_handler = handler;
1763 }
1764
1765 #[inline]
1766 pub fn vm_store_context(&self) -> &VMStoreContext {
1767 &self.vm_store_context
1768 }
1769
1770 #[inline]
1771 pub fn vm_store_context_mut(&mut self) -> &mut VMStoreContext {
1772 &mut self.vm_store_context
1773 }
1774
1775 /// Attempts to access the GC store that has been previously allocated.
1776 ///
1777 /// This method will return `Some` if the GC store was previously allocated.
1778 /// A `None` return value means either that the GC heap hasn't yet been
1779 /// allocated or that it does not need to be allocated for this store. Note
1780 /// that to require a GC store in a particular situation it's recommended to
1781 /// use [`Self::require_gc_store_mut`] instead.
1782 #[inline]
1783 pub(crate) fn optional_gc_store_mut(&mut self) -> Option<&mut GcStore> {
1784 if cfg!(not(feature = "gc")) || !self.engine.features().gc_types() {
1785 debug_assert!(self.gc_store.is_none());
1786 None
1787 } else {
1788 self.gc_store.as_mut()
1789 }
1790 }
1791
1792 /// Helper to assert that a GC store was previously allocated and is
1793 /// present.
1794 ///
1795 /// # Panics
1796 ///
1797 /// This method will panic if the GC store has not yet been allocated. This
1798 /// should only be used in a context where there's an existing GC reference,
1799 /// for example, or if `ensure_gc_store` has already been called.
1800 #[inline]
1801 #[track_caller]
1802 pub(crate) fn unwrap_gc_store(&self) -> &GcStore {
1803 self.gc_store
1804 .as_ref()
1805 .expect("attempted to access the store's GC heap before it has been allocated")
1806 }
1807
1808 /// Same as [`Self::unwrap_gc_store`], but mutable.
1809 #[inline]
1810 #[track_caller]
1811 pub(crate) fn unwrap_gc_store_mut(&mut self) -> &mut GcStore {
1812 self.gc_store
1813 .as_mut()
1814 .expect("attempted to access the store's GC heap before it has been allocated")
1815 }
1816
1817 /// Returns a mutable reference to the GC store if it has been allocated.
1818 #[inline]
1819 #[cfg(any(feature = "gc-drc", feature = "gc-copying"))]
1820 pub(crate) fn try_gc_store_mut(&mut self) -> Option<&mut GcStore> {
1821 self.gc_store.as_mut()
1822 }
1823
1824 /// Helper function execute a `init_gc_ref` when placing `gc_ref` in `dest`.
1825 ///
1826 /// This avoids allocating `GcStore` where possible.
1827 pub(crate) fn init_gc_ref(
1828 &mut self,
1829 dest: &mut MaybeUninit<Option<VMGcRef>>,
1830 gc_ref: Option<&VMGcRef>,
1831 ) -> Result<()> {
1832 if GcStore::needs_init_barrier(gc_ref) {
1833 self.unwrap_gc_store_mut().init_gc_ref(dest, gc_ref)
1834 } else {
1835 dest.write(gc_ref.map(|r| r.copy_i31()));
1836 Ok(())
1837 }
1838 }
1839
1840 /// Helper function execute a write barrier when placing `gc_ref` in `dest`.
1841 ///
1842 /// This avoids allocating `GcStore` where possible.
1843 pub(crate) fn write_gc_ref(
1844 &mut self,
1845 dest: &mut Option<VMGcRef>,
1846 gc_ref: Option<&VMGcRef>,
1847 ) -> Result<()> {
1848 GcStore::write_gc_ref_optional_store(self.optional_gc_store_mut(), dest, gc_ref)
1849 }
1850
1851 /// Helper function to clone `gc_ref` notably avoiding allocating a
1852 /// `GcStore` where possible.
1853 pub(crate) fn clone_gc_ref(&mut self, gc_ref: &VMGcRef) -> VMGcRef {
1854 if gc_ref.is_i31() {
1855 gc_ref.copy_i31()
1856 } else {
1857 self.unwrap_gc_store_mut().clone_gc_ref(gc_ref)
1858 }
1859 }
1860
1861 pub fn get_fuel(&self) -> Result<u64> {
1862 crate::ensure!(
1863 self.engine().tunables().consume_fuel,
1864 "fuel is not configured in this store"
1865 );
1866 let injected_fuel = unsafe { *self.vm_store_context.fuel_consumed.get() };
1867 Ok(get_fuel(injected_fuel, self.fuel_reserve))
1868 }
1869
1870 pub(crate) fn refuel(&mut self) -> bool {
1871 let injected_fuel = unsafe { &mut *self.vm_store_context.fuel_consumed.get() };
1872 refuel(
1873 injected_fuel,
1874 &mut self.fuel_reserve,
1875 self.fuel_yield_interval,
1876 )
1877 }
1878
1879 pub fn set_fuel(&mut self, fuel: u64) -> Result<()> {
1880 crate::ensure!(
1881 self.engine().tunables().consume_fuel,
1882 "fuel is not configured in this store"
1883 );
1884 let injected_fuel = unsafe { &mut *self.vm_store_context.fuel_consumed.get() };
1885 set_fuel(
1886 injected_fuel,
1887 &mut self.fuel_reserve,
1888 self.fuel_yield_interval,
1889 fuel,
1890 );
1891 Ok(())
1892 }
1893
1894 #[cfg(feature = "async")]
1895 pub fn fuel_async_yield_interval(&mut self, interval: Option<u64>) -> Result<()> {
1896 crate::ensure!(
1897 self.engine().tunables().consume_fuel,
1898 "fuel is not configured in this store"
1899 );
1900 crate::ensure!(
1901 interval != Some(0),
1902 "fuel_async_yield_interval must not be 0"
1903 );
1904
1905 // All future entrypoints must be async to handle the case that fuel
1906 // runs out and an async yield is needed.
1907 self.set_async_required(Asyncness::Yes);
1908
1909 self.fuel_yield_interval = interval.and_then(|i| NonZeroU64::new(i));
1910 // Reset the fuel active + reserve states by resetting the amount.
1911 self.set_fuel(self.get_fuel()?)
1912 }
1913
1914 #[inline]
1915 pub fn signal_handler(&self) -> Option<*const SignalHandler> {
1916 let handler = self.signal_handler.as_ref()?;
1917 Some(handler)
1918 }
1919
1920 #[inline]
1921 pub fn vm_store_context_ptr(&self) -> NonNull<VMStoreContext> {
1922 NonNull::from(&self.vm_store_context)
1923 }
1924
1925 #[inline]
1926 pub fn default_caller(&self) -> NonNull<VMContext> {
1927 self.default_caller_vmctx.as_non_null()
1928 }
1929
1930 #[inline]
1931 pub fn traitobj(&self) -> NonNull<dyn VMStore> {
1932 self.traitobj.0.unwrap()
1933 }
1934
1935 /// Takes the cached `Vec<Val>` stored internally across hostcalls to get
1936 /// used as part of calling the host in a `Func::new` method invocation.
1937 #[inline]
1938 pub fn take_hostcall_val_storage(&mut self) -> Vec<Val> {
1939 mem::take(&mut self.hostcall_val_storage)
1940 }
1941
1942 /// Restores the vector previously taken by `take_hostcall_val_storage`
1943 /// above back into the store, allowing it to be used in the future for the
1944 /// next wasm->host call.
1945 #[inline]
1946 pub fn save_hostcall_val_storage(&mut self, storage: Vec<Val>) {
1947 if storage.capacity() > self.hostcall_val_storage.capacity() {
1948 self.hostcall_val_storage = storage;
1949 }
1950 }
1951
1952 /// Same as `take_hostcall_val_storage`, but for the direction of the host
1953 /// calling wasm.
1954 #[inline]
1955 pub fn take_wasm_val_raw_storage(&mut self) -> TryVec<ValRaw> {
1956 mem::take(&mut self.wasm_val_raw_storage)
1957 }
1958
1959 /// Same as `save_hostcall_val_storage`, but for the direction of the host
1960 /// calling wasm.
1961 #[inline]
1962 pub fn save_wasm_val_raw_storage(&mut self, storage: TryVec<ValRaw>) {
1963 if storage.capacity() > self.wasm_val_raw_storage.capacity() {
1964 self.wasm_val_raw_storage = storage;
1965 }
1966 }
1967
1968 /// Translates a WebAssembly fault at the native `pc` and native `addr` to a
1969 /// WebAssembly-relative fault.
1970 ///
1971 /// This function may abort the process if `addr` is not found to actually
1972 /// reside in any linear memory. In such a situation it means that the
1973 /// segfault was erroneously caught by Wasmtime and is possibly indicative
1974 /// of a code generator bug.
1975 ///
1976 /// This function returns `None` for dynamically-bounds-checked-memories
1977 /// with spectre mitigations enabled since the hardware fault address is
1978 /// always zero in these situations which means that the trapping context
1979 /// doesn't have enough information to report the fault address.
1980 pub(crate) fn wasm_fault(&self, pc: usize, addr: usize) -> Option<vm::WasmFault> {
1981 // There are a few instances where a "close to zero" pointer is loaded
1982 // and we expect that to happen:
1983 //
1984 // * Explicitly bounds-checked memories with spectre-guards enabled will
1985 // cause out-of-bounds accesses to get routed to address 0, so allow
1986 // wasm instructions to fault on the null address.
1987 // * `call_indirect` when invoking a null function pointer may load data
1988 // from the a `VMFuncRef` whose address is null, meaning any field of
1989 // `VMFuncRef` could be the address of the fault.
1990 //
1991 // In these situations where the address is so small it won't be in any
1992 // instance, so skip the checks below.
1993 if addr <= mem::size_of::<VMFuncRef>() {
1994 const _: () = {
1995 // static-assert that `VMFuncRef` isn't too big to ensure that
1996 // it lives solely within the first page as we currently only
1997 // have the guarantee that the first page of memory is unmapped,
1998 // no more.
1999 assert!(mem::size_of::<VMFuncRef>() <= 512);
2000 };
2001 return None;
2002 }
2003
2004 // Search all known instances in this store for this address. Note that
2005 // this is probably not the speediest way to do this. Traps, however,
2006 // are generally not expected to be super fast and additionally stores
2007 // probably don't have all that many instances or memories.
2008 //
2009 // If this loop becomes hot in the future, however, it should be
2010 // possible to precompute maps about linear memories in a store and have
2011 // a quicker lookup.
2012 let mut fault = None;
2013 for (_, instance) in self.instances.iter() {
2014 if let Some(f) = instance.handle.get().wasm_fault(addr) {
2015 assert!(fault.is_none());
2016 fault = Some(f);
2017 }
2018 }
2019 if fault.is_some() {
2020 return fault;
2021 }
2022
2023 cfg_select! {
2024 feature = "std" => {
2025 // With the standard library a rich error can be printed here
2026 // to stderr and the native abort path is used.
2027 eprintln!(
2028 "\
2029Wasmtime caught a segfault for a wasm program because the faulting instruction
2030is allowed to segfault due to how linear memories are implemented. The address
2031that was accessed, however, is not known to any linear memory in use within this
2032Store. This may be indicative of a critical bug in Wasmtime's code generation
2033because all addresses which are known to be reachable from wasm won't reach this
2034message.
2035
2036 pc: 0x{pc:x}
2037 address: 0x{addr:x}
2038
2039This is a possible security issue because WebAssembly has accessed something it
2040shouldn't have been able to. Other accesses may have succeeded and this one just
2041happened to be caught. The process will now be aborted to prevent this damage
2042from going any further and to alert what's going on. If this is a security
2043issue please reach out to the Wasmtime team via its security policy
2044at https://bytecodealliance.org/security.
2045"
2046 );
2047 std::process::abort();
2048 }
2049 panic = "abort" => {
2050 // Without the standard library but with `panic=abort` then
2051 // it's safe to panic as that's known to halt execution. For
2052 // now avoid the above error message as well since without
2053 // `std` it's probably best to be a bit more size-conscious.
2054 let _ = pc;
2055 panic!("invalid fault");
2056 }
2057 _ => {
2058 // Without `std` and with `panic = "unwind"` there's no
2059 // dedicated API to abort the process portably, so manufacture
2060 // this with a double-panic.
2061 let _ = pc;
2062
2063 struct PanicAgainOnDrop;
2064
2065 impl Drop for PanicAgainOnDrop {
2066 fn drop(&mut self) {
2067 panic!("panicking again to trigger a process abort");
2068 }
2069
2070 }
2071
2072 let _bomb = PanicAgainOnDrop;
2073
2074 panic!("invalid fault");
2075 }
2076 }
2077 }
2078
2079 /// Retrieve the store's protection key.
2080 #[inline]
2081 #[cfg(feature = "pooling-allocator")]
2082 pub(crate) fn get_pkey(&self) -> Option<ProtectionKey> {
2083 self.pkey
2084 }
2085
2086 #[cfg(feature = "async")]
2087 pub(crate) fn fiber_async_state_mut(&mut self) -> &mut fiber::AsyncState {
2088 &mut self.async_state
2089 }
2090
2091 #[cfg(feature = "async")]
2092 pub(crate) fn has_pkey(&self) -> bool {
2093 self.pkey.is_some()
2094 }
2095
2096 pub(crate) fn executor(&mut self) -> ExecutorRef<'_> {
2097 match &mut self.executor {
2098 Executor::Interpreter(i) => ExecutorRef::Interpreter(i.as_interpreter_ref()),
2099 #[cfg(has_host_compiler_backend)]
2100 Executor::Native => ExecutorRef::Native,
2101 }
2102 }
2103
2104 #[cfg(feature = "async")]
2105 pub(crate) fn swap_executor(&mut self, executor: &mut Executor) {
2106 mem::swap(&mut self.executor, executor);
2107 }
2108
2109 pub(crate) fn unwinder(&self) -> &'static dyn Unwind {
2110 match &self.executor {
2111 Executor::Interpreter(i) => i.unwinder(),
2112 #[cfg(has_host_compiler_backend)]
2113 Executor::Native => &vm::UnwindHost,
2114 }
2115 }
2116
2117 /// Allocates a new continuation. Note that we currently don't support
2118 /// deallocating them. Instead, all continuations remain allocated
2119 /// throughout the store's lifetime.
2120 #[cfg(feature = "stack-switching")]
2121 pub fn allocate_continuation(&mut self) -> Result<*mut VMContRef> {
2122 // FIXME(frank-emrich) Do we need to pin this?
2123 let mut continuation = Box::new(VMContRef::empty());
2124 let stack_size = self.engine.config().async_stack_size;
2125 let stack = crate::vm::VMContinuationStack::new(stack_size)?;
2126 continuation.stack = stack;
2127 let ptr = continuation.deref_mut() as *mut VMContRef;
2128 self.continuations.push(continuation);
2129 Ok(ptr)
2130 }
2131
2132 /// Constructs and executes an `InstanceAllocationRequest` and pushes the
2133 /// returned instance into the store.
2134 ///
2135 /// This is a helper method for invoking
2136 /// `InstanceAllocator::allocate_module` with the appropriate parameters
2137 /// from this store's own configuration. The `kind` provided is used to
2138 /// distinguish between "real" modules and dummy ones that are synthesized
2139 /// for embedder-created memories, globals, tables, etc. The `kind` will
2140 /// also use a different instance allocator by default, the one passed in,
2141 /// rather than the engine's default allocator.
2142 ///
2143 /// This method will push the instance within `StoreOpaque` onto the
2144 /// `instances` array and return the `InstanceId` which can be use to look
2145 /// it up within the store.
2146 ///
2147 /// # Safety
2148 ///
2149 /// The `imports` provided must be correctly sized/typed for the module
2150 /// being allocated.
2151 pub(crate) async unsafe fn allocate_instance(
2152 &mut self,
2153 limiter: Option<&mut StoreResourceLimiter<'_>>,
2154 kind: AllocateInstanceKind<'_>,
2155 runtime_info: &ModuleRuntimeInfo,
2156 imports: Imports<'_>,
2157 ) -> Result<InstanceId> {
2158 self.instances.reserve(1)?;
2159
2160 let id = self.instances.next_key();
2161
2162 let allocator = match kind {
2163 AllocateInstanceKind::Module(_) => self.engine().allocator(),
2164 AllocateInstanceKind::Dummy { allocator } => allocator,
2165 };
2166 // SAFETY: this function's own contract is the same as
2167 // `allocate_module`, namely the imports provided are valid.
2168 let handle = unsafe {
2169 allocator
2170 .allocate_module(InstanceAllocationRequest {
2171 id,
2172 runtime_info,
2173 imports,
2174 store: self,
2175 limiter,
2176 })
2177 .await?
2178 };
2179
2180 let actual = match kind {
2181 AllocateInstanceKind::Module(module_id) => {
2182 log::trace!(
2183 "Adding instance to store: store={:?}, module={module_id:?}, instance={id:?}",
2184 self.id()
2185 );
2186 self.instances
2187 .push(StoreInstance {
2188 handle,
2189 kind: StoreInstanceKind::Real { module_id },
2190 })
2191 .expect("capacity was reserved above")
2192 }
2193 AllocateInstanceKind::Dummy { .. } => {
2194 log::trace!(
2195 "Adding dummy instance to store: store={:?}, instance={id:?}",
2196 self.id()
2197 );
2198 self.instances
2199 .push(StoreInstance {
2200 handle,
2201 kind: StoreInstanceKind::Dummy,
2202 })
2203 .expect("capacity was reserved above")
2204 }
2205 };
2206
2207 // double-check we didn't accidentally allocate two instances and our
2208 // prediction of what the id would be is indeed the id it should be.
2209 assert_eq!(id, actual);
2210
2211 Ok(id)
2212 }
2213
2214 #[cfg(target_has_atomic = "64")]
2215 pub(crate) fn set_epoch_deadline(&mut self, delta: u64) {
2216 // Set a new deadline based on the "epoch deadline delta".
2217 //
2218 // Also, note that when this update is performed while Wasm is
2219 // on the stack, the Wasm will reload the new value once we
2220 // return into it.
2221 let current_epoch = self.engine().current_epoch();
2222 let epoch_deadline = self.vm_store_context.epoch_deadline.get_mut();
2223 *epoch_deadline = current_epoch + delta;
2224 }
2225
2226 pub(crate) fn get_epoch_deadline(&mut self) -> u64 {
2227 *self.vm_store_context.epoch_deadline.get_mut()
2228 }
2229
2230 #[inline]
2231 pub(crate) fn validate_sync_call(&self) -> Result<()> {
2232 #[cfg(feature = "async")]
2233 if self.async_state.async_required {
2234 bail!("store configuration requires that `*_async` functions are used instead");
2235 }
2236 Ok(())
2237 }
2238
2239 /// Returns whether this store is presently on a fiber and is allowed to
2240 /// block via `block_on` with fibers.
2241 pub(crate) fn can_block(&mut self) -> bool {
2242 #[cfg(feature = "async")]
2243 if true {
2244 return self.fiber_async_state_mut().can_block();
2245 }
2246
2247 false
2248 }
2249
2250 #[cfg(not(feature = "async"))]
2251 pub(crate) fn set_async_required(&mut self, asyncness: Asyncness) {
2252 match asyncness {
2253 Asyncness::No => {}
2254 }
2255 }
2256
2257 #[cfg(any(feature = "async", feature = "gc"))]
2258 pub(crate) async fn yield_now(&self) {
2259 // TODO: Once `Config` has an optional `AsyncFn` field for yielding to the
2260 // current async runtime (e.g. `tokio::task::yield_now`), use that if set;
2261 // otherwise fall back to the runtime-agnostic code.
2262 yield_now().await
2263 }
2264}
2265
2266#[cfg(any(feature = "async", feature = "gc"))]
2267async fn yield_now() {
2268 let mut yielded = false;
2269 future::poll_fn(move |cx| {
2270 if yielded {
2271 Poll::Ready(())
2272 } else {
2273 yielded = true;
2274 cx.waker().wake_by_ref();
2275 Poll::Pending
2276 }
2277 })
2278 .await;
2279}
2280
2281/// Helper parameter to [`StoreOpaque::allocate_instance`].
2282pub(crate) enum AllocateInstanceKind<'a> {
2283 /// An embedder-provided module is being allocated meaning that the default
2284 /// engine's allocator will be used.
2285 Module(RegisteredModuleId),
2286
2287 /// Add a dummy instance that to the store.
2288 ///
2289 /// These are instances that are just implementation details of something
2290 /// else (e.g. host-created memories that are not actually defined in any
2291 /// Wasm module) and therefore shouldn't show up in things like core dumps.
2292 ///
2293 /// A custom, typically OnDemand-flavored, allocator is provided to execute
2294 /// the allocation.
2295 Dummy {
2296 allocator: &'a dyn InstanceAllocator,
2297 },
2298}
2299
2300unsafe impl<T> VMStore for StoreInner<T> {
2301 #[cfg(feature = "component-model-async")]
2302 fn component_async_store(
2303 &mut self,
2304 ) -> &mut dyn crate::runtime::component::VMComponentAsyncStore {
2305 self
2306 }
2307
2308 fn store_opaque(&self) -> &StoreOpaque {
2309 &self.inner
2310 }
2311
2312 fn store_opaque_mut(&mut self) -> &mut StoreOpaque {
2313 &mut self.inner
2314 }
2315
2316 #[cfg(feature = "call-hook")]
2317 fn call_hook(&mut self, s: CallHook) -> Result<()> {
2318 StoreInner::call_hook(self, s)
2319 }
2320
2321 fn resource_limiter_and_store_opaque(
2322 &mut self,
2323 ) -> (Option<StoreResourceLimiter<'_>>, &mut StoreOpaque) {
2324 let (data, limiter, opaque) = self.data_limiter_and_opaque();
2325
2326 let limiter = limiter.map(|l| match l {
2327 ResourceLimiterInner::Sync(s) => StoreResourceLimiter::Sync(s(data)),
2328 #[cfg(feature = "async")]
2329 ResourceLimiterInner::Async(s) => StoreResourceLimiter::Async(s(data)),
2330 });
2331
2332 (limiter, opaque)
2333 }
2334
2335 #[cfg(target_has_atomic = "64")]
2336 fn new_epoch_updated_deadline(&mut self) -> Result<UpdateDeadline> {
2337 // Temporarily take the configured behavior to avoid mutably borrowing
2338 // multiple times.
2339 let mut behavior = self.epoch_deadline_behavior.take();
2340 let update = match &mut behavior {
2341 Some(callback) => callback((&mut *self).as_context_mut()),
2342 None => Ok(UpdateDeadline::Interrupt),
2343 };
2344
2345 // Put back the original behavior which was replaced by `take`.
2346 self.epoch_deadline_behavior = behavior;
2347 update
2348 }
2349
2350 #[cfg(feature = "debug")]
2351 fn block_on_debug_handler(&mut self, event: crate::DebugEvent<'_>) -> crate::Result<()> {
2352 if let Some(handler) = self.debug_handler.take() {
2353 if !self.can_block() {
2354 bail!("could not invoke debug handler without async context");
2355 }
2356 log::trace!("about to raise debug event {event:?}");
2357 StoreContextMut(self).with_blocking(|store, cx| {
2358 cx.block_on(Pin::from(handler.handle(store, event)).as_mut())
2359 })
2360 } else {
2361 Ok(())
2362 }
2363 }
2364}
2365
2366impl<T> StoreInner<T> {
2367 #[cfg(target_has_atomic = "64")]
2368 fn epoch_deadline_trap(&mut self) {
2369 self.epoch_deadline_behavior = None;
2370 }
2371
2372 #[cfg(target_has_atomic = "64")]
2373 fn epoch_deadline_callback(
2374 &mut self,
2375 callback: Box<dyn FnMut(StoreContextMut<T>) -> Result<UpdateDeadline> + Send + Sync>,
2376 ) {
2377 self.epoch_deadline_behavior = Some(callback);
2378 }
2379}
2380
2381impl<T: Default> Default for Store<T> {
2382 fn default() -> Store<T> {
2383 Store::new(&Engine::default(), T::default())
2384 }
2385}
2386
2387impl<T: fmt::Debug> fmt::Debug for Store<T> {
2388 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2389 let inner = &**self.inner as *const StoreInner<T>;
2390 f.debug_struct("Store")
2391 .field("inner", &inner)
2392 .field("data", self.inner.data())
2393 .finish()
2394 }
2395}
2396
2397impl<T> Drop for Store<T> {
2398 fn drop(&mut self) {
2399 self.run_manual_drop_routines();
2400
2401 // For documentation on this `unsafe`, see `into_data`.
2402 unsafe {
2403 ManuallyDrop::drop(&mut self.inner.data_no_provenance);
2404 ManuallyDrop::drop(&mut self.inner);
2405 }
2406 }
2407}
2408
2409impl Drop for StoreOpaque {
2410 fn drop(&mut self) {
2411 // NB it's important that this destructor does not access `self.data`.
2412 // That is deallocated by `Drop for Store<T>` above.
2413
2414 unsafe {
2415 let allocator = self.engine.allocator();
2416 let ondemand = OnDemandInstanceAllocator::default();
2417 let store_id = self.id();
2418
2419 #[cfg(feature = "gc")]
2420 if let Some(mut gc_store) = self.gc_store.take() {
2421 let gc_alloc_index = gc_store.allocation_index;
2422 log::trace!("store {store_id:?} is deallocating GC heap {gc_alloc_index:?}");
2423 debug_assert!(self.engine.features().gc_types());
2424 let mem = gc_store.gc_heap.detach();
2425 let mem_alloc_index =
2426 allocator.deallocate_gc_heap(gc_alloc_index, gc_store.gc_heap);
2427 allocator.deallocate_memory(None, mem_alloc_index, mem);
2428 }
2429
2430 for (id, instance) in self.instances.iter_mut() {
2431 log::trace!("store {store_id:?} is deallocating {id:?}");
2432 let allocator = match instance.kind {
2433 StoreInstanceKind::Dummy => &ondemand,
2434 _ => allocator,
2435 };
2436 allocator.deallocate_module(&mut instance.handle);
2437 }
2438
2439 self.store_data.decrement_allocator_resources(allocator);
2440 }
2441 }
2442}
2443
2444#[cfg_attr(
2445 not(any(feature = "gc", feature = "async")),
2446 // NB: Rust 1.89, current stable, does not fire this lint. Rust 1.90,
2447 // however, does, so use #[allow] until our MSRV is 1.90.
2448 allow(dead_code, reason = "don't want to put #[cfg] on all impls below too")
2449)]
2450pub(crate) trait AsStoreOpaque {
2451 fn as_store_opaque(&mut self) -> &mut StoreOpaque;
2452}
2453
2454impl AsStoreOpaque for StoreOpaque {
2455 fn as_store_opaque(&mut self) -> &mut StoreOpaque {
2456 self
2457 }
2458}
2459
2460impl AsStoreOpaque for dyn VMStore {
2461 fn as_store_opaque(&mut self) -> &mut StoreOpaque {
2462 self
2463 }
2464}
2465
2466impl<T: 'static> AsStoreOpaque for Store<T> {
2467 fn as_store_opaque(&mut self) -> &mut StoreOpaque {
2468 &mut self.inner.inner
2469 }
2470}
2471
2472impl<T: 'static> AsStoreOpaque for StoreInner<T> {
2473 fn as_store_opaque(&mut self) -> &mut StoreOpaque {
2474 self
2475 }
2476}
2477
2478impl<T: AsStoreOpaque + ?Sized> AsStoreOpaque for &mut T {
2479 fn as_store_opaque(&mut self) -> &mut StoreOpaque {
2480 T::as_store_opaque(self)
2481 }
2482}
2483
2484/// Helper enum to indicate, in some function contexts, whether `async` should
2485/// be taken advantage of or not.
2486///
2487/// This is used throughout Wasmtime where internal functions are all `async`
2488/// but external functions might be either sync or `async`. If the external
2489/// function is sync, then internally Wasmtime shouldn't yield as it won't do
2490/// anything. If the external function is `async`, however, yields are fine.
2491///
2492/// An example of this is GC. Right now GC will cooperatively yield after phases
2493/// of GC have passed, but this cooperative yielding is only enabled with
2494/// `Asyncness::Yes`.
2495///
2496/// This enum is additionally conditionally defined such that `Yes` is only
2497/// present in `async`-enabled builds. That ensures that this compiles down to a
2498/// zero-sized type in `async`-disabled builds in case that interests embedders.
2499#[derive(PartialEq, Eq, Copy, Clone)]
2500pub enum Asyncness {
2501 /// Don't do async things, don't yield, etc. It's ok to execute an `async`
2502 /// function, but it should be validated ahead of time that when doing so a
2503 /// yield isn't possible (e.g. `validate_sync_*` methods on Store.
2504 No,
2505
2506 /// Async things is OK. This should only be used when the API entrypoint is
2507 /// itself `async`.
2508 #[cfg(feature = "async")]
2509 Yes,
2510}
2511
2512impl core::ops::BitOr for Asyncness {
2513 type Output = Self;
2514
2515 fn bitor(self, rhs: Self) -> Self::Output {
2516 match (self, rhs) {
2517 (Asyncness::No, Asyncness::No) => Asyncness::No,
2518 #[cfg(feature = "async")]
2519 (Asyncness::Yes, _) | (_, Asyncness::Yes) => Asyncness::Yes,
2520 }
2521 }
2522}
2523
2524#[cfg(test)]
2525mod tests {
2526 use super::*;
2527
2528 struct FuelTank {
2529 pub consumed_fuel: i64,
2530 pub reserve_fuel: u64,
2531 pub yield_interval: Option<NonZeroU64>,
2532 }
2533
2534 impl FuelTank {
2535 fn new() -> Self {
2536 FuelTank {
2537 consumed_fuel: 0,
2538 reserve_fuel: 0,
2539 yield_interval: None,
2540 }
2541 }
2542 fn get_fuel(&self) -> u64 {
2543 get_fuel(self.consumed_fuel, self.reserve_fuel)
2544 }
2545 fn refuel(&mut self) -> bool {
2546 refuel(
2547 &mut self.consumed_fuel,
2548 &mut self.reserve_fuel,
2549 self.yield_interval,
2550 )
2551 }
2552 fn set_fuel(&mut self, fuel: u64) {
2553 set_fuel(
2554 &mut self.consumed_fuel,
2555 &mut self.reserve_fuel,
2556 self.yield_interval,
2557 fuel,
2558 );
2559 }
2560 }
2561
2562 #[test]
2563 fn smoke() {
2564 let mut tank = FuelTank::new();
2565 tank.set_fuel(10);
2566 assert_eq!(tank.consumed_fuel, -10);
2567 assert_eq!(tank.reserve_fuel, 0);
2568
2569 tank.yield_interval = NonZeroU64::new(10);
2570 tank.set_fuel(25);
2571 assert_eq!(tank.consumed_fuel, -10);
2572 assert_eq!(tank.reserve_fuel, 15);
2573 }
2574
2575 #[test]
2576 fn does_not_lose_precision() {
2577 let mut tank = FuelTank::new();
2578 tank.set_fuel(u64::MAX);
2579 assert_eq!(tank.get_fuel(), u64::MAX);
2580
2581 tank.set_fuel(i64::MAX as u64);
2582 assert_eq!(tank.get_fuel(), i64::MAX as u64);
2583
2584 tank.set_fuel(i64::MAX as u64 + 1);
2585 assert_eq!(tank.get_fuel(), i64::MAX as u64 + 1);
2586 }
2587
2588 #[test]
2589 fn yielding_does_not_lose_precision() {
2590 let mut tank = FuelTank::new();
2591
2592 tank.yield_interval = NonZeroU64::new(10);
2593 tank.set_fuel(u64::MAX);
2594 assert_eq!(tank.get_fuel(), u64::MAX);
2595 assert_eq!(tank.consumed_fuel, -10);
2596 assert_eq!(tank.reserve_fuel, u64::MAX - 10);
2597
2598 tank.yield_interval = NonZeroU64::new(u64::MAX);
2599 tank.set_fuel(u64::MAX);
2600 assert_eq!(tank.get_fuel(), u64::MAX);
2601 assert_eq!(tank.consumed_fuel, -i64::MAX);
2602 assert_eq!(tank.reserve_fuel, u64::MAX - (i64::MAX as u64));
2603
2604 tank.yield_interval = NonZeroU64::new((i64::MAX as u64) + 1);
2605 tank.set_fuel(u64::MAX);
2606 assert_eq!(tank.get_fuel(), u64::MAX);
2607 assert_eq!(tank.consumed_fuel, -i64::MAX);
2608 assert_eq!(tank.reserve_fuel, u64::MAX - (i64::MAX as u64));
2609 }
2610
2611 #[test]
2612 fn refueling() {
2613 // It's possible to fuel to have consumed over the limit as some instructions can consume
2614 // multiple units of fuel at once. Refueling should be strict in it's consumption and not
2615 // add more fuel than there is.
2616 let mut tank = FuelTank::new();
2617
2618 tank.yield_interval = NonZeroU64::new(10);
2619 tank.reserve_fuel = 42;
2620 tank.consumed_fuel = 4;
2621 assert!(tank.refuel());
2622 assert_eq!(tank.reserve_fuel, 28);
2623 assert_eq!(tank.consumed_fuel, -10);
2624
2625 tank.yield_interval = NonZeroU64::new(1);
2626 tank.reserve_fuel = 8;
2627 tank.consumed_fuel = 4;
2628 assert_eq!(tank.get_fuel(), 4);
2629 assert!(tank.refuel());
2630 assert_eq!(tank.reserve_fuel, 3);
2631 assert_eq!(tank.consumed_fuel, -1);
2632 assert_eq!(tank.get_fuel(), 4);
2633
2634 tank.yield_interval = NonZeroU64::new(10);
2635 tank.reserve_fuel = 3;
2636 tank.consumed_fuel = 4;
2637 assert_eq!(tank.get_fuel(), 0);
2638 assert!(!tank.refuel());
2639 assert_eq!(tank.reserve_fuel, 3);
2640 assert_eq!(tank.consumed_fuel, 4);
2641 assert_eq!(tank.get_fuel(), 0);
2642 }
2643
2644 #[test]
2645 fn store_data_provenance() {
2646 // Test that we juggle pointer provenance and all that correctly, and
2647 // miri is happy with everything, while allowing both Rust code and
2648 // "Wasm" to access and modify the store's `T` data. Note that this is
2649 // not actually Wasm mutating the store data here because compiling Wasm
2650 // under miri is way too slow.
2651
2652 unsafe fn run_wasm(store: &mut Store<u32>) {
2653 let ptr = store
2654 .inner
2655 .inner
2656 .vm_store_context
2657 .store_data
2658 .as_ptr()
2659 .cast::<u32>();
2660 unsafe { *ptr += 1 }
2661 }
2662
2663 let engine = Engine::default();
2664 let mut store = Store::new(&engine, 0_u32);
2665
2666 assert_eq!(*store.data(), 0);
2667 *store.data_mut() += 1;
2668 assert_eq!(*store.data(), 1);
2669 unsafe { run_wasm(&mut store) }
2670 assert_eq!(*store.data(), 2);
2671 *store.data_mut() += 1;
2672 assert_eq!(*store.data(), 3);
2673 }
2674}