diff --git a/crates/cranelift/src/builder.rs b/crates/cranelift/src/builder.rs index 026960dd4097..2c85832376ba 100644 --- a/crates/cranelift/src/builder.rs +++ b/crates/cranelift/src/builder.rs @@ -16,7 +16,7 @@ use wasmtime_cranelift_shared::isa_builder::IsaBuilder; use wasmtime_environ::{CacheStore, CompilerBuilder, Setting, Tunables}; struct Builder { - tunables: Tunables, + tunables: Option, inner: IsaBuilder>, linkopts: LinkOptions, cache_store: Option>, @@ -39,7 +39,7 @@ pub struct LinkOptions { pub fn builder(triple: Option) -> Result> { Ok(Box::new(Builder { - tunables: Tunables::default(), + tunables: None, inner: IsaBuilder::new(triple, |triple| isa::lookup(triple).map_err(|e| e.into()))?, linkopts: LinkOptions::default(), cache_store: None, @@ -82,14 +82,17 @@ impl CompilerBuilder for Builder { } fn set_tunables(&mut self, tunables: Tunables) -> Result<()> { - self.tunables = tunables; + self.tunables = Some(tunables); Ok(()) } fn build(&self) -> Result> { let isa = self.inner.build()?; Ok(Box::new(crate::compiler::Compiler::new( - self.tunables.clone(), + self.tunables + .as_ref() + .expect("set_tunables not called") + .clone(), isa, self.cache_store.clone(), self.linkopts.clone(), diff --git a/crates/environ/src/lib.rs b/crates/environ/src/lib.rs index 9f34dd940a3c..4df17658a11f 100644 --- a/crates/environ/src/lib.rs +++ b/crates/environ/src/lib.rs @@ -33,7 +33,7 @@ pub use crate::ref_bits::*; pub use crate::scopevec::ScopeVec; pub use crate::stack_map::StackMap; pub use crate::trap_encoding::*; -pub use crate::tunables::Tunables; +pub use crate::tunables::*; pub use crate::vmoffsets::*; pub use object; diff --git a/crates/environ/src/tunables.rs b/crates/environ/src/tunables.rs index 7ba3e6fdfc9b..4ff360fcb523 100644 --- a/crates/environ/src/tunables.rs +++ b/crates/environ/src/tunables.rs @@ -1,7 +1,7 @@ use serde_derive::{Deserialize, Serialize}; /// Tunable parameters for WebAssembly compilation. -#[derive(Clone, Hash, Serialize, Deserialize)] +#[derive(Clone, Hash, Serialize, Deserialize, Debug)] pub struct Tunables { /// For static heaps, the size in wasm pages of the heap protected by bounds /// checking. @@ -56,62 +56,85 @@ pub struct Tunables { pub tail_callable: bool, } -impl Default for Tunables { - fn default() -> Self { - let (static_memory_bound, static_memory_offset_guard_size) = if cfg!(miri) { +impl Tunables { + /// Returns a `Tunables` configuration assumed for running code on the host. + pub fn default_host() -> Self { + if cfg!(miri) { + Tunables::default_miri() + } else if cfg!(target_pointer_width = "32") { + Tunables::default_u32() + } else if cfg!(target_pointer_width = "64") { + Tunables::default_u64() + } else { + panic!("unsupported target_pointer_width"); + } + } + + /// Returns the default set of tunables for running under MIRI. + pub fn default_miri() -> Tunables { + Tunables { // No virtual memory tricks are available on miri so make these // limits quite conservative. - ((1 << 20) / crate::WASM_PAGE_SIZE as u64, 0) - } else if cfg!(target_pointer_width = "64") { + static_memory_bound: (1 << 20) / crate::WASM_PAGE_SIZE as u64, + static_memory_offset_guard_size: 0, + dynamic_memory_offset_guard_size: 0, + dynamic_memory_growth_reserve: 0, + + // General options which have the same defaults regardless of + // architecture. + generate_native_debuginfo: false, + parse_wasm_debuginfo: true, + consume_fuel: false, + epoch_interruption: false, + static_memory_bound_is_maximum: false, + guard_before_linear_memory: true, + generate_address_map: true, + debug_adapter_modules: false, + relaxed_simd_deterministic: false, + tail_callable: false, + } + } + + /// Returns the default set of tunables for running under a 32-bit host. + pub fn default_u32() -> Tunables { + Tunables { + // For 32-bit we scale way down to 10MB of reserved memory. This + // impacts performance severely but allows us to have more than a + // few instances running around. + static_memory_bound: (10 * (1 << 20)) / crate::WASM_PAGE_SIZE as u64, + static_memory_offset_guard_size: 0x1_0000, + dynamic_memory_offset_guard_size: 0x1_0000, + dynamic_memory_growth_reserve: 1 << 20, // 1MB + + ..Tunables::default_miri() + } + } + + /// Returns the default set of tunables for running under a 64-bit host. + pub fn default_u64() -> Tunables { + Tunables { // 64-bit has tons of address space to static memories can have 4gb // address space reservations liberally by default, allowing us to // help eliminate bounds checks. // // Coupled with a 2 GiB address space guard it lets us translate // wasm offsets into x86 offsets as aggressively as we can. - (0x1_0000, 0x8000_0000) - } else if cfg!(target_pointer_width = "32") { - // For 32-bit we scale way down to 10MB of reserved memory. This - // impacts performance severely but allows us to have more than a - // few instances running around. - ((10 * (1 << 20)) / crate::WASM_PAGE_SIZE as u64, 0x1_0000) - } else { - panic!("unsupported target_pointer_width"); - }; - Self { - static_memory_bound, - static_memory_offset_guard_size, + static_memory_bound: 0x1_0000, + static_memory_offset_guard_size: 0x8000_0000, // Size in bytes of the offset guard for dynamic memories. // // Allocate a small guard to optimize common cases but without // wasting too much memory. - dynamic_memory_offset_guard_size: if cfg!(miri) { 0 } else { 0x1_0000 }, + dynamic_memory_offset_guard_size: 0x1_0000, // We've got lots of address space on 64-bit so use a larger // grow-into-this area, but on 32-bit we aren't as lucky. Miri is // not exactly fast so reduce memory consumption instead of trying // to avoid memory movement. - dynamic_memory_growth_reserve: if cfg!(miri) { - 0 - } else if cfg!(target_pointer_width = "64") { - 2 << 30 // 2GB - } else if cfg!(target_pointer_width = "32") { - 1 << 20 // 1MB - } else { - panic!("unsupported target_pointer_width"); - }, + dynamic_memory_growth_reserve: 2 << 30, // 2GB - generate_native_debuginfo: false, - parse_wasm_debuginfo: true, - consume_fuel: false, - epoch_interruption: false, - static_memory_bound_is_maximum: false, - guard_before_linear_memory: true, - generate_address_map: true, - debug_adapter_modules: false, - relaxed_simd_deterministic: false, - tail_callable: false, + ..Tunables::default_miri() } } } diff --git a/crates/runtime/src/instance/allocator/pooling.rs b/crates/runtime/src/instance/allocator/pooling.rs index 928069b5ef01..a7154c7c9984 100644 --- a/crates/runtime/src/instance/allocator/pooling.rs +++ b/crates/runtime/src/instance/allocator/pooling.rs @@ -579,7 +579,7 @@ mod test { &config, &Tunables { static_memory_bound: 1, - ..Tunables::default() + ..Tunables::default_host() }, ) .map_err(|e| e.to_string()) @@ -603,7 +603,7 @@ mod test { async_stack_zeroing: true, ..PoolingInstanceAllocatorConfig::default() }; - let allocator = PoolingInstanceAllocator::new(&config, &Tunables::default())?; + let allocator = PoolingInstanceAllocator::new(&config, &Tunables::default_host())?; unsafe { for _ in 0..255 { @@ -637,7 +637,7 @@ mod test { async_stack_zeroing: false, ..PoolingInstanceAllocatorConfig::default() }; - let allocator = PoolingInstanceAllocator::new(&config, &Tunables::default())?; + let allocator = PoolingInstanceAllocator::new(&config, &Tunables::default_host())?; unsafe { for i in 0..255 { diff --git a/crates/runtime/src/instance/allocator/pooling/memory_pool.rs b/crates/runtime/src/instance/allocator/pooling/memory_pool.rs index 9658e43d8b5f..414ecb7978cf 100644 --- a/crates/runtime/src/instance/allocator/pooling/memory_pool.rs +++ b/crates/runtime/src/instance/allocator/pooling/memory_pool.rs @@ -774,7 +774,7 @@ mod tests { &Tunables { static_memory_bound: 1, static_memory_offset_guard_size: 0, - ..Tunables::default() + ..Tunables::default_host() }, )?; @@ -808,7 +808,7 @@ mod tests { &Tunables { static_memory_bound: 1, static_memory_offset_guard_size: 0, - ..Tunables::default() + ..Tunables::default_host() }, ) .unwrap(); @@ -828,7 +828,7 @@ mod tests { memory_protection_keys: MpkEnabled::Enable, ..PoolingInstanceAllocatorConfig::default() }; - let pool = MemoryPool::new(&config, &Tunables::default()).unwrap(); + let pool = MemoryPool::new(&config, &Tunables::default_host()).unwrap(); assert!(pool.stripes.len() >= 2); let max_memory_slots = config.limits.total_memories; diff --git a/crates/wasmtime/src/compile.rs b/crates/wasmtime/src/compile.rs index 71bc5a96ca3f..b8811619d355 100644 --- a/crates/wasmtime/src/compile.rs +++ b/crates/wasmtime/src/compile.rs @@ -54,7 +54,7 @@ pub(crate) fn build_artifacts( engine: &Engine, wasm: &[u8], ) -> Result<(T, Option<(CompiledModuleInfo, ModuleTypes)>)> { - let tunables = &engine.config().tunables; + let tunables = engine.tunables(); // First a `ModuleEnvironment` is created which records type information // about the wasm module. This is where the WebAssembly is parsed and @@ -117,7 +117,7 @@ pub(crate) fn build_component_artifacts( use wasmtime_environ::component::{CompiledComponentInfo, ComponentArtifacts}; use wasmtime_environ::ScopeVec; - let tunables = &engine.config().tunables; + let tunables = engine.tunables(); let compiler = engine.compiler(); let scope = ScopeVec::new(); @@ -610,7 +610,7 @@ impl FunctionIndices { // `symbol_ids_and_locs[i]` is the symbol ID and function location of // `compiled_funcs[i]`. let compiler = engine.compiler(); - let tunables = &engine.config().tunables; + let tunables = engine.tunables(); let symbol_ids_and_locs = compiler.append_code( &mut obj, &compiled_funcs, diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs index 75a1c616fe43..944afd255828 100644 --- a/crates/wasmtime/src/config.rs +++ b/crates/wasmtime/src/config.rs @@ -6,7 +6,7 @@ use std::fmt; use std::path::Path; use std::str::FromStr; use std::sync::Arc; -use target_lexicon::Architecture; +use target_lexicon::{Architecture, PointerWidth}; use wasmparser::WasmFeatures; #[cfg(feature = "cache")] use wasmtime_cache::CacheConfig; @@ -103,8 +103,8 @@ pub struct Config { #[cfg(any(feature = "cranelift", feature = "winch"))] compiler_config: CompilerConfig, profiling_strategy: ProfilingStrategy, + tunables: ConfigTunables, - pub(crate) tunables: Tunables, #[cfg(feature = "cache")] pub(crate) cache_config: CacheConfig, #[cfg(feature = "runtime")] @@ -130,6 +130,24 @@ pub struct Config { pub(crate) macos_use_mach_ports: bool, } +#[derive(Default, Clone)] +struct ConfigTunables { + static_memory_bound: Option, + static_memory_offset_guard_size: Option, + dynamic_memory_offset_guard_size: Option, + dynamic_memory_growth_reserve: Option, + generate_native_debuginfo: Option, + parse_wasm_debuginfo: Option, + consume_fuel: Option, + epoch_interruption: Option, + static_memory_bound_is_maximum: Option, + guard_before_linear_memory: Option, + generate_address_map: Option, + debug_adapter_modules: Option, + relaxed_simd_deterministic: Option, + tail_callable: Option, +} + /// User-provided configuration for the compiler. #[cfg(any(feature = "cranelift", feature = "winch"))] #[derive(Debug, Clone)] @@ -190,7 +208,7 @@ impl Config { /// specified. pub fn new() -> Self { let mut ret = Self { - tunables: Tunables::default(), + tunables: ConfigTunables::default(), #[cfg(any(feature = "cranelift", feature = "winch"))] compiler_config: CompilerConfig::default(), #[cfg(feature = "cache")] @@ -386,7 +404,7 @@ impl Config { /// /// By default this option is `false`. pub fn debug_info(&mut self, enable: bool) -> &mut Self { - self.tunables.generate_native_debuginfo = enable; + self.tunables.generate_native_debuginfo = Some(enable); self } @@ -433,13 +451,13 @@ impl Config { pub fn wasm_backtrace_details(&mut self, enable: WasmBacktraceDetails) -> &mut Self { self.wasm_backtrace_details_env_used = false; self.tunables.parse_wasm_debuginfo = match enable { - WasmBacktraceDetails::Enable => true, - WasmBacktraceDetails::Disable => false, + WasmBacktraceDetails::Enable => Some(true), + WasmBacktraceDetails::Disable => Some(false), WasmBacktraceDetails::Environment => { self.wasm_backtrace_details_env_used = true; std::env::var("WASMTIME_BACKTRACE_DETAILS") - .map(|s| s == "1") - .unwrap_or(false) + .map(|s| Some(s == "1")) + .unwrap_or(Some(false)) } }; self @@ -482,7 +500,7 @@ impl Config { /// /// [`Store`]: crate::Store pub fn consume_fuel(&mut self, enable: bool) -> &mut Self { - self.tunables.consume_fuel = enable; + self.tunables.consume_fuel = Some(enable); self } @@ -576,7 +594,7 @@ impl Config { /// - [`Store::epoch_deadline_callback`](crate::Store::epoch_deadline_callback) /// - [`Store::epoch_deadline_async_yield_and_update`](crate::Store::epoch_deadline_async_yield_and_update) pub fn epoch_interruption(&mut self, enable: bool) -> &mut Self { - self.tunables.epoch_interruption = enable; + self.tunables.epoch_interruption = Some(enable); self } @@ -667,7 +685,7 @@ impl Config { /// [WebAssembly tail calls proposal]: https://github.com/WebAssembly/tail-call pub fn wasm_tail_call(&mut self, enable: bool) -> &mut Self { self.features.tail_call = enable; - self.tunables.tail_callable = enable; + self.tunables.tail_callable = Some(enable); self } @@ -794,7 +812,7 @@ impl Config { /// /// [proposal]: https://github.com/webassembly/relaxed-simd pub fn relaxed_simd_deterministic(&mut self, enable: bool) -> &mut Self { - self.tunables.relaxed_simd_deterministic = enable; + self.tunables.relaxed_simd_deterministic = Some(enable); self } @@ -1239,7 +1257,7 @@ impl Config { /// `PoolingAllocatorConfig::memory_protection_keys` for details. pub fn static_memory_maximum_size(&mut self, max_size: u64) -> &mut Self { let max_pages = max_size / u64::from(wasmtime_environ::WASM_PAGE_SIZE); - self.tunables.static_memory_bound = max_pages; + self.tunables.static_memory_bound = Some(max_pages); self } @@ -1255,7 +1273,7 @@ impl Config { /// For the difference between static and dynamic memories, see the /// [`Config::static_memory_maximum_size`]. pub fn static_memory_forced(&mut self, force: bool) -> &mut Self { - self.tunables.static_memory_bound_is_maximum = force; + self.tunables.static_memory_bound_is_maximum = Some(force); self } @@ -1311,7 +1329,7 @@ impl Config { /// than the value configured for [`Config::dynamic_memory_guard_size`]. pub fn static_memory_guard_size(&mut self, guard_size: u64) -> &mut Self { let guard_size = round_up_to_pages(guard_size); - self.tunables.static_memory_offset_guard_size = guard_size; + self.tunables.static_memory_offset_guard_size = Some(guard_size); self } @@ -1344,7 +1362,7 @@ impl Config { /// than the value configured for [`Config::static_memory_guard_size`]. pub fn dynamic_memory_guard_size(&mut self, guard_size: u64) -> &mut Self { let guard_size = round_up_to_pages(guard_size); - self.tunables.dynamic_memory_offset_guard_size = guard_size; + self.tunables.dynamic_memory_offset_guard_size = Some(guard_size); self } @@ -1383,7 +1401,7 @@ impl Config { /// For 64-bit platforms this defaults to 2GB, and for 32-bit platforms this /// defaults to 1MB. pub fn dynamic_memory_reserved_for_growth(&mut self, reserved: u64) -> &mut Self { - self.tunables.dynamic_memory_growth_reserve = round_up_to_pages(reserved); + self.tunables.dynamic_memory_growth_reserve = Some(round_up_to_pages(reserved)); self } @@ -1408,7 +1426,7 @@ impl Config { /// /// This value defaults to `true`. pub fn guard_before_linear_memory(&mut self, guard: bool) -> &mut Self { - self.tunables.guard_before_linear_memory = guard; + self.tunables.guard_before_linear_memory = Some(guard); self } @@ -1455,7 +1473,7 @@ impl Config { /// numbers if so configured as well (and the original wasm module has DWARF /// debugging information present). pub fn generate_address_map(&mut self, generate: bool) -> &mut Self { - self.tunables.generate_address_map = generate; + self.tunables.generate_address_map = Some(generate); self } @@ -1589,7 +1607,7 @@ impl Config { self } - pub(crate) fn validate(&self) -> Result<()> { + pub(crate) fn validate(&self) -> Result { if self.features.reference_types && !self.features.bulk_memory { bail!("feature 'reference_types' requires 'bulk_memory' to be enabled"); } @@ -1603,27 +1621,73 @@ impl Config { if self.max_wasm_stack == 0 { bail!("max_wasm_stack size cannot be zero"); } - if self.tunables.static_memory_offset_guard_size - < self.tunables.dynamic_memory_offset_guard_size - { - bail!("static memory guard size cannot be smaller than dynamic memory guard size"); - } #[cfg(not(feature = "wmemcheck"))] if self.wmemcheck { bail!("wmemcheck (memory checker) was requested but is not enabled in this build"); } - Ok(()) + #[cfg(not(any(feature = "cranelift", feature = "winch")))] + let mut tunables = Tunables::default_host(); + #[cfg(any(feature = "cranelift", feature = "winch"))] + let mut tunables = match &self.compiler_config.target.as_ref() { + Some(target) => match target.pointer_width() { + Ok(PointerWidth::U32) => Tunables::default_u32(), + Ok(PointerWidth::U64) => Tunables::default_u64(), + _ => bail!("unknown pointer width"), + }, + None => Tunables::default_host(), + }; + + macro_rules! set_fields { + ($($field:ident)*) => ( + let ConfigTunables { + $($field,)* + } = &self.tunables; + + $( + if let Some(e) = $field { + tunables.$field = *e; + } + )* + ) + } + + set_fields! { + static_memory_bound + static_memory_offset_guard_size + dynamic_memory_offset_guard_size + dynamic_memory_growth_reserve + generate_native_debuginfo + parse_wasm_debuginfo + consume_fuel + epoch_interruption + static_memory_bound_is_maximum + guard_before_linear_memory + generate_address_map + debug_adapter_modules + relaxed_simd_deterministic + tail_callable + } + + if tunables.static_memory_offset_guard_size < tunables.dynamic_memory_offset_guard_size { + bail!("static memory guard size cannot be smaller than dynamic memory guard size"); + } + Ok(tunables) } #[cfg(feature = "runtime")] - pub(crate) fn build_allocator(&self) -> Result> { + pub(crate) fn build_allocator( + &self, + tunables: &Tunables, + ) -> Result> { #[cfg(feature = "async")] let stack_size = self.async_stack_size; #[cfg(not(feature = "async"))] let stack_size = 0; + let _ = tunables; + match &self.allocation_strategy { InstanceAllocationStrategy::OnDemand => { #[allow(unused_mut)] @@ -1642,8 +1706,7 @@ impl Config { let mut config = config.config; config.stack_size = stack_size; Ok(Box::new(wasmtime_runtime::PoolingInstanceAllocator::new( - &config, - &self.tunables, + &config, tunables, )?)) } } @@ -1660,7 +1723,10 @@ impl Config { } #[cfg(any(feature = "cranelift", feature = "winch"))] - pub(crate) fn build_compiler(mut self) -> Result<(Self, Box)> { + pub(crate) fn build_compiler( + mut self, + tunables: &Tunables, + ) -> Result<(Self, Box)> { let target = self.compiler_config.target.clone(); let mut compiler = match self.compiler_config.strategy { @@ -1767,7 +1833,7 @@ impl Config { compiler.enable_incremental_compilation(cache_store.clone())?; } - compiler.set_tunables(self.tunables.clone())?; + compiler.set_tunables(tunables.clone())?; compiler.wmemcheck(self.compiler_config.wmemcheck); Ok((self, compiler.build()?)) @@ -1778,7 +1844,7 @@ impl Config { /// then are necessary. #[cfg(feature = "component-model")] pub fn debug_adapter_modules(&mut self, debug: bool) -> &mut Self { - self.tunables.debug_adapter_modules = debug; + self.tunables.debug_adapter_modules = Some(debug); self } @@ -1849,7 +1915,6 @@ impl fmt::Debug for Config { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut f = f.debug_struct("Config"); f.field("debug_info", &self.tunables.generate_native_debuginfo) - .field("parse_wasm_debuginfo", &self.tunables.parse_wasm_debuginfo) .field("wasm_threads", &self.features.threads) .field("wasm_reference_types", &self.features.reference_types) .field( @@ -1860,28 +1925,30 @@ impl fmt::Debug for Config { .field("wasm_simd", &self.features.simd) .field("wasm_relaxed_simd", &self.features.relaxed_simd) .field("wasm_multi_value", &self.features.multi_value) - .field( - "static_memory_maximum_size", - &(u64::from(self.tunables.static_memory_bound) - * u64::from(wasmtime_environ::WASM_PAGE_SIZE)), - ) - .field( - "static_memory_guard_size", - &self.tunables.static_memory_offset_guard_size, - ) - .field( - "dynamic_memory_guard_size", - &self.tunables.dynamic_memory_offset_guard_size, - ) - .field( - "guard_before_linear_memory", - &self.tunables.guard_before_linear_memory, - ) .field("parallel_compilation", &self.parallel_compilation); #[cfg(any(feature = "cranelift", feature = "winch"))] { f.field("compiler_config", &self.compiler_config); } + + if let Some(enable) = self.tunables.parse_wasm_debuginfo { + f.field("parse_wasm_debuginfo", &enable); + } + if let Some(size) = self.tunables.static_memory_bound { + f.field( + "static_memory_maximum_size", + &(u64::from(size) * u64::from(wasmtime_environ::WASM_PAGE_SIZE)), + ); + } + if let Some(size) = self.tunables.static_memory_offset_guard_size { + f.field("static_memory_guard_size", &size); + } + if let Some(size) = self.tunables.dynamic_memory_offset_guard_size { + f.field("dynamic_memory_guard_size", &size); + } + if let Some(enable) = self.tunables.guard_before_linear_memory { + f.field("guard_before_linear_memory", &enable); + } f.finish() } } diff --git a/crates/wasmtime/src/engine.rs b/crates/wasmtime/src/engine.rs index 567838f2fa9f..2a6aba471d1e 100644 --- a/crates/wasmtime/src/engine.rs +++ b/crates/wasmtime/src/engine.rs @@ -9,7 +9,7 @@ use std::path::Path; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::Arc; use wasmtime_environ::obj; -use wasmtime_environ::{FlagValue, ObjectKind}; +use wasmtime_environ::{FlagValue, ObjectKind, Tunables}; mod serialization; @@ -37,27 +37,28 @@ mod serialization; /// default settings. #[derive(Clone)] pub struct Engine { - pub(crate) inner: Arc, + inner: Arc, } -pub(crate) struct EngineInner { - pub(crate) config: Config, +struct EngineInner { + config: Config, + tunables: Tunables, #[cfg(any(feature = "cranelift", feature = "winch"))] - pub(crate) compiler: Box, + compiler: Box, #[cfg(feature = "runtime")] - pub(crate) allocator: Box, + allocator: Box, #[cfg(feature = "runtime")] - pub(crate) profiler: Box, + profiler: Box, #[cfg(feature = "runtime")] - pub(crate) signatures: TypeRegistry, + signatures: TypeRegistry, #[cfg(feature = "runtime")] - pub(crate) epoch: AtomicU64, + epoch: AtomicU64, #[cfg(feature = "runtime")] - pub(crate) unique_id_allocator: wasmtime_runtime::CompiledModuleIdAllocator, + unique_id_allocator: wasmtime_runtime::CompiledModuleIdAllocator, /// One-time check of whether the compiler's settings, if present, are /// compatible with the native host. - pub(crate) compatible_with_native_host: OnceCell>, + compatible_with_native_host: OnceCell>, } impl Default for Engine { @@ -94,17 +95,17 @@ impl Engine { } let config = config.clone(); - config.validate()?; + let tunables = config.validate()?; #[cfg(any(feature = "cranelift", feature = "winch"))] - let (config, compiler) = config.build_compiler()?; + let (config, compiler) = config.build_compiler(&tunables)?; Ok(Engine { inner: Arc::new(EngineInner { #[cfg(any(feature = "cranelift", feature = "winch"))] compiler, #[cfg(feature = "runtime")] - allocator: config.build_allocator()?, + allocator: config.build_allocator(&tunables)?, #[cfg(feature = "runtime")] profiler: config.build_profiler()?, #[cfg(feature = "runtime")] @@ -115,6 +116,7 @@ impl Engine { unique_id_allocator: wasmtime_runtime::CompiledModuleIdAllocator::new(), compatible_with_native_host: OnceCell::new(), config, + tunables, }), }) } @@ -161,6 +163,10 @@ impl Engine { } } + pub(crate) fn tunables(&self) -> &Tunables { + &self.inner.tunables + } + /// Returns whether the engine `a` and `b` refer to the same configuration. pub fn same(a: &Engine, b: &Engine) -> bool { Arc::ptr_eq(&a.inner, &b.inner) diff --git a/crates/wasmtime/src/engine/serialization.rs b/crates/wasmtime/src/engine/serialization.rs index 410776d45345..f4063bd6e547 100644 --- a/crates/wasmtime/src/engine/serialization.rs +++ b/crates/wasmtime/src/engine/serialization.rs @@ -231,7 +231,7 @@ impl Metadata<'_> { target: engine.compiler().triple().to_string(), shared_flags: engine.compiler().flags(), isa_flags: engine.compiler().isa_flags(), - tunables: engine.config().tunables.clone(), + tunables: engine.tunables().clone(), features: WasmFeatures { reference_types, multi_value, @@ -254,7 +254,7 @@ impl Metadata<'_> { self.check_triple(engine)?; self.check_shared_flags(engine)?; self.check_isa_flags(engine)?; - self.check_tunables(&engine.config().tunables)?; + self.check_tunables(&engine.tunables())?; self.check_features(&engine.config().features)?; Ok(()) } diff --git a/crates/wasmtime/src/runtime/memory.rs b/crates/wasmtime/src/runtime/memory.rs index d79736958951..0a625ee2129b 100644 --- a/crates/wasmtime/src/runtime/memory.rs +++ b/crates/wasmtime/src/runtime/memory.rs @@ -732,7 +732,7 @@ impl SharedMemory { } debug_assert!(ty.maximum().is_some()); - let tunables = &engine.config().tunables; + let tunables = engine.tunables(); let plan = MemoryPlan::for_memory(ty.wasmtime_memory().clone(), tunables); let memory = wasmtime_runtime::SharedMemory::new(plan)?; Ok(Self(memory, engine.clone())) diff --git a/crates/wasmtime/src/runtime/module.rs b/crates/wasmtime/src/runtime/module.rs index 564bacd217d9..94c9470b633b 100644 --- a/crates/wasmtime/src/runtime/module.rs +++ b/crates/wasmtime/src/runtime/module.rs @@ -1105,7 +1105,7 @@ impl std::hash::Hash for HashedEngineCompileEnv<'_> { // Hash configuration state read for compilation let config = self.0.config(); - config.tunables.hash(hasher); + self.0.tunables().hash(hasher); config.features.hash(hasher); config.wmemcheck.hash(hasher); diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs index 5a5c1e94e9cd..631f49b3bd0c 100644 --- a/crates/wasmtime/src/runtime/store.rs +++ b/crates/wasmtime/src/runtime/store.rs @@ -1390,7 +1390,7 @@ impl StoreOpaque { pub fn get_fuel(&self) -> Result { anyhow::ensure!( - self.engine().config().tunables.consume_fuel, + self.engine().tunables().consume_fuel, "fuel is not configured in this store" ); let injected_fuel = unsafe { *self.runtime_limits.fuel_consumed.get() }; @@ -1408,7 +1408,7 @@ impl StoreOpaque { pub fn set_fuel(&mut self, fuel: u64) -> Result<()> { anyhow::ensure!( - self.engine().config().tunables.consume_fuel, + self.engine().tunables().consume_fuel, "fuel is not configured in this store" ); let injected_fuel = unsafe { &mut *self.runtime_limits.fuel_consumed.get() }; @@ -1423,7 +1423,7 @@ impl StoreOpaque { pub fn fuel_async_yield_interval(&mut self, interval: Option) -> Result<()> { anyhow::ensure!( - self.engine().config().tunables.consume_fuel, + self.engine().tunables().consume_fuel, "fuel is not configured in this store" ); anyhow::ensure!( diff --git a/crates/wasmtime/src/runtime/trampoline/func.rs b/crates/wasmtime/src/runtime/trampoline/func.rs index ab90d5dcf731..c6c0f49fba2b 100644 --- a/crates/wasmtime/src/runtime/trampoline/func.rs +++ b/crates/wasmtime/src/runtime/trampoline/func.rs @@ -94,10 +94,7 @@ where &mut obj, )?; engine.append_bti(&mut obj); - let obj = finish_object(wasmtime_environ::ObjectBuilder::new( - obj, - &engine.config().tunables, - ))?; + let obj = finish_object(wasmtime_environ::ObjectBuilder::new(obj, engine.tunables()))?; // Copy the results of JIT compilation into executable memory, and this will // also take care of unwind table registration. diff --git a/crates/wasmtime/src/runtime/trampoline/memory.rs b/crates/wasmtime/src/runtime/trampoline/memory.rs index 72c7eb891f81..9d258375718e 100644 --- a/crates/wasmtime/src/runtime/trampoline/memory.rs +++ b/crates/wasmtime/src/runtime/trampoline/memory.rs @@ -40,7 +40,7 @@ pub fn create_memory( // preallocated (i.e., shared memory) or allocated manually below. let plan = wasmtime_environ::MemoryPlan::for_memory( memory_ty.wasmtime_memory().clone(), - &store.engine().config().tunables, + store.engine().tunables(), ); let memory_id = module.memory_plans.push(plan.clone()); diff --git a/crates/wasmtime/src/runtime/trampoline/table.rs b/crates/wasmtime/src/runtime/trampoline/table.rs index f351a26096f1..b6034dc3eaee 100644 --- a/crates/wasmtime/src/runtime/trampoline/table.rs +++ b/crates/wasmtime/src/runtime/trampoline/table.rs @@ -8,7 +8,7 @@ pub fn create_table(store: &mut StoreOpaque, table: &TableType) -> Result Result<()> { let mut validator = Validator::new(); let parser = WasmParser::new(0); let mut types = Default::default(); - let tunables = Tunables::default(); + let tunables = Tunables::default_host(); let mut translation = ModuleEnvironment::new(&tunables, &mut validator, &mut types) .translate(parser, &bytes) .context("Failed to translate WebAssembly module")?;