Struct Config
pub struct Config { /* private fields */ }
Expand description
Global configuration options used to create an Engine
and customize its behavior.
This structure exposed a builder-like interface and is primarily consumed by
Engine::new()
.
The validation of Config
is deferred until the engine is being built, thus
a problematic config may cause Engine::new
to fail.
§Defaults
The Default
trait implementation and the return value from
Config::new()
are the same and represent the default set of
configuration for an engine. The exact set of defaults will differ based on
properties such as enabled Cargo features at compile time and the configured
target (see Config::target
). Configuration options document their
default values and what the conditional value of the default is where
applicable.
Implementations§
§impl Config
impl Config
pub fn target(&mut self, target: &str) -> Result<&mut Config, Error>
pub fn target(&mut self, target: &str) -> Result<&mut Config, Error>
Configures the target platform of this Config
.
This method is used to configure the output of compilation in an
Engine
. This can be used, for example, to
cross-compile from one platform to another. By default, the host target
triple is used meaning compiled code is suitable to run on the host.
Note that the Module
type can only be created if the
target configured here matches the host. Otherwise if a cross-compile is
being performed where the host doesn’t match the target then
Engine::precompile_module
must be
used instead.
Target-specific flags (such as CPU features) will not be inferred by
default for the target when one is provided here. This means that this
can also be used, for example, with the host architecture to disable all
host-inferred feature flags. Configuring target-specific flags can be
done with Config::cranelift_flag_set
and
Config::cranelift_flag_enable
.
§Errors
This method will error if the given target triple is not supported.
pub fn enable_incremental_compilation(
&mut self,
cache_store: Arc<dyn CacheStore>,
) -> Result<&mut Config, Error>
pub fn enable_incremental_compilation( &mut self, cache_store: Arc<dyn CacheStore>, ) -> Result<&mut Config, Error>
Enables the incremental compilation cache in Cranelift, using the provided CacheStore
backend for storage.
pub fn async_support(&mut self, enable: bool) -> &mut Config
pub fn async_support(&mut self, enable: bool) -> &mut Config
Whether or not to enable support for asynchronous functions in Wasmtime.
When enabled, the config can optionally define host functions with async
.
Instances created and functions called with this Config
must be called
through their asynchronous APIs, however. For example using
Func::call
will panic when used with this config.
§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 impedance mismatch here. To solve this
Wasmtime supports “asynchronous configs” which enables calling these
asynchronous functions in a way that looks synchronous to the executing
WebAssembly code.
An asynchronous config 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 a few possible ways to solve this:
-
The most efficient solution is to enable
Config::epoch_interruption
in conjunction withcrate::Store::epoch_deadline_async_yield_and_update
. Coupled with periodic calls tocrate::Engine::increment_epoch
this will cause executing WebAssembly to periodically yield back according to the epoch configuration settings. This enablesFuture::poll
to take at most a certain amount of time according to epoch configuration settings and when increments happen. The benefit of this approach is that the instrumentation in compiled code is quite lightweight, but a downside can be that the scheduling is somewhat nondeterministic since increments are usually timer-based which are not always deterministic.Note that to prevent infinite execution of wasm it’s recommended to place a timeout on the entire future representing executing wasm code and the periodic yields with epochs should ensure that when the timeout is reached it’s appropriately recognized.
-
Alternatively you can enable the
Config::consume_fuel
method as well ascrate::Store::fuel_async_yield_interval
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 returnPoll::Pending
from theirpoll
method, and will get automatically re-polled later. This enables theFuture::poll
method to take roughly a fixed amount of time since fuel is guaranteed to get consumed while wasm is executing. Unlike epoch-based preemption this is deterministic since wasm always consumes a fixed amount of fuel per-operation. The downside of this approach, however, is that the compiled code instrumentation is significantly more expensive than epoch checks.Note that to prevent infinite execution of wasm it’s recommended to place a timeout on the entire future representing executing wasm code and the periodic yields with epochs should ensure that when the timeout is reached it’s appropriately recognized.
In all cases 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 debug_info(&mut self, enable: bool) -> &mut Config
pub fn debug_info(&mut self, enable: bool) -> &mut Config
Configures whether DWARF debug information will be emitted during compilation.
Note that the debug-builtins
compile-time Cargo feature must also be
enabled for native debuggers such as GDB or LLDB to be able to debug
guest WebAssembly programs.
By default this option is false
.
Note Enabling this option is not compatible with the Winch compiler.
pub fn wasm_backtrace(&mut self, enable: bool) -> &mut Config
pub fn wasm_backtrace(&mut self, enable: bool) -> &mut Config
Configures whether WasmBacktrace
will be present in the context of
errors returned from Wasmtime.
A backtrace may be collected whenever an error is returned from a host function call through to WebAssembly or when WebAssembly itself hits a trap condition, such as an out-of-bounds memory access. This flag indicates, in these conditions, whether the backtrace is collected or not.
Currently wasm backtraces are implemented through frame pointer walking. This means that collecting a backtrace is expected to be a fast and relatively cheap operation. Additionally backtrace collection is suitable in concurrent environments since one thread capturing a backtrace won’t block other threads.
Collected backtraces are attached via anyhow::Error::context
to
errors returned from host functions. The WasmBacktrace
type can be
acquired via anyhow::Error::downcast_ref
to inspect the backtrace.
When this option is disabled then this context is never applied to
errors coming out of wasm.
This option is true
by default.
pub fn wasm_backtrace_details(
&mut self,
enable: WasmBacktraceDetails,
) -> &mut Config
pub fn wasm_backtrace_details( &mut self, enable: WasmBacktraceDetails, ) -> &mut Config
Configures whether backtraces in Trap
will parse debug info in the wasm file to
have filename/line number information.
When enabled this will causes modules to retain debugging information found in wasm binaries. This debug information will be used when a trap happens to symbolicate each stack frame and attempt to print a filename/line number for each wasm frame in the stack trace.
By default this option is WasmBacktraceDetails::Environment
, meaning
that wasm will read WASMTIME_BACKTRACE_DETAILS
to indicate whether
details should be parsed. Note that the std
feature of this crate must
be active to read environment variables, otherwise this is disabled by
default.
pub fn native_unwind_info(&mut self, enable: bool) -> &mut Config
pub fn native_unwind_info(&mut self, enable: bool) -> &mut Config
Configures whether to generate native unwind information
(e.g. .eh_frame
on Linux).
This configuration option only exists to help third-party stack
capturing mechanisms, such as the system’s unwinder or the backtrace
crate, determine how to unwind through Wasm frames. It does not affect
whether Wasmtime can capture Wasm backtraces or not. The presence of
WasmBacktrace
is controlled by the Config::wasm_backtrace
option.
Native unwind information is included:
- When targeting Windows, since the Windows ABI requires it.
- By default.
pub fn consume_fuel(&mut self, enable: bool) -> &mut Config
pub fn consume_fuel(&mut self, enable: bool) -> &mut Config
Configures whether execution of WebAssembly will “consume fuel” to either halt or yield execution as desired.
This can be used to deterministically prevent infinitely-executing
WebAssembly code by instrumenting generated code to consume fuel as it
executes. When fuel runs out a trap is raised, however Store
can be
configured to yield execution periodically via
crate::Store::fuel_async_yield_interval
.
Note that a Store
starts with no fuel, so if you enable this option
you’ll have to be sure to pour some fuel into Store
before
executing some code.
By default this option is false
.
Note Enabling this option is not compatible with the Winch compiler.
pub fn epoch_interruption(&mut self, enable: bool) -> &mut Config
pub fn epoch_interruption(&mut self, enable: bool) -> &mut Config
Enables epoch-based interruption.
When executing code in async mode, we sometimes want to
implement a form of cooperative timeslicing: long-running Wasm
guest code should periodically yield to the executor
loop. This yielding could be implemented by using “fuel” (see
consume_fuel
). However, fuel
instrumentation is somewhat expensive: it modifies the
compiled form of the Wasm code so that it maintains a precise
instruction count, frequently checking this count against the
remaining fuel. If one does not need this precise count or
deterministic interruptions, and only needs a periodic
interrupt of some form, then It would be better to have a more
lightweight mechanism.
Epoch-based interruption is that mechanism. There is a global
“epoch”, which is a counter that divides time into arbitrary
periods (or epochs). This counter lives on the
Engine
and can be incremented by calling
Engine::increment_epoch
.
Epoch-based instrumentation works by setting a “deadline
epoch”. The compiled code knows the deadline, and at certain
points, checks the current epoch against that deadline. It
will yield if the deadline has been reached.
The idea is that checking an infrequently-changing counter is cheaper than counting and frequently storing a precise metric (instructions executed) locally. The interruptions are not deterministic, but if the embedder increments the epoch in a periodic way (say, every regular timer tick by a thread or signal handler), then we can ensure that all async code will yield to the executor within a bounded time.
The deadline check cannot be avoided by malicious wasm code. It is safe to use epoch deadlines to limit the execution time of untrusted code.
The Store
tracks the deadline, and controls
what happens when the deadline is reached during
execution. Several behaviors are possible:
-
Trap if code is executing when the epoch deadline is met. See
Store::epoch_deadline_trap
. -
Call an arbitrary function. This function may chose to trap or increment the epoch. See
Store::epoch_deadline_callback
. -
Yield to the executor loop, then resume when the future is next polled. See
Store::epoch_deadline_async_yield_and_update
.
Trapping is the default. The yielding behaviour may be used for the timeslicing behavior described above.
This feature is available with or without async support. However, without async support, the timeslicing behaviour is not available. This means epoch-based interruption can only serve as a simple external-interruption mechanism.
An initial deadline must be set before executing code by calling
Store::set_epoch_deadline
. If this
deadline is not configured then wasm will immediately trap.
§Interaction with blocking host calls
Epochs (and fuel) do not assist in handling WebAssembly code blocked in
a call to the host. For example if the WebAssembly function calls
wasi:io/poll/poll
to sleep epochs will not assist in waking this up or
timing it out. Epochs intentionally only affect running WebAssembly code
itself and it’s left to the embedder to determine how best to wake up
indefinitely blocking code in the host.
The typical solution for this, however, is to use
Config::async_support(true)
and the async
variant of WASI host functions. This models computation as a Rust
Future
which means that when blocking happens the future is only
suspended and control yields back to the main event loop. This gives the
embedder the opportunity to use tokio::time::timeout
for example on a
wasm computation and have the desired effect of cancelling a blocking
operation when a timeout expires.
§When to use fuel vs. epochs
In general, epoch-based interruption results in faster execution. This difference is sometimes significant: in some measurements, up to 2-3x. This is because epoch-based interruption does less work: it only watches for a global rarely-changing counter to increment, rather than keeping a local frequently-changing counter and comparing it to a deadline.
Fuel, in contrast, should be used when deterministic yielding or trapping is needed. For example, if it is required that the same function call with the same starting state will always either complete or trap with an out-of-fuel error, deterministically, then fuel with a fixed bound should be used.
Note Enabling this option is not compatible with the Winch compiler.
§See Also
pub fn max_wasm_stack(&mut self, size: usize) -> &mut Config
pub fn max_wasm_stack(&mut self, size: usize) -> &mut Config
Configures the maximum amount of stack space available for executing WebAssembly code.
WebAssembly has well-defined semantics on stack overflow. This is intended to be a knob which can help configure how much stack space wasm execution is allowed to consume. Note that the number here is not super-precise, but rather wasm will take at most “pretty close to this much” stack space.
If a wasm call (or series of nested wasm calls) take more stack space
than the size
specified then a stack overflow trap will be raised.
Caveat: this knob only limits the stack space consumed by wasm code. More importantly, it does not ensure that this much stack space is available on the calling thread stack. Exhausting the thread stack typically leads to an abort of the process.
Here are some examples of how that could happen:
-
Let’s assume this option is set to 2 MiB and then a thread that has a stack with 512 KiB left.
If wasm code consumes more than 512 KiB then the process will be aborted.
-
Assuming the same conditions, but this time wasm code does not consume any stack but calls into a host function. The host function consumes more than 512 KiB of stack space. The process will be aborted.
There’s another gotcha related to recursive calling into wasm: the stack space consumed by a host function is counted towards this limit. The host functions are not prevented from consuming more than this limit. However, if the host function that used more than this limit and called back into wasm, then the execution will trap immediately because of stack overflow.
When the async
feature is enabled, this value cannot exceed the
async_stack_size
option. Be careful not to set this value too close
to async_stack_size
as doing so may limit how much stack space
is available for host functions.
By default this option is 512 KiB.
§Errors
The Engine::new
method will fail if the size
specified here is
either 0 or larger than the Config::async_stack_size
configuration.
pub fn async_stack_size(&mut self, size: usize) -> &mut Config
pub fn async_stack_size(&mut self, size: usize) -> &mut Config
Configures the size of the stacks used for asynchronous execution.
This setting configures the size of the stacks that are allocated for
asynchronous execution. The value cannot be less than max_wasm_stack
.
The amount of stack space guaranteed for host functions is
async_stack_size - max_wasm_stack
, so take care not to set these two values
close to one another; doing so may cause host functions to overflow the
stack and abort the process.
By default this option is 2 MiB.
§Errors
The Engine::new
method will fail if the value for this option is
smaller than the Config::max_wasm_stack
option.
pub fn wasm_tail_call(&mut self, enable: bool) -> &mut Config
pub fn wasm_tail_call(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly tail calls proposal will be enabled for compilation or not.
The WebAssembly tail calls proposal introduces the return_call
and
return_call_indirect
instructions. These instructions allow for Wasm
programs to implement some recursive algorithms with O(1) stack space
usage.
This is true
by default except when the Winch compiler is enabled.
pub fn wasm_custom_page_sizes(&mut self, enable: bool) -> &mut Config
pub fn wasm_custom_page_sizes(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly custom-page-sizes proposal will be enabled for compilation or not.
The WebAssembly custom-page-sizes proposal allows a memory to customize its page sizes. By default, Wasm page sizes are 64KiB large. This proposal allows the memory to opt into smaller page sizes instead, allowing Wasm to run in environments with less than 64KiB RAM available, for example.
Note that the page size is part of the memory’s type, and because different memories may have different types, they may also have different page sizes.
Currently the only valid page sizes are 64KiB (the default) and 1 byte. Future extensions may relax this constraint and allow all powers of two.
Support for this proposal is disabled by default.
pub fn wasm_threads(&mut self, enable: bool) -> &mut Config
pub fn wasm_threads(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly threads proposal will be enabled for compilation.
This feature gates items such as shared memories and atomic instructions. Note that the threads feature depends on the bulk memory feature, which is enabled by default. Additionally note that while the wasm feature is called “threads” it does not actually include the ability to spawn threads. Spawning threads is part of the wasi-threads proposal which is a separately gated feature in Wasmtime.
Embeddings of Wasmtime are able to build their own custom threading scheme on top of the core wasm threads proposal, however.
The default value for this option is whether the threads
crate feature of Wasmtime is enabled or not. By default this crate
feature is enabled.
pub fn wasm_reference_types(&mut self, enable: bool) -> &mut Config
pub fn wasm_reference_types(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly reference types proposal will be enabled for compilation.
This feature gates items such as the externref
and funcref
types as
well as allowing a module to define multiple tables.
Note that the reference types proposal depends on the bulk memory proposal.
This feature is true
by default.
§Errors
The validation of this feature are deferred until the engine is being built,
and thus may cause Engine::new
fail if the bulk_memory
feature is disabled.
pub fn wasm_function_references(&mut self, enable: bool) -> &mut Config
pub fn wasm_function_references(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly function references proposal will be enabled for compilation.
This feature gates non-nullable reference types, function reference
types, call_ref
, ref.func
, and non-nullable reference related
instructions.
Note that the function references proposal depends on the reference types proposal.
This feature is false
by default.
pub fn wasm_wide_arithmetic(&mut self, enable: bool) -> &mut Config
pub fn wasm_wide_arithmetic(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly wide-arithmetic will be enabled for compilation.
This feature is false
by default.
pub fn wasm_gc(&mut self, enable: bool) -> &mut Config
pub fn wasm_gc(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly Garbage Collection proposal will be enabled for compilation.
This feature gates struct
and array
type definitions and references,
the i31ref
type, and all related instructions.
Note that the function references proposal depends on the typed function references proposal.
This feature is false
by default.
Warning: Wasmtime’s implementation of the GC proposal is still in progress and generally not ready for primetime.
pub fn wasm_simd(&mut self, enable: bool) -> &mut Config
pub fn wasm_simd(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly SIMD proposal will be enabled for compilation.
The WebAssembly SIMD proposal. This feature gates items such
as the v128
type and all of its operators being in a module. Note that
this does not enable the relaxed simd proposal.
On x86_64 platforms note that enabling this feature requires SSE 4.2 and below to be available on the target platform. Compilation will fail if the compile target does not include SSE 4.2.
This is true
by default.
pub fn wasm_relaxed_simd(&mut self, enable: bool) -> &mut Config
pub fn wasm_relaxed_simd(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly Relaxed SIMD proposal will be enabled for compilation.
The relaxed SIMD proposal adds new instructions to WebAssembly which, for some specific inputs, are allowed to produce different results on different hosts. More-or-less this proposal enables exposing platform-specific semantics of SIMD instructions in a controlled fashion to a WebAssembly program. From an embedder’s perspective this means that WebAssembly programs may execute differently depending on whether the host is x86_64 or AArch64, for example.
By default Wasmtime lowers relaxed SIMD instructions to the fastest
lowering for the platform it’s running on. This means that, by default,
some relaxed SIMD instructions may have different results for the same
inputs across x86_64 and AArch64. This behavior can be disabled through
the Config::relaxed_simd_deterministic
option which will force
deterministic behavior across all platforms, as classified by the
specification, at the cost of performance.
This is true
by default.
pub fn relaxed_simd_deterministic(&mut self, enable: bool) -> &mut Config
pub fn relaxed_simd_deterministic(&mut self, enable: bool) -> &mut Config
This option can be used to control the behavior of the relaxed SIMD proposal’s instructions.
The relaxed SIMD proposal introduces instructions that are allowed to have different behavior on different architectures, primarily to afford an efficient implementation on all architectures. This means, however, that the same module may execute differently on one host than another, which typically is not otherwise the case. This option is provided to force Wasmtime to generate deterministic code for all relaxed simd instructions, at the cost of performance, for all architectures. When this option is enabled then the deterministic behavior of all instructions in the relaxed SIMD proposal is selected.
This is false
by default.
pub fn wasm_bulk_memory(&mut self, enable: bool) -> &mut Config
pub fn wasm_bulk_memory(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly bulk memory operations proposal will be enabled for compilation.
This feature gates items such as the memory.copy
instruction, passive
data/table segments, etc, being in a module.
This is true
by default.
Feature reference_types
, which is also true
by default, requires
this feature to be enabled. Thus disabling this feature must also disable
reference_types
as well using wasm_reference_types
.
§Errors
Disabling this feature without disabling reference_types
will cause
Engine::new
to fail.
pub fn wasm_multi_value(&mut self, enable: bool) -> &mut Config
pub fn wasm_multi_value(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly multi-value proposal will be enabled for compilation.
This feature gates functions and blocks returning multiple values in a module, for example.
This is true
by default.
pub fn wasm_multi_memory(&mut self, enable: bool) -> &mut Config
pub fn wasm_multi_memory(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly multi-memory proposal will be enabled for compilation.
This feature gates modules having more than one linear memory declaration or import.
This is true
by default.
pub fn wasm_memory64(&mut self, enable: bool) -> &mut Config
pub fn wasm_memory64(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly memory64 proposal will be enabled for compilation.
Note that this the upstream specification is not finalized and Wasmtime may also have bugs for this feature since it hasn’t been exercised much.
This is false
by default.
pub fn wasm_extended_const(&mut self, enable: bool) -> &mut Config
pub fn wasm_extended_const(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly extended-const proposal will be enabled for compilation.
This is true
by default.
pub fn wasm_component_model(&mut self, enable: bool) -> &mut Config
pub fn wasm_component_model(&mut self, enable: bool) -> &mut Config
Configures whether the WebAssembly component-model proposal will be enabled for compilation.
This flag can be used to blanket disable all components within Wasmtime.
Otherwise usage of components requires statically using
Component
instead of
Module
for example anyway.
The default value for this option is whether the component-model
crate feature of Wasmtime is enabled or not. By default this crate
feature is enabled.
pub fn wasm_component_model_more_flags(&mut self, enable: bool) -> &mut Config
pub fn wasm_component_model_more_flags(&mut self, enable: bool) -> &mut Config
Configures whether components support more than 32 flags in each flags
type.
This is part of the transition plan in https://github.com/WebAssembly/component-model/issues/370.
pub fn wasm_component_model_multiple_returns(
&mut self,
enable: bool,
) -> &mut Config
pub fn wasm_component_model_multiple_returns( &mut self, enable: bool, ) -> &mut Config
Configures whether components support more than one return value for functions.
This is part of the transition plan in https://github.com/WebAssembly/component-model/pull/368.
pub fn strategy(&mut self, strategy: Strategy) -> &mut Config
pub fn strategy(&mut self, strategy: Strategy) -> &mut Config
Configures which compilation strategy will be used for wasm modules.
This method can be used to configure which compiler is used for wasm
modules, and for more documentation consult the Strategy
enumeration
and its documentation.
The default value for this is Strategy::Auto
.
pub fn collector(&mut self, collector: Collector) -> &mut Config
pub fn collector(&mut self, collector: Collector) -> &mut Config
Configures which garbage collector will be used for Wasm modules.
This method can be used to configure which garbage collector
implementation is used for Wasm modules. For more documentation, consult
the Collector
enumeration and its documentation.
The default value for this is Collector::Auto
.
pub fn profiler(&mut self, profile: ProfilingStrategy) -> &mut Config
pub fn profiler(&mut self, profile: ProfilingStrategy) -> &mut Config
Creates a default profiler based on the profiling strategy chosen.
Profiler creation calls the type’s default initializer where the purpose is really just to put in place the type used for profiling.
Some ProfilingStrategy
require specific platforms or particular feature
to be enabled, such as ProfilingStrategy::JitDump
requires the jitdump
feature.
§Errors
The validation of this field is deferred until the engine is being built, and thus may
cause Engine::new
fail if the required feature is disabled, or the platform is not
supported.
pub fn cranelift_debug_verifier(&mut self, enable: bool) -> &mut Config
pub fn cranelift_debug_verifier(&mut self, enable: bool) -> &mut Config
Configures whether the debug verifier of Cranelift is enabled or not.
When Cranelift is used as a code generation backend this will configure
it to have the enable_verifier
flag which will enable a number of debug
checks inside of Cranelift. This is largely only useful for the
developers of wasmtime itself.
The default value for this is false
pub fn cranelift_opt_level(&mut self, level: OptLevel) -> &mut Config
pub fn cranelift_opt_level(&mut self, level: OptLevel) -> &mut Config
Configures the Cranelift code generator optimization level.
When the Cranelift code generator is used you can configure the
optimization level used for generated code in a few various ways. For
more information see the documentation of OptLevel
.
The default value for this is OptLevel::None
.
pub fn cranelift_regalloc_algorithm(
&mut self,
algo: RegallocAlgorithm,
) -> &mut Config
pub fn cranelift_regalloc_algorithm( &mut self, algo: RegallocAlgorithm, ) -> &mut Config
Configures the regalloc algorithm used by the Cranelift code generator.
Cranelift can select any of several register allocator algorithms. Each
of these algorithms generates correct code, but they represent different
tradeoffs between compile speed (how expensive the compilation process
is) and run-time speed (how fast the generated code runs).
For more information see the documentation of RegallocAlgorithm
.
The default value for this is RegallocAlgorithm::Backtracking
.
pub fn cranelift_nan_canonicalization(&mut self, enable: bool) -> &mut Config
pub fn cranelift_nan_canonicalization(&mut self, enable: bool) -> &mut Config
Configures whether Cranelift should perform a NaN-canonicalization pass.
When Cranelift is used as a code generation backend this will configure it to replace NaNs with a single canonical value. This is useful for users requiring entirely deterministic WebAssembly computation. This is not required by the WebAssembly spec, so it is not enabled by default.
Note that this option affects not only WebAssembly’s f32
and f64
types but additionally the v128
type. This option will cause
operations using any of these types to have extra checks placed after
them to normalize NaN values as needed.
The default value for this is false
pub fn cranelift_pcc(&mut self, enable: bool) -> &mut Config
pub fn cranelift_pcc(&mut self, enable: bool) -> &mut Config
Controls whether proof-carrying code (PCC) is used to validate lowering of Wasm sandbox checks.
Proof-carrying code carries “facts” about program values from the IR all the way to machine code, and checks those facts against known machine-instruction semantics. This guards against bugs in instruction lowering that might create holes in the Wasm sandbox.
PCC is designed to be fast: it does not require complex solvers or logic engines to verify, but only a linear pass over a trail of “breadcrumbs” or facts at each intermediate value. Thus, it is appropriate to enable in production.
pub unsafe fn cranelift_flag_enable(&mut self, flag: &str) -> &mut Config
pub unsafe fn cranelift_flag_enable(&mut self, flag: &str) -> &mut Config
Allows setting a Cranelift boolean flag or preset. This allows fine-tuning of Cranelift settings.
Since Cranelift flags may be unstable, this method should not be considered to be stable
either; other Config
functions should be preferred for stability.
§Safety
This is marked as unsafe, because setting the wrong flag might break invariants, resulting in execution hazards.
§Errors
The validation of the flags are deferred until the engine is being built, and thus may
cause Engine::new
fail if the flag’s name does not exist, or the value is not appropriate
for the flag type.
pub unsafe fn cranelift_flag_set(
&mut self,
name: &str,
value: &str,
) -> &mut Config
pub unsafe fn cranelift_flag_set( &mut self, name: &str, value: &str, ) -> &mut Config
Allows settings another Cranelift flag defined by a flag name and value. This allows fine-tuning of Cranelift settings.
Since Cranelift flags may be unstable, this method should not be considered to be stable
either; other Config
functions should be preferred for stability.
§Safety
This is marked as unsafe, because setting the wrong flag might break invariants, resulting in execution hazards.
§Errors
The validation of the flags are deferred until the engine is being built, and thus may
cause Engine::new
fail if the flag’s name does not exist, or incompatible with other
settings.
For example, feature wasm_backtrace
will set unwind_info
to true
, but if it’s
manually set to false then it will fail.
pub fn cache_config_load(
&mut self,
path: impl AsRef<Path>,
) -> Result<&mut Config, Error>
pub fn cache_config_load( &mut self, path: impl AsRef<Path>, ) -> Result<&mut Config, Error>
Loads cache configuration specified at path
.
This method will read the file specified by path
on the filesystem and
attempt to load cache configuration from it. This method can also fail
due to I/O errors, misconfiguration, syntax errors, etc. For expected
syntax in the configuration file see the documentation online.
By default cache configuration is not enabled or loaded.
This method is only available when the cache
feature of this crate is
enabled.
§Errors
This method can fail due to any error that happens when loading the file
pointed to by path
and attempting to load the cache configuration.
pub fn disable_cache(&mut self) -> &mut Config
pub fn disable_cache(&mut self) -> &mut Config
Disable caching.
Every call to Module::new(my_wasm)
will
recompile my_wasm
, even when it is unchanged.
By default, new configs do not have caching enabled. This method is only useful for disabling a previous cache configuration.
This method is only available when the cache
feature of this crate is
enabled.
pub fn cache_config_load_default(&mut self) -> Result<&mut Config, Error>
pub fn cache_config_load_default(&mut self) -> Result<&mut Config, Error>
Loads cache configuration from the system default path.
This commit is the same as Config::cache_config_load
except that it
does not take a path argument and instead loads the default
configuration present on the system. This is located, for example, on
Unix at $HOME/.config/wasmtime/config.toml
and is typically created
with the wasmtime config new
command.
By default cache configuration is not enabled or loaded.
This method is only available when the cache
feature of this crate is
enabled.
§Errors
This method can fail due to any error that happens when loading the default system configuration. Note that it is not an error if the default config file does not exist, in which case the default settings for an enabled cache are applied.
pub fn with_host_memory(
&mut self,
mem_creator: Arc<dyn MemoryCreator>,
) -> &mut Config
pub fn with_host_memory( &mut self, mem_creator: Arc<dyn MemoryCreator>, ) -> &mut Config
Sets a custom memory creator.
Custom memory creators are used when creating host Memory
objects or when
creating instance linear memories for the on-demand instance allocation strategy.
pub fn with_host_stack(
&mut self,
stack_creator: Arc<dyn StackCreator>,
) -> &mut Config
pub fn with_host_stack( &mut self, stack_creator: Arc<dyn StackCreator>, ) -> &mut Config
Sets a custom stack creator.
Custom memory creators are used when creating creating async instance stacks for the on-demand instance allocation strategy.
pub fn with_custom_code_memory(
&mut self,
custom_code_memory: Option<Arc<dyn CustomCodeMemory>>,
) -> &mut Config
pub fn with_custom_code_memory( &mut self, custom_code_memory: Option<Arc<dyn CustomCodeMemory>>, ) -> &mut Config
Sets a custom executable-memory publisher.
Custom executable-memory publishers are hooks that allow Wasmtime to make certain regions of memory executable when loading precompiled modules or compiling new modules in-process. In most modern operating systems, memory allocated for heap usage is readable and writable by default but not executable. To jump to machine code stored in that memory, we need to make it executable. For security reasons, we usually also make it read-only at the same time, so the executing code can’t be modified later.
By default, Wasmtime will use the appropriate system calls on
the host platform for this work. However, it also allows
plugging in a custom implementation via this configuration
option. This may be useful on custom or no_std
platforms,
for example, especially where virtual memory is not otherwise
used by Wasmtime (no signals-and-traps
feature).
pub fn allocation_strategy(
&mut self,
strategy: impl Into<InstanceAllocationStrategy>,
) -> &mut Config
pub fn allocation_strategy( &mut self, strategy: impl Into<InstanceAllocationStrategy>, ) -> &mut Config
Sets the instance allocation strategy to use.
This is notably used in conjunction with
InstanceAllocationStrategy::Pooling
and PoolingAllocationConfig
.
pub fn memory_reservation(&mut self, bytes: u64) -> &mut Config
pub fn memory_reservation(&mut self, bytes: u64) -> &mut Config
Specifies the capacity of linear memories, in bytes, in their initial allocation.
Note: this value has important performance ramifications, be sure to benchmark when setting this to a non-default value and read over this documentation.
This function will change the size of the initial memory allocation made
for linear memories. This setting is only applicable when the initial
size of a linear memory is below this threshold. Linear memories are
allocated in the virtual address space of the host process with OS APIs
such as mmap
and this setting affects how large the allocation will
be.
§Background: WebAssembly Linear Memories
WebAssembly linear memories always start with a minimum size and can possibly grow up to a maximum size. The minimum size is always specified in a WebAssembly module itself and the maximum size can either be optionally specified in the module or inherently limited by the index type. For example for this module:
(module
(memory $a 4)
(memory $b 4096 4096 (pagesize 1))
(memory $c i64 10)
)
- Memory
$a
initially allocates 4 WebAssembly pages (256KiB) and can grow up to 4GiB, the limit of the 32-bit index space. - Memory
$b
initially allocates 4096 WebAssembly pages, but in this case its page size is 1, so it’s 4096 bytes. Memory can also grow no further meaning that it will always be 4096 bytes. - Memory
$c
is a 64-bit linear memory which starts with 640KiB of memory and can theoretically grow up to 2^64 bytes, although most hosts will run out of memory long before that.
All operations on linear memories done by wasm are required to be in-bounds. Any access beyond the end of a linear memory is considered a trap.
§What this setting affects: Virtual Memory
This setting is used to configure the behavior of the size of the linear memory allocation performed for each of these memories. For example the initial linear memory allocation looks like this:
memory_reservation
|
◄─────────┴────────────────►
┌───────┬─────────┬──────────────────┬───────┐
│ guard │ initial │ ... capacity ... │ guard │
└───────┴─────────┴──────────────────┴───────┘
◄──┬──► ◄──┬──►
│ │
│ memory_guard_size
│
│
memory_guard_size (if guard_before_linear_memory)
Memory in the initial
range is accessible to the instance and can be
read/written by wasm code. Memory in the guard
regions is never
accesible to wasm code and memory in capacity
is initially
inaccessible but may become accesible through memory.grow
instructions
for example.
This means that this setting is the size of the initial chunk of virtual memory that a linear memory may grow into.
§What this setting affects: Runtime Speed
This is a performance-sensitive setting which is taken into account
during the compilation process of a WebAssembly module. For example if a
32-bit WebAssembly linear memory has a memory_reservation
size of 4GiB
then bounds checks can be elided because capacity
will be guaranteed
to be unmapped for all addressible bytes that wasm can access (modulo a
few details).
If memory_reservation
was something smaller like 256KiB then that
would have a much smaller impact on virtual memory but the compile code
would then need to have explicit bounds checks to ensure that
loads/stores are in-bounds.
The goal of this setting is to enable skipping bounds checks in most modules by default. Some situations which require explicit bounds checks though are:
-
When
memory_reservation
is smaller than the addressible size of the linear memory. For example if 64-bit linear memories always need bounds checks as they can address the entire virtual address spacce. For 32-bit linear memories amemory_reservation
minimum size of 4GiB is required to elide bounds checks. -
When linear memories have a page size of 1 then bounds checks are required. In this situation virtual memory can’t be relied upon because that operates at the host page size granularity where wasm requires a per-byte level granularity.
-
Configuration settings such as
Config::signals_based_traps
can be used to disable the use of signal handlers and virtual memory so explicit bounds checks are required. -
When
Config::memory_guard_size
is too small a bounds check may be required. For 32-bit wasm addresses are actually 33-bit effective addresses because loads/stores have a 32-bit static offset to add to the dynamic 32-bit address. If the static offset is larger than the size of the guard region then an explicit bounds check is required.
§What this setting affects: Memory Growth Behavior
In addition to affecting bounds checks emitted in compiled code this
setting also affects how WebAssembly linear memories are grown. The
memory.grow
instruction can be used to make a linear memory larger and
this is also affected by APIs such as
Memory::grow
.
In these situations when the amount being grown is small enough to fit within the remaining capacity then the linear memory doesn’t have to be moved at runtime. If the capacity runs out though then a new linear memory allocation must be made and the contents of linear memory is copied over.
For example here’s a situation where a copy happens:
- The
memory_reservation
setting is configured to 128KiB. - A WebAssembly linear memory starts with a single 64KiB page.
- This memory can be grown by one page to contain the full 128KiB of memory.
- If grown by one more page, though, then a 192KiB allocation must be made and the previous 128KiB of contents are copied into the new allocation.
This growth behavior can have a significant performance impact if lots of data needs to be copied on growth. Conversely if memory growth never needs to happen because the capacity will always be large enough then optimizations can be applied to cache the base pointer of linear memory.
When memory is grown then the
Config::memory_reservation_for_growth
is used for the new
memory allocation to have memory to grow into.
When using the pooling allocator via PoolingAllocationConfig
then
memories are never allowed to move so requests for growth are instead
rejected with an error.
§When this setting is not used
This setting is ignored and unused when the initial size of linear
memory is larger than this threshold. For example if this setting is set
to 1MiB but a wasm module requires a 2MiB minimum allocation then this
setting is ignored. In this situation the minimum size of memory will be
allocated along with Config::memory_reservation_for_growth
after it to grow into.
That means that this value can be set to zero. That can be useful in benchmarking to see the overhead of bounds checks for example. Additionally it can be used to minimize the virtual memory allocated by Wasmtime.
§Default Value
The default value for this property depends on the host platform. For
64-bit platforms there’s lots of address space available, so the default
configured here is 4GiB. When coupled with the default size of
Config::memory_guard_size
this means that 32-bit WebAssembly linear
memories with 64KiB page sizes will skip almost all bounds checks by
default.
For 32-bit platforms this value defaults to 10MiB. This means that bounds checks will be required on 32-bit platforms.
pub fn memory_may_move(&mut self, enable: bool) -> &mut Config
pub fn memory_may_move(&mut self, enable: bool) -> &mut Config
Indicates whether linear memories may relocate their base pointer at runtime.
WebAssembly linear memories either have a maximum size that’s explicitly
listed in the type of a memory or inherently limited by the index type
of the memory (e.g. 4GiB for 32-bit linear memories). Depending on how
the linear memory is allocated (see Config::memory_reservation
) it
may be necessary to move the memory in the host’s virtual address space
during growth. This option controls whether this movement is allowed or
not.
An example of a linear memory needing to move is when
Config::memory_reservation
is 0 then a linear memory will be
allocated as the minimum size of the memory plus
Config::memory_reservation_for_growth
. When memory grows beyond the
reservation for growth then the memory needs to be relocated.
When this option is set to false
then it can have a number of impacts
on how memories work at runtime:
-
Modules can be compiled with static knowledge the base pointer of linear memory never changes to enable optimizations such as loop invariant code motion (hoisting the base pointer out of a loop).
-
Memories cannot grow in excess of their original allocation. This means that
Config::memory_reservation
andConfig::memory_reservation_for_growth
may need tuning to ensure the memory configuration works at runtime.
The default value for this option is true
.
pub fn memory_guard_size(&mut self, bytes: u64) -> &mut Config
pub fn memory_guard_size(&mut self, bytes: u64) -> &mut Config
Configures the size, in bytes, of the guard region used at the end of a linear memory’s address space reservation.
Note: this value has important performance ramifications, be sure to understand what this value does before tweaking it and benchmarking.
This setting controls how many bytes are guaranteed to be unmapped after
the virtual memory allocation of a linear memory. When
combined with sufficiently large values of
Config::memory_reservation
(e.g. 4GiB for 32-bit linear memories)
then a guard region can be used to eliminate bounds checks in generated
code.
This setting additionally can be used to help deduplicate bounds checks
in code that otherwise requires bounds checks. For example with a 4KiB
guard region then a 64-bit linear memory which accesses addresses x+8
and x+16
only needs to perform a single bounds check on x
. If that
bounds check passes then the offset is guaranteed to either reside in
linear memory or the guard region, resulting in deterministic behavior
either way.
§How big should the guard be?
In general, like with configuring Config::memory_reservation
, you
probably don’t want to change this value from the defaults. Removing
bounds checks is dependent on a number of factors where the size of the
guard region is only one piece of the equation. Other factors include:
Config::memory_reservation
- The index type of the linear memory (e.g. 32-bit or 64-bit)
- The page size of the linear memory
- Other settings such as
Config::signals_based_traps
Embeddings using virtual memory almost always want at least some guard region, but otherwise changes from the default should be profiled locally to see the performance impact.
§Default
The default value for this property is 32MiB on 64-bit platforms. This allows eliminating almost all bounds checks on loads/stores with an immediate offset of less than 32MiB. On 32-bit platforms this defaults to 64KiB.
pub fn memory_reservation_for_growth(&mut self, bytes: u64) -> &mut Config
pub fn memory_reservation_for_growth(&mut self, bytes: u64) -> &mut Config
Configures the size, in bytes, of the extra virtual memory space reserved after a linear memory is relocated.
This setting is used in conjunction with Config::memory_reservation
to configure what happens after a linear memory is relocated in the host
address space. If the initial size of a linear memory exceeds
Config::memory_reservation
or if it grows beyond that size
throughout its lifetime then this setting will be used.
When a linear memory is relocated it will initially look like this:
memory.size
│
◄──────┴─────►
┌───────┬──────────────┬───────┐
│ guard │ accessible │ guard │
└───────┴──────────────┴───────┘
◄──┬──►
│
memory_guard_size
where accessible
needs to be grown but there’s no more memory to grow
into. A new region of the virtual address space will be allocated that
looks like this:
memory_reservation_for_growth
│
memory.size │
│ │
◄──────┴─────► ◄─────────────┴───────────►
┌───────┬──────────────┬───────────────────────────┬───────┐
│ guard │ accessible │ .. reserved for growth .. │ guard │
└───────┴──────────────┴───────────────────────────┴───────┘
◄──┬──►
│
memory_guard_size
This means that up to memory_reservation_for_growth
bytes can be
allocated again before the entire linear memory needs to be moved again
when another memory_reservation_for_growth
bytes will be appended to
the size of the allocation.
Note that this is a currently simple heuristic for optimizing the growth of dynamic memories, primarily implemented for the memory64 proposal where the maximum size of memory is larger than 4GiB. This setting is unlikely to be a one-size-fits-all style approach and if you’re an embedder running into issues with growth and are interested in having other growth strategies available here please feel free to open an issue on the Wasmtime repository!
§Default
For 64-bit platforms this defaults to 2GiB, and for 32-bit platforms this defaults to 1MiB.
pub fn guard_before_linear_memory(&mut self, enable: bool) -> &mut Config
pub fn guard_before_linear_memory(&mut self, enable: bool) -> &mut Config
Indicates whether a guard region is present before allocations of linear memory.
Guard regions before linear memories are never used during normal operation of WebAssembly modules, even if they have out-of-bounds loads. The only purpose for a preceding guard region in linear memory is extra protection against possible bugs in code generators like Cranelift. This setting does not affect performance in any way, but will result in larger virtual memory reservations for linear memories (it won’t actually ever use more memory, just use more of the address space).
The size of the guard region before linear memory is the same as the
guard size that comes after linear memory, which is configured by
Config::memory_guard_size
.
§Default
This value defaults to true
.
pub fn table_lazy_init(&mut self, table_lazy_init: bool) -> &mut Config
pub fn table_lazy_init(&mut self, table_lazy_init: bool) -> &mut Config
Indicates whether to initialize tables lazily, so that instantiation is fast but indirect calls are a little slower. If false, tables are initialized eagerly during instantiation from any active element segments that apply to them.
Note Disabling this option is not compatible with the Winch compiler.
§Default
This value defaults to true
.
pub fn module_version(
&mut self,
strategy: ModuleVersionStrategy,
) -> Result<&mut Config, Error>
pub fn module_version( &mut self, strategy: ModuleVersionStrategy, ) -> Result<&mut Config, Error>
Configure the version information used in serialized and deserialized crate::Module
s.
This effects the behavior of crate::Module::serialize()
, as well as
crate::Module::deserialize()
and related functions.
The default strategy is to use the wasmtime crate’s Cargo package version.
pub fn parallel_compilation(&mut self, parallel: bool) -> &mut Config
pub fn parallel_compilation(&mut self, parallel: bool) -> &mut Config
Configure whether wasmtime should compile a module using multiple threads.
Disabling this will result in a single thread being used to compile the wasm bytecode.
By default parallel compilation is enabled.
pub fn generate_address_map(&mut self, generate: bool) -> &mut Config
pub fn generate_address_map(&mut self, generate: bool) -> &mut Config
Configures whether compiled artifacts will contain information to map native program addresses back to the original wasm module.
This configuration option is true
by default and, if enabled,
generates the appropriate tables in compiled modules to map from native
address back to wasm source addresses. This is used for displaying wasm
program counters in backtraces as well as generating filenames/line
numbers if so configured as well (and the original wasm module has DWARF
debugging information present).
pub fn memory_init_cow(&mut self, enable: bool) -> &mut Config
pub fn memory_init_cow(&mut self, enable: bool) -> &mut Config
Configures whether copy-on-write memory-mapped data is used to initialize a linear memory.
Initializing linear memory via a copy-on-write mapping can drastically improve instantiation costs of a WebAssembly module because copying memory is deferred. Additionally if a page of memory is only ever read from WebAssembly and never written too then the same underlying page of data will be reused between all instantiations of a module meaning that if a module is instantiated many times this can lower the overall memory required needed to run that module.
The main disadvantage of copy-on-write initialization, however, is that it may be possible for highly-parallel scenarios to be less scalable. If a page is read initially by a WebAssembly module then that page will be mapped to a read-only copy shared between all WebAssembly instances. If the same page is then written, however, then a private copy is created and swapped out from the read-only version. This also requires an IPI, however, which can be a significant bottleneck in high-parallelism situations.
This feature is only applicable when a WebAssembly module meets specific criteria to be initialized in this fashion, such as:
- Only memories defined in the module can be initialized this way.
- Data segments for memory must use statically known offsets.
- Data segments for memory must all be in-bounds.
Modules which do not meet these criteria will fall back to initialization of linear memory based on copying memory.
This feature of Wasmtime is also platform-specific:
- Linux - this feature is supported for all instances of
Module
. Modules backed by an existing mmap (such as those created byModule::deserialize_file
) will reuse that mmap to cow-initialize memory. Other instance ofModule
may use thememfd_create
syscall to create an initialization image tommap
. - Unix (not Linux) - this feature is only supported when loading modules
from a precompiled file via
Module::deserialize_file
where there is a file descriptor to use to map data into the process. Note that the module must have been compiled with this setting enabled as well. - Windows - there is no support for this feature at this time. Memory initialization will always copy bytes.
By default this option is enabled.
pub fn force_memory_init_memfd(&mut self, enable: bool) -> &mut Config
pub fn force_memory_init_memfd(&mut self, enable: bool) -> &mut Config
A configuration option to force the usage of memfd_create
on Linux to
be used as the backing source for a module’s initial memory image.
When Config::memory_init_cow
is enabled, which is enabled by
default, module memory initialization images are taken from a module’s
original mmap if possible. If a precompiled module was loaded from disk
this means that the disk’s file is used as an mmap source for the
initial linear memory contents. This option can be used to force, on
Linux, that instead of using the original file on disk a new in-memory
file is created with memfd_create
to hold the contents of the initial
image.
This option can be used to avoid possibly loading the contents of memory
from disk through a page fault. Instead with memfd_create
the contents
of memory are always in RAM, meaning that even page faults which
initially populate a wasm linear memory will only work with RAM instead
of ever hitting the disk that the original precompiled module is stored
on.
This option is disabled by default.
pub fn coredump_on_trap(&mut self, enable: bool) -> &mut Config
pub fn coredump_on_trap(&mut self, enable: bool) -> &mut Config
Configures whether or not a coredump should be generated and attached to the anyhow::Error when a trap is raised.
This option is disabled by default.
pub fn wmemcheck(&mut self, enable: bool) -> &mut Config
pub fn wmemcheck(&mut self, enable: bool) -> &mut Config
Enables memory error checking for wasm programs.
This option is disabled by default.
pub fn memory_guaranteed_dense_image_size(
&mut self,
size_in_bytes: u64,
) -> &mut Config
pub fn memory_guaranteed_dense_image_size( &mut self, size_in_bytes: u64, ) -> &mut Config
Configures the “guaranteed dense image size” for copy-on-write initialized memories.
When using the Config::memory_init_cow
feature to initialize memory
efficiently (which is enabled by default), compiled modules contain an
image of the module’s initial heap. If the module has a fairly sparse
initial heap, with just a few data segments at very different offsets,
this could result in a large region of zero bytes in the image. In
other words, it’s not very memory-efficient.
We normally use a heuristic to avoid this: if less than half of the initialized range (first non-zero to last non-zero byte) of any memory in the module has pages with nonzero bytes, then we avoid creating a memory image for the entire module.
However, if the embedder always needs the instantiation-time efficiency of copy-on-write initialization, and is otherwise carefully controlling parameters of the modules (for example, by limiting the maximum heap size of the modules), then it may be desirable to ensure a memory image is created even if this could go against the heuristic above. Thus, we add another condition: there is a size of initialized data region up to which we always allow a memory image. The embedder can set this to a known maximum heap size if they desire to always get the benefits of copy-on-write images.
In the future we may implement a “best of both worlds” solution where we have a dense image up to some limit, and then support a sparse list of initializers beyond that; this would get most of the benefit of copy-on-write and pay the incremental cost of eager initialization only for those bits of memory that are out-of-bounds. However, for now, an embedder desiring fast instantiation should ensure that this setting is as large as the maximum module initial memory content size.
By default this value is 16 MiB.
pub fn debug_adapter_modules(&mut self, debug: bool) -> &mut Config
pub fn debug_adapter_modules(&mut self, debug: bool) -> &mut Config
Internal setting for whether adapter modules for components will have extra WebAssembly instructions inserted performing more debug checks then are necessary.
pub fn emit_clif(&mut self, path: &Path) -> &mut Config
pub fn emit_clif(&mut self, path: &Path) -> &mut Config
Enables clif output when compiling a WebAssembly module.
pub fn macos_use_mach_ports(&mut self, mach_ports: bool) -> &mut Config
pub fn macos_use_mach_ports(&mut self, mach_ports: bool) -> &mut Config
Configures whether, when on macOS, Mach ports are used for exception handling instead of traditional Unix-based signal handling.
WebAssembly traps in Wasmtime are implemented with native faults, for
example a SIGSEGV
will occur when a WebAssembly guest accesses
out-of-bounds memory. Handling this can be configured to either use Unix
signals or Mach ports on macOS. By default Mach ports are used.
Mach ports enable Wasmtime to work by default with foreign error-handling systems such as breakpad which also use Mach ports to handle signals. In this situation Wasmtime will continue to handle guest faults gracefully while any non-guest faults will get forwarded to process-level handlers such as breakpad. Some more background on this can be found in #2456.
A downside of using mach ports, however, is that they don’t interact
well with fork()
. Forking a Wasmtime process on macOS will produce a
child process that cannot successfully run WebAssembly. In this
situation traditional Unix signal handling should be used as that’s
inherited and works across forks.
If your embedding wants to use a custom error handler which leverages
Mach ports and you additionally wish to fork()
the process and use
Wasmtime in the child process that’s not currently possible. Please
reach out to us if you’re in this bucket!
This option defaults to true
, using Mach ports by default.
pub unsafe fn detect_host_feature(
&mut self,
detect: fn(_: &str) -> Option<bool>,
) -> &mut Config
pub unsafe fn detect_host_feature( &mut self, detect: fn(_: &str) -> Option<bool>, ) -> &mut Config
Configures an embedder-provided function, detect
, which is used to
determine if an ISA-specific feature is available on the current host.
This function is used to verify that any features enabled for a compiler backend, such as AVX support on x86_64, are also available on the host. It is undefined behavior to execute an AVX instruction on a host that doesn’t support AVX instructions, for example.
When the std
feature is active on this crate then this function is
configured to a default implementation that uses the standard library’s
feature detection. When the std
feature is disabled then there is no
default available and this method must be called to configure a feature
probing function.
The detect
function provided is given a string name of an ISA feature.
The function should then return:
Some(true)
- indicates that the feature was found on the host and it is supported.Some(false)
- the feature name was recognized but it was not detected on the host, for example the CPU is too old.None
- the feature name was not recognized and it’s not known whether it’s on the host or not.
Feature names passed to detect
match the same feature name used in the
Rust standard library. For example "sse4.2"
is used on x86_64.
§Unsafety
This function is unsafe
because it is undefined behavior to execute
instructions that a host does not support. This means that the result of
detect
must be correct for memory safe execution at runtime.
pub fn signals_based_traps(&mut self, enable: bool) -> &mut Config
pub fn signals_based_traps(&mut self, enable: bool) -> &mut Config
Configures Wasmtime to not use signals-based trap handlers, for example
disables SIGILL
and SIGSEGV
handler registration on Unix platforms.
Wasmtime will by default leverage signals-based trap handlers (or the
platform equivalent, for example “vectored exception handlers” on
Windows) to make generated code more efficient. For example an
out-of-bounds load in WebAssembly will result in a SIGSEGV
on Unix
that is caught by a signal handler in Wasmtime by default. Another
example is divide-by-zero is reported by hardware rather than
explicitly checked and Wasmtime turns that into a trap.
Some environments however may not have easy access to signal handlers. For example embedded scenarios may not support virtual memory. Other environments where Wasmtime is embedded within the surrounding environment may require that new signal handlers aren’t registered due to the global nature of signal handlers. This option exists to disable the signal handler registration when required.
When signals-based trap handlers are disabled then generated code will never rely on segfaults or other signals. Generated code will be slower because bounds checks must be explicit along with other operations like integer division which must check for zero.
When this option is disable it additionally requires that the
enable_heap_access_spectre_mitigation
and
enable_table_access_spectre_mitigation
Cranelift settings are
disabled. This means that generated code must have spectre mitigations
disabled. This is because spectre mitigations rely on faults from
loading from the null address to implement bounds checks.
This option defaults to true
meaning that signals-based trap handlers
are enabled by default.
Note Disabling this option is not compatible with the Winch compiler.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Config
impl !RefUnwindSafe for Config
impl Send for Config
impl Sync for Config
impl Unpin for Config
impl !UnwindSafe for Config
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more