wasmtime_environ/tunables.rs
1use anyhow::{anyhow, bail, Result};
2use serde_derive::{Deserialize, Serialize};
3use target_lexicon::{PointerWidth, Triple};
4
5/// Tunable parameters for WebAssembly compilation.
6#[derive(Clone, Hash, Serialize, Deserialize, Debug)]
7pub struct Tunables {
8 /// For static heaps, the size in bytes of virtual memory reservation for
9 /// the heap.
10 pub static_memory_reservation: u64,
11
12 /// The size in bytes of the offset guard for static heaps.
13 pub static_memory_offset_guard_size: u64,
14
15 /// The size in bytes of the offset guard for dynamic heaps.
16 pub dynamic_memory_offset_guard_size: u64,
17
18 /// The size, in bytes, of reserved memory at the end of a "dynamic" memory,
19 /// before the guard page, that memory can grow into. This is intended to
20 /// amortize the cost of `memory.grow` in the same manner that `Vec<T>` has
21 /// space not in use to grow into.
22 pub dynamic_memory_growth_reserve: u64,
23
24 /// Whether or not to generate native DWARF debug information.
25 pub generate_native_debuginfo: bool,
26
27 /// Whether or not to retain DWARF sections in compiled modules.
28 pub parse_wasm_debuginfo: bool,
29
30 /// Whether or not fuel is enabled for generated code, meaning that fuel
31 /// will be consumed every time a wasm instruction is executed.
32 pub consume_fuel: bool,
33
34 /// Whether or not we use epoch-based interruption.
35 pub epoch_interruption: bool,
36
37 /// Whether or not to treat the static memory bound as the maximum for
38 /// unbounded heaps.
39 pub static_memory_bound_is_maximum: bool,
40
41 /// Whether or not linear memory allocations will have a guard region at the
42 /// beginning of the allocation in addition to the end.
43 pub guard_before_linear_memory: bool,
44
45 /// Whether to initialize tables lazily, so that instantiation is fast but
46 /// indirect calls are a little slower. If false, tables are initialized
47 /// eagerly from any active element segments that apply to them during
48 /// instantiation.
49 pub table_lazy_init: bool,
50
51 /// Indicates whether an address map from compiled native code back to wasm
52 /// offsets in the original file is generated.
53 pub generate_address_map: bool,
54
55 /// Flag for the component module whether adapter modules have debug
56 /// assertions baked into them.
57 pub debug_adapter_modules: bool,
58
59 /// Whether or not lowerings for relaxed simd instructions are forced to
60 /// be deterministic.
61 pub relaxed_simd_deterministic: bool,
62
63 /// Whether or not Wasm functions target the winch abi.
64 pub winch_callable: bool,
65}
66
67impl Tunables {
68 /// Returns a `Tunables` configuration assumed for running code on the host.
69 pub fn default_host() -> Self {
70 if cfg!(miri) {
71 Tunables::default_miri()
72 } else if cfg!(target_pointer_width = "32") {
73 Tunables::default_u32()
74 } else if cfg!(target_pointer_width = "64") {
75 Tunables::default_u64()
76 } else {
77 panic!("unsupported target_pointer_width");
78 }
79 }
80
81 /// Returns the default set of tunables for the given target triple.
82 pub fn default_for_target(target: &Triple) -> Result<Self> {
83 match target
84 .pointer_width()
85 .map_err(|_| anyhow!("failed to retrieve target pointer width"))?
86 {
87 PointerWidth::U32 => Ok(Tunables::default_u32()),
88 PointerWidth::U64 => Ok(Tunables::default_u64()),
89 _ => bail!("unsupported target pointer width"),
90 }
91 }
92
93 /// Returns the default set of tunables for running under MIRI.
94 pub fn default_miri() -> Tunables {
95 Tunables {
96 // No virtual memory tricks are available on miri so make these
97 // limits quite conservative.
98 static_memory_reservation: 1 << 20,
99 static_memory_offset_guard_size: 0,
100 dynamic_memory_offset_guard_size: 0,
101 dynamic_memory_growth_reserve: 0,
102
103 // General options which have the same defaults regardless of
104 // architecture.
105 generate_native_debuginfo: false,
106 parse_wasm_debuginfo: true,
107 consume_fuel: false,
108 epoch_interruption: false,
109 static_memory_bound_is_maximum: false,
110 guard_before_linear_memory: true,
111 table_lazy_init: true,
112 generate_address_map: true,
113 debug_adapter_modules: false,
114 relaxed_simd_deterministic: false,
115 winch_callable: false,
116 }
117 }
118
119 /// Returns the default set of tunables for running under a 32-bit host.
120 pub fn default_u32() -> Tunables {
121 Tunables {
122 // For 32-bit we scale way down to 10MB of reserved memory. This
123 // impacts performance severely but allows us to have more than a
124 // few instances running around.
125 static_memory_reservation: 10 * (1 << 20),
126 static_memory_offset_guard_size: 0x1_0000,
127 dynamic_memory_offset_guard_size: 0x1_0000,
128 dynamic_memory_growth_reserve: 1 << 20, // 1MB
129
130 ..Tunables::default_miri()
131 }
132 }
133
134 /// Returns the default set of tunables for running under a 64-bit host.
135 pub fn default_u64() -> Tunables {
136 Tunables {
137 // 64-bit has tons of address space to static memories can have 4gb
138 // address space reservations liberally by default, allowing us to
139 // help eliminate bounds checks.
140 //
141 // Coupled with a 2 GiB address space guard it lets us translate
142 // wasm offsets into x86 offsets as aggressively as we can.
143 static_memory_reservation: 1 << 32,
144 static_memory_offset_guard_size: 0x8000_0000,
145
146 // Size in bytes of the offset guard for dynamic memories.
147 //
148 // Allocate a small guard to optimize common cases but without
149 // wasting too much memory.
150 dynamic_memory_offset_guard_size: 0x1_0000,
151
152 // We've got lots of address space on 64-bit so use a larger
153 // grow-into-this area, but on 32-bit we aren't as lucky. Miri is
154 // not exactly fast so reduce memory consumption instead of trying
155 // to avoid memory movement.
156 dynamic_memory_growth_reserve: 2 << 30, // 2GB
157
158 ..Tunables::default_miri()
159 }
160 }
161}