Struct wasmtime::Store[][src]

pub struct Store { /* fields omitted */ }

A Store is a collection of WebAssembly instances and host-defined items.

All WebAssembly instances and items will be attached to and refer to a Store. For example instances, functions, globals, and tables are all attached to a Store. Instances are created by instantiating a Module within a Store.

Store is not thread-safe and cannot be sent to other threads. All items which refer to a Store additionally are not threadsafe and can only be used on the original thread that they were created on.

A Store is not intended to be a long-lived object in a program. No form of GC is implemented at this time so once an instance is created within a Store it will not be deallocated until all references to the Store have gone away (this includes all references to items in the store). This makes Store unsuitable for creating an unbounded number of instances in it because Store will never release this memory. It’s instead recommended to have a long-lived Engine and instead create a Store for a more scoped portion of your application.

Stores and Clone

Using clone on a Store is a cheap operation. It will not create an entirely new store, but rather just a new reference to the existing object. In other words it’s a shallow copy, not a deep copy.

Stores and Default

You can create a store with default configuration settings using Store::default(). This will create a brand new Engine with default ocnfiguration (see Config for more information).

Implementations

impl Store[src]

pub fn new(engine: &Engine) -> Store[src]

Creates a new store to be associated with the given Engine.

Note that this Store cannot be used with asynchronous host calls nor can it be used to call functions asynchronously. For that you’ll want to use Store::new_async.

pub fn new_async(engine: &Engine) -> Store[src]

This is supported on crate feature async only.

Creates a new async store to be associated with the given Engine.

The returned store can optionally define host functions with async. Instances created and functions called within the returned Store must be called through their asynchronous APIs, however. For example using Func::call will panic in the returned store.

Asynchronous Wasm

WebAssembly does not currently have a way to specify at the bytecode level what is and isn’t async. Host-defined functions, however, may be defined as async. WebAssembly imports always appear synchronous, which gives rise to a bit of an impedence mismatch here. To solve this Wasmtime supports “asynchronous stores” which enables calling these asynchronous functions in a way that looks synchronous to the executing WebAssembly code.

An asynchronous store must always invoke wasm code asynchronously, meaning we’ll always represent its computation as a Future. The poll method of the futures returned by Wasmtime will perform the actual work of calling the WebAssembly. Wasmtime won’t manage its own thread pools or similar, that’s left up to the embedder.

To implement futures in a way that WebAssembly sees asynchronous host functions as synchronous, all async Wasmtime futures will execute on a separately allocated native stack from the thread otherwise executing Wasmtime. This separate native stack can then be switched to and from. Using this whenever an async host function returns a future that resolves to Pending we switch away from the temporary stack back to the main stack and propagate the Pending status.

In general it’s encouraged that the integration with async and wasmtime is designed early on in your embedding of Wasmtime to ensure that it’s planned that WebAssembly executes in the right context of your application.

Execution in poll

The Future::poll method is the main driving force behind Rust’s futures. That method’s own documentation states “an implementation of poll should strive to return quickly, and should not block”. This, however, can be at odds with executing WebAssembly code as part of the poll method itself. If your WebAssembly is untrusted then this could allow the poll method to take arbitrarily long in the worst case, likely blocking all other asynchronous tasks.

To remedy this situation you have a two possible ways to solve this:

  • First you can spawn futures into a thread pool. Care must be taken for this because Wasmtime futures are not Send or Sync. If you ensure that the entire state of a Store is wrapped up in a single future, though, you can send the whole future at once to a separate thread. By doing this in a thread pool you are relaxing the requirement that Future::poll must be fast because your future is executing on a separate thread. This strategy, however, would likely still require some form of cancellation via Store::interrupt_handle to ensure wasm doesn’t take too long to execute.

  • Alternatively you can enable the Config::consume_fuel method as well as Store::out_of_fuel_async_yield When doing so this will configure Wasmtime futures to yield periodically while they’re executing WebAssembly code. After consuming the specified amount of fuel wasm futures will return Poll::Pending from their poll method, and will get automatically re-polled later. This enables the Future::poll method to take roughly a fixed amount of time since fuel is guaranteed to get consumed while wasm is executing. Note that to prevent infinite execution of wasm you’ll still need to use Store::interrupt_handle.

In either case special care needs to be taken when integrating asynchronous wasm into your application. You should carefully plan where WebAssembly will execute and what compute resources will be allotted to it. If Wasmtime doesn’t support exactly what you’d like just yet, please feel free to open an issue!

pub fn engine(&self) -> &Engine[src]

Returns the Engine that this store is associated with.

pub fn same(a: &Store, b: &Store) -> bool[src]

Returns whether the stores a and b refer to the same underlying Store.

Because the Store type is reference counted multiple clones may point to the same underlying storage, and this method can be used to determine whether two stores are indeed the same.

pub fn interrupt_handle(&self) -> Result<InterruptHandle>[src]

Creates an InterruptHandle which can be used to interrupt the execution of instances within this Store.

An InterruptHandle handle is a mechanism of ensuring that guest code doesn’t execute for too long. For example it’s used to prevent wasm programs for executing infinitely in infinite loops or recursive call chains.

The InterruptHandle type is sendable to other threads so you can interact with it even while the thread with this Store is executing wasm code.

There’s one method on an interrupt handle: InterruptHandle::interrupt. This method is used to generate an interrupt and cause wasm code to exit “soon”.

When are interrupts delivered?

The term “interrupt” here refers to one of two different behaviors that are interrupted in wasm:

  • The head of every loop in wasm has a check to see if it’s interrupted.
  • The prologue of every function has a check to see if it’s interrupted.

This interrupt mechanism makes no attempt to signal interrupts to native code. For example if a host function is blocked, then sending an interrupt will not interrupt that operation.

Interrupts are consumed as soon as possible when wasm itself starts executing. This means that if you interrupt wasm code then it basically guarantees that the next time wasm is executing on the target thread it will return quickly (either normally if it were already in the process of returning or with a trap from the interrupt). Once an interrupt trap is generated then an interrupt is consumed, and further execution will not be interrupted (unless another interrupt is set).

When implementing interrupts you’ll want to ensure that the delivery of interrupts into wasm code is also handled in your host imports and functionality. Host functions need to either execute for bounded amounts of time or you’ll need to arrange for them to be interrupted as well.

Return Value

This function returns a Result since interrupts are not always enabled. Interrupts are enabled via the Config::interruptable method, and if this store’s Config hasn’t been configured to enable interrupts then an error is returned.

Examples

// Enable interruptable code via `Config` and then create an interrupt
// handle which we'll use later to interrupt running code.
let engine = Engine::new(Config::new().interruptable(true));
let store = Store::new(&engine);
let interrupt_handle = store.interrupt_handle()?;

// Compile and instantiate a small example with an infinite loop.
let module = Module::new(&engine, r#"
    (func (export "run") (loop br 0))
"#)?;
let instance = Instance::new(&store, &module, &[])?;
let run = instance
    .get_func("run")
    .ok_or(anyhow::format_err!("failed to find `run` function export"))?
    .get0::<()>()?;

// Spin up a thread to send us an interrupt in a second
std::thread::spawn(move || {
    std::thread::sleep(std::time::Duration::from_secs(1));
    interrupt_handle.interrupt();
});

let trap = run().unwrap_err();
assert!(trap.to_string().contains("wasm trap: interrupt"));

pub fn gc(&self)[src]

Perform garbage collection of ExternRefs.

pub fn fuel_consumed(&self) -> Option<u64>[src]

Returns the amount of fuel consumed by this store’s execution so far.

If fuel consumption is not enabled via Config::consume_fuel then this function will return None. Also note that fuel, if enabled, must be originally configured via Store::add_fuel.

pub fn add_fuel(&self, fuel: u64) -> Result<()>[src]

Adds fuel to this Store for wasm to consume while executing.

For this method to work fuel consumption must be enabled via Config::consume_fuel. By default a Store starts with 0 fuel for wasm to execute with (meaning it will immediately trap). This function must be called for the store to have some fuel to allow WebAssembly to execute.

Note that at this time when fuel is entirely consumed it will cause wasm to trap. More usages of fuel are planned for the future.

Panics

This function will panic if the store’s Config did not have fuel consumption enabled.

pub fn out_of_fuel_trap(&self)[src]

Configures a Store to generate a Trap whenever it runs out of fuel.

When a Store is configured to consume fuel with Config::consume_fuel this method will configure what happens when fuel runs out. Specifically a WebAssembly trap will be raised and the current execution of WebAssembly will be aborted.

This is the default behavior for running out of fuel.

pub fn out_of_fuel_async_yield(&self, injection_count: u32, fuel_to_inject: u64)[src]

Configures a Store to yield execution of async WebAssembly code periodically.

When a Store is configured to consume fuel with Config::consume_fuel this method will configure what happens when fuel runs out. Specifically executing WebAssembly will be suspended and control will be yielded back to the caller. This is only suitable with use of async stores because only then are futures used and yields are possible.

The purpose of this behavior is to ensure that futures which represent execution of WebAssembly do not execute too long inside their Future::poll method. This allows for some form of cooperative multitasking where WebAssembly will voluntarily yield control periodically (based on fuel consumption) back to the running thread.

Note that futures returned by this crate will automatically flag themselves to get re-polled if a yield happens. This means that WebAssembly will continue to execute, just after giving the host an opportunity to do something else.

The fuel_to_inject parameter indicates how much fuel should be automatically re-injected after fuel runs out. This is how much fuel will be consumed between yields of an async future.

The injection_count parameter indicates how many times this fuel will be injected. Multiplying the two parameters is the total amount of fuel this store is allowed before wasm traps.

Panics

This method will panic if it is not called on an async store.

Trait Implementations

impl Clone for Store[src]

impl Debug for Store[src]

impl Default for Store[src]

impl StoreExt for Store[src]

impl TrapInfo for Store[src]

Auto Trait Implementations

impl !RefUnwindSafe for Store

impl !Send for Store

impl !Sync for Store

impl Unpin for Store

impl !UnwindSafe for Store

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

impl<T> Same<T> for T

type Output = T

Should always be Self

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.