Skip to content

Commit

Permalink
Deduplicate some code related to Tunables (#9540)
Browse files Browse the repository at this point in the history
Generate the `Option`-field struct based on the definition of `Tunables`
itself instead of duplicating the listed fields in `config.rs`.
Additionally auto-generate methods to debug-format and configure
`Tunables` instead of requiring more duplicated macros as well.
  • Loading branch information
alexcrichton authored Nov 2, 2024
1 parent 38845a0 commit 2e8ed88
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 114 deletions.
160 changes: 108 additions & 52 deletions crates/environ/src/tunables.rs
Original file line number Diff line number Diff line change
@@ -1,74 +1,130 @@
use core::fmt;

use anyhow::{anyhow, bail, Result};
use core::fmt;
use serde_derive::{Deserialize, Serialize};
use target_lexicon::{PointerWidth, Triple};

/// Tunable parameters for WebAssembly compilation.
#[derive(Clone, Hash, Serialize, Deserialize, Debug)]
pub struct Tunables {
/// The garbage collector implementation to use, which implies the layout of
/// GC objects and barriers that must be emitted in Wasm code.
pub collector: Option<Collector>,
macro_rules! define_tunables {
(
$(#[$outer_attr:meta])*
pub struct $tunables:ident {
$(
$(#[$field_attr:meta])*
pub $field:ident : $field_ty:ty,
)*
}

pub struct $config_tunables:ident {
...
}
) => {
$(#[$outer_attr])*
pub struct $tunables {
$(
$(#[$field_attr])*
pub $field: $field_ty,
)*
}

/// Optional tunable configuration options used in `wasmtime::Config`
#[derive(Default, Clone)]
#[allow(missing_docs)]
pub struct $config_tunables {
$(pub $field: Option<$field_ty>,)*
}

impl $config_tunables {
/// Formats configured fields into `f`.
pub fn format(&self, f: &mut fmt::DebugStruct<'_,'_>) {
$(
if let Some(val) = &self.$field {
f.field(stringify!($field), val);
}
)*
}

/// Configure the `Tunables` provided.
pub fn configure(&self, tunables: &mut Tunables) {
$(
if let Some(val) = self.$field {
tunables.$field = val;
}
)*
}
}
};
}

/// For static heaps, the size in bytes of virtual memory reservation for
/// the heap.
pub static_memory_reservation: u64,
define_tunables! {
/// Tunable parameters for WebAssembly compilation.
#[derive(Clone, Hash, Serialize, Deserialize, Debug)]
pub struct Tunables {
/// The garbage collector implementation to use, which implies the layout of
/// GC objects and barriers that must be emitted in Wasm code.
pub collector: Option<Collector>,

/// The size, in bytes, of the guard page region for linear memories.
pub memory_guard_size: u64,
/// For static heaps, the size in bytes of virtual memory reservation for
/// the heap.
pub static_memory_reservation: u64,

/// The size, in bytes, of reserved memory at the end of a "dynamic" memory,
/// before the guard page, that memory can grow into. This is intended to
/// amortize the cost of `memory.grow` in the same manner that `Vec<T>` has
/// space not in use to grow into.
pub dynamic_memory_growth_reserve: u64,
/// The size, in bytes, of the guard page region for linear memories.
pub memory_guard_size: u64,

/// Whether or not to generate native DWARF debug information.
pub generate_native_debuginfo: bool,
/// The size, in bytes, of reserved memory at the end of a "dynamic" memory,
/// before the guard page, that memory can grow into. This is intended to
/// amortize the cost of `memory.grow` in the same manner that `Vec<T>` has
/// space not in use to grow into.
pub dynamic_memory_growth_reserve: u64,

/// Whether or not to retain DWARF sections in compiled modules.
pub parse_wasm_debuginfo: bool,
/// Whether or not to generate native DWARF debug information.
pub generate_native_debuginfo: bool,

/// Whether or not fuel is enabled for generated code, meaning that fuel
/// will be consumed every time a wasm instruction is executed.
pub consume_fuel: bool,
/// Whether or not to retain DWARF sections in compiled modules.
pub parse_wasm_debuginfo: bool,

/// Whether or not we use epoch-based interruption.
pub epoch_interruption: bool,
/// Whether or not fuel is enabled for generated code, meaning that fuel
/// will be consumed every time a wasm instruction is executed.
pub consume_fuel: bool,

/// Whether or not to treat the static memory bound as the maximum for
/// unbounded heaps.
pub static_memory_bound_is_maximum: bool,
/// Whether or not we use epoch-based interruption.
pub epoch_interruption: bool,

/// Whether or not linear memory allocations will have a guard region at the
/// beginning of the allocation in addition to the end.
pub guard_before_linear_memory: bool,
/// Whether or not to treat the static memory bound as the maximum for
/// unbounded heaps.
pub static_memory_bound_is_maximum: bool,

/// Whether to initialize tables lazily, so that instantiation is fast but
/// indirect calls are a little slower. If false, tables are initialized
/// eagerly from any active element segments that apply to them during
/// instantiation.
pub table_lazy_init: bool,
/// Whether or not linear memory allocations will have a guard region at the
/// beginning of the allocation in addition to the end.
pub guard_before_linear_memory: bool,

/// Indicates whether an address map from compiled native code back to wasm
/// offsets in the original file is generated.
pub generate_address_map: bool,
/// Whether to initialize tables lazily, so that instantiation is fast but
/// indirect calls are a little slower. If false, tables are initialized
/// eagerly from any active element segments that apply to them during
/// instantiation.
pub table_lazy_init: bool,

/// Flag for the component module whether adapter modules have debug
/// assertions baked into them.
pub debug_adapter_modules: bool,
/// Indicates whether an address map from compiled native code back to wasm
/// offsets in the original file is generated.
pub generate_address_map: bool,

/// Whether or not lowerings for relaxed simd instructions are forced to
/// be deterministic.
pub relaxed_simd_deterministic: bool,
/// Flag for the component module whether adapter modules have debug
/// assertions baked into them.
pub debug_adapter_modules: bool,

/// Whether or not Wasm functions target the winch abi.
pub winch_callable: bool,
/// Whether or not lowerings for relaxed simd instructions are forced to
/// be deterministic.
pub relaxed_simd_deterministic: bool,

/// Whether or not the host will be using native signals (e.g. SIGILL,
/// SIGSEGV, etc) to implement traps.
pub signals_based_traps: bool,
/// Whether or not Wasm functions target the winch abi.
pub winch_callable: bool,

/// Whether or not the host will be using native signals (e.g. SIGILL,
/// SIGSEGV, etc) to implement traps.
pub signals_based_traps: bool,
}

pub struct ConfigTunables {
...
}
}

impl Tunables {
Expand Down
65 changes: 3 additions & 62 deletions crates/wasmtime/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::path::Path;
use wasmparser::WasmFeatures;
#[cfg(feature = "cache")]
use wasmtime_cache::CacheConfig;
use wasmtime_environ::Tunables;
use wasmtime_environ::{ConfigTunables, Tunables};

#[cfg(feature = "runtime")]
use crate::memory::MemoryCreator;
Expand Down Expand Up @@ -145,24 +145,6 @@ pub struct Config {
pub(crate) detect_host_feature: Option<fn(&str) -> Option<bool>>,
}

#[derive(Default, Clone)]
struct ConfigTunables {
static_memory_reservation: Option<u64>,
memory_guard_size: Option<u64>,
dynamic_memory_growth_reserve: Option<u64>,
generate_native_debuginfo: Option<bool>,
parse_wasm_debuginfo: Option<bool>,
consume_fuel: Option<bool>,
epoch_interruption: Option<bool>,
static_memory_bound_is_maximum: Option<bool>,
guard_before_linear_memory: Option<bool>,
table_lazy_init: Option<bool>,
generate_address_map: Option<bool>,
debug_adapter_modules: Option<bool>,
relaxed_simd_deterministic: Option<bool>,
signals_based_traps: Option<bool>,
}

/// User-provided configuration for the compiler.
#[cfg(any(feature = "cranelift", feature = "winch"))]
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -1916,36 +1898,7 @@ impl Config {
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_reservation
memory_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
table_lazy_init
generate_address_map
debug_adapter_modules
relaxed_simd_deterministic
signals_based_traps
}
self.tunables.configure(&mut tunables);

// If we're going to compile with winch, we must use the winch calling convention.
#[cfg(any(feature = "cranelift", feature = "winch"))]
Expand Down Expand Up @@ -2318,7 +2271,6 @@ impl Default for Config {
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);

// Not every flag in WasmFeatures can be enabled as part of creating
// a Config. This impl gives a complete picture of all WasmFeatures
Expand All @@ -2339,18 +2291,7 @@ impl fmt::Debug for Config {
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_reservation {
f.field("static_memory_maximum_reservation", &size);
}
if let Some(size) = self.tunables.memory_guard_size {
f.field("memory_guard_size", &size);
}
if let Some(enable) = self.tunables.guard_before_linear_memory {
f.field("guard_before_linear_memory", &enable);
}
self.tunables.format(&mut f);
f.finish()
}
}
Expand Down

0 comments on commit 2e8ed88

Please sign in to comment.