use crate::module::ModuleLimits;
#[allow(clippy::struct_excessive_bools)] #[derive(Clone, Debug)]
pub struct Config {
consume_fuel: bool,
epoch_interruption: bool,
max_wasm_stack: Option<usize>,
collector: Collector,
gc_memory_threshold: Option<usize>,
gc_heap_reservation: u64,
max_module_bytes: usize,
max_expanded_locals: usize,
async_support: bool,
wasm_backtrace: bool,
wasm_backtrace_details: WasmBacktraceDetails,
debug_info: bool,
}
impl Default for Config {
fn default() -> Self {
Config {
consume_fuel: false,
epoch_interruption: false,
max_wasm_stack: None,
collector: Collector::default(),
gc_memory_threshold: None,
gc_heap_reservation: 256 * 1024,
max_module_bytes: crate::module::DEFAULT_MAX_MODULE_BYTES,
max_expanded_locals: crate::module::DEFAULT_MAX_EXPANDED_LOCALS,
async_support: true,
wasm_backtrace: true,
wasm_backtrace_details: WasmBacktraceDetails::default(),
debug_info: false,
}
}
}
impl Config {
pub fn new() -> Self {
Config::default()
}
pub fn consume_fuel(&mut self, enable: bool) -> &mut Self {
self.consume_fuel = enable;
self
}
pub(crate) fn consume_fuel_enabled(&self) -> bool {
self.consume_fuel
}
pub fn epoch_interruption(&mut self, enable: bool) -> &mut Self {
self.epoch_interruption = enable;
self
}
pub(crate) fn epoch_interruption_enabled(&self) -> bool {
self.epoch_interruption
}
pub fn max_wasm_stack(&mut self, size: usize) -> &mut Self {
self.max_wasm_stack = Some(size);
self
}
pub(crate) fn max_wasm_stack_bytes(&self) -> Option<usize> {
self.max_wasm_stack
}
pub fn max_module_bytes(&mut self, bytes: usize) -> &mut Self {
self.max_module_bytes = bytes;
self
}
pub fn max_expanded_locals(&mut self, locals: usize) -> &mut Self {
self.max_expanded_locals = locals;
self
}
pub(crate) fn module_limits(&self) -> ModuleLimits {
ModuleLimits {
max_module_bytes: self.max_module_bytes,
max_expanded_locals: self.max_expanded_locals,
}
}
pub fn wasm_multi_value(&mut self, enable: bool) -> &mut Self {
self
}
pub fn wasm_tail_call(&mut self, enable: bool) -> &mut Self {
self
}
pub fn wasm_bulk_memory(&mut self, enable: bool) -> &mut Self {
self
}
pub fn wasm_reference_types(&mut self, enable: bool) -> &mut Self {
self
}
pub fn wasm_function_references(&mut self, enable: bool) -> &mut Self {
self
}
pub fn wasm_gc(&mut self, enable: bool) -> &mut Self {
self
}
pub fn wasm_exceptions(&mut self, enable: bool) -> &mut Self {
self
}
pub fn memory_reservation(&mut self, bytes: u64) -> &mut Self {
self
}
pub fn memory_reservation_for_growth(&mut self, bytes: u64) -> &mut Self {
self
}
pub fn memory_may_move(&mut self, enable: bool) -> &mut Self {
self
}
pub fn memory_init_cow(&mut self, enable: bool) -> &mut Self {
self
}
pub fn memory_guard_size(&mut self, bytes: u64) -> &mut Self {
self
}
pub fn gc_heap_reservation(&mut self, bytes: u64) -> &mut Self {
self.gc_heap_reservation = bytes;
self
}
pub(crate) fn gc_heap_reservation_bytes(&self) -> usize {
usize::try_from(self.gc_heap_reservation).unwrap_or(usize::MAX)
}
pub fn gc_heap_guard_size(&mut self, bytes: u64) -> &mut Self {
self
}
pub fn gc_heap_reservation_for_growth(&mut self, bytes: u64) -> &mut Self {
self
}
pub fn gc_heap_may_move(&mut self, enable: bool) -> &mut Self {
self
}
pub fn cranelift_opt_level(&mut self, level: OptLevel) -> &mut Self {
self
}
pub fn wasm_backtrace(&mut self, enable: bool) -> &mut Self {
self.wasm_backtrace = enable;
self
}
pub fn wasm_backtrace_details(&mut self, enable: WasmBacktraceDetails) -> &mut Self {
self.wasm_backtrace_details = enable;
self
}
pub fn debug_info(&mut self, enable: bool) -> &mut Self {
self.debug_info = enable;
self
}
pub(crate) fn wasm_backtrace_enabled(&self) -> bool {
self.wasm_backtrace
}
pub(crate) fn debug_info_enabled(&self) -> bool {
self.debug_info
}
pub(crate) fn wasm_backtrace_details_enabled(&self) -> bool {
match self.wasm_backtrace_details {
WasmBacktraceDetails::Enable => true,
WasmBacktraceDetails::Disable => false,
WasmBacktraceDetails::Environment => {
std::env::var("WASMTIME_BACKTRACE_DETAILS").is_ok_and(|v| v == "1")
}
}
}
pub fn gc_memory_threshold(&mut self, bytes: usize) -> &mut Self {
self.gc_memory_threshold = Some(bytes);
self
}
pub fn collector(&mut self, collector: Collector) -> &mut Self {
self.collector = collector;
self
}
pub(crate) fn collector_kind(&self) -> Collector {
self.collector
}
pub(crate) fn gc_memory_threshold_bytes(&self) -> Option<usize> {
self.gc_memory_threshold
}
#[cfg(feature = "async")]
pub fn async_support(&mut self, enable: bool) -> &mut Self {
self.async_support = enable;
self
}
pub(crate) fn async_support_enabled(&self) -> bool {
self.async_support
}
#[cfg(feature = "async")]
pub fn async_stack_size(&mut self, size: usize) -> &mut Self {
self
}
}
#[non_exhaustive]
#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
pub enum Collector {
#[default]
Auto,
DeferredReferenceCounting,
Null,
Copying,
MarkSweep,
}
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub(crate) enum CollectorKind {
Null,
MarkSweep,
}
impl Collector {
pub(crate) fn resolve(self) -> crate::Result<CollectorKind> {
match self {
Collector::Auto | Collector::MarkSweep => Ok(CollectorKind::MarkSweep),
Collector::Null => Ok(CollectorKind::Null),
Collector::DeferredReferenceCounting => Err(crate::Error::msg(
"the deferred reference-counting collector is not supported \
(use Collector::Auto, Collector::MarkSweep, or Collector::Null)",
)),
Collector::Copying => Err(crate::Error::msg(
"the copying collector is not supported \
(use Collector::Auto, Collector::MarkSweep, or Collector::Null)",
)),
}
}
}
#[non_exhaustive]
#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
pub enum OptLevel {
#[default]
None,
Speed,
SpeedAndSize,
}
#[non_exhaustive]
#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
pub enum WasmBacktraceDetails {
Enable,
Disable,
#[default]
Environment,
}
#[cfg(test)]
mod tests {
use super::{Config, WasmBacktraceDetails};
#[test]
fn backtrace_knob_defaults() {
let c = Config::new();
assert!(c.wasm_backtrace_enabled(), "backtrace on by default");
assert!(!c.debug_info_enabled(), "debug_info off by default");
}
#[test]
fn details_enable_disable_resolve_without_env() {
assert!(Config::new()
.wasm_backtrace_details(WasmBacktraceDetails::Enable)
.wasm_backtrace_details_enabled());
assert!(!Config::new()
.wasm_backtrace_details(WasmBacktraceDetails::Disable)
.wasm_backtrace_details_enabled());
}
#[test]
fn knobs_round_trip() {
let mut c = Config::new();
c.wasm_backtrace(false).debug_info(true);
assert!(!c.wasm_backtrace_enabled());
assert!(c.debug_info_enabled());
}
}