1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
use serde::{Deserialize, Serialize};

/// Tunable parameters for WebAssembly compilation.
#[derive(Clone, Hash, Serialize, Deserialize)]
pub struct Tunables {
    /// For static heaps, the size in wasm pages of the heap protected by bounds checking.
    pub static_memory_bound: u64,

    /// The size in bytes of the offset guard for static heaps.
    pub static_memory_offset_guard_size: u64,

    /// The size in bytes of the offset guard for dynamic heaps.
    pub dynamic_memory_offset_guard_size: 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,

    /// Whether or not to generate native DWARF debug information.
    pub generate_native_debuginfo: bool,

    /// Whether or not to retain DWARF sections in compiled modules.
    pub parse_wasm_debuginfo: bool,

    /// Whether or not to enable the ability to interrupt wasm code dynamically.
    ///
    /// More info can be found about the implementation in
    /// crates/environ/src/cranelift.rs. Note that you can't interrupt host
    /// calls and interrupts are implemented through the `VMInterrupts`
    /// structure, or `InterruptHandle` in the `wasmtime` crate.
    pub interruptable: 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 we use epoch-based interruption.
    pub epoch_interruption: 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 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,
}

impl Default for Tunables {
    fn default() -> Self {
        let (static_memory_bound, static_memory_offset_guard_size) =
            if cfg!(target_pointer_width = "64") {
                // 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,

            // 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: 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.
            #[cfg(target_pointer_width = "64")]
            dynamic_memory_growth_reserve: 2 << 30, // 2GB
            #[cfg(target_pointer_width = "32")]
            dynamic_memory_growth_reserve: 1 << 20, // 1MB

            generate_native_debuginfo: false,
            parse_wasm_debuginfo: true,
            interruptable: false,
            consume_fuel: false,
            epoch_interruption: false,
            static_memory_bound_is_maximum: false,
            guard_before_linear_memory: true,
            generate_address_map: true,
        }
    }
}