@@ -366,48 +366,84 @@ and generated code need to handle.
366366First there are a number of properties about linear memory which can be
367367configured:
368368
369- * ` wasmtime::Config::static_memory_maximum_size `
370- * ` wasmtime::Config::static_memory_guard_size `
371- * ` wasmtime::Config::dynamic_memory_guard_size `
369+ * ` wasmtime::Config::memory_reservation `
370+ * ` wasmtime::Config::memory_may_move `
371+ * ` wasmtime::Config::memory_guard_size `
372+ * ` wasmtime::Config::memory_reservation_for_growth `
373+ * ` wasmtime::Config::memory_init_cow `
372374* ` wasmtime::Config::guard_before_linear_memory `
375+ * ` wasmtime::Config::signals_based_traps `
373376
374377The methods on ` Config ` have a good bit of documentation to go over some
375- nitty-gritty, but the general gist is that Wasmtime has two modes of memory:
376- static and dynamic. Static memories represent an address space reservation that
377- never moves and pages are committed to represent memory growth. Dynamic
378- memories represent allocations where the committed portion exactly matches the
379- wasm memory's size and growth happens by allocating a bigger chunk of memory.
380-
381- The guard size configuration indicates the size of the guard region that
382- happens after linear memory. This guard size affects whether generated JIT code
383- emits bounds checks or not. Bounds checks are elided if out-of-bounds addresses
384- provably encounter the guard pages.
385-
386- The ` guard_before_linear_memory ` configuration additionally places guard pages
387- in front of linear memory as well as after linear memory (the same size on both
388- ends). This is only used to protect against possible Cranelift bugs and
389- otherwise serves no purpose.
390-
391- The defaults for Wasmtime on 64-bit platforms are:
392-
393- * 4GB static maximum size meaning all 32-bit memories are static and 64-bit
394- memories are dynamic.
395- * 2GB static guard size meaning all loads/stores with less than 2GB offset
396- don't need bounds checks with 32-bit memories.
397- * Guard pages before linear memory are enabled.
398-
399- Altogether this means that 32-bit linear memories result in an 8GB virtual
400- address space reservation by default in Wasmtime. With the pooling allocator
401- where we know that linear memories are contiguous this results in a 6GB
402- reservation per memory because the guard region after one memory is the guard
403- region before the next.
404-
405- Note that 64-bit memories (the memory64 proposal for WebAssembly) can be
406- configured to be static but will never be able to elide bounds checks at this
407- time. This configuration is possible through the ` static_memory_forced `
408- configuration option. Additionally note that support for 64-bit memories in
409- Wasmtime is functional but not yet tuned at this time so there's probably still
410- some performance work and better defaults to manage.
378+ nitty-gritty. Wasmtime also has some ` #[cfg] ` directives which are calculated by
379+ ` crates/wasmtime/build.rs ` which affects the defaults of various strategies. For
380+ example ` has_native_signals ` means that segfaults are allowed to happen at
381+ runtime and are caught in a signal handler. Additionally ` has_virtual_memory `
382+ means that ` mmap ` is available and will be used (otherwise a fallback to
383+ ` malloc ` is implemented). The matrix of all of these combinations is then used
384+ to implement a linear memory for a WebAssembly instance.
385+
386+ It's generally best to consult the documentation of ` Config ` for the most
387+ up-to-date information. Additionally code comments throughout the codebase can
388+ also be useful for understanding the impact of some of these options. Some
389+ example scenarios though are:
390+
391+ * ** ` (memory 1) ` on 64-bit platforms** - by default this WebAssembly memory has
392+ unlimited size, meaning it's only limited by its index type (` i32 ` ) meaning it
393+ can grow up to 4GiB if the host/embedder allows it. This is implemented with a
394+ 8GiB virtual memory reservation -- 2GiB unmapped before linear memory, 4GiB
395+ for linear memory itself (but only 1 wasm page, 64KiB, read/write at the
396+ start), and 2GiB unmapped afterwards. The guard region before linear memory is
397+ a defense-in-depth measure and should never be hit under any operation. The
398+ guard region after linear memory is present to eliminate bounds checks in the
399+ wasm module (WebAssembly addresses are effective 33-bit addresses when the
400+ static ` offset ` is taken into account).
401+
402+ * ** ` (memory i64 1) ` on 64-bit platforms** - this WebAssembly memory uses 64-bit
403+ indexes instead of 32-bit indexes. This means that the configuration looks
404+ similar to ` (memory 1) ` above except that growth beyond 4GiB will copy all the
405+ contents of linear memory to a new location. Embedders might want to raise
406+ ` Config::memory_reservation ` in this situation. This configuration mode cannot
407+ remove any bounds checks, but guard pages are still used to deduplicate bounds
408+ checks where possible (so segfaults may still be caught at runtime for
409+ out-of-bounds accesses).
410+
411+ * ** ` (memory 1) ` on 64-bit platforms with the pooling allocator** - the pooling
412+ allocator has a few important differences than the default settings. First is
413+ that the pooling allocator is able to "overlap" the before/after guard regions
414+ meaning that the virtual memory cost per-linear-memory is 6GiB by default
415+ instead of 8GiB. Additionally the pooling allocator cannot resize memory so if
416+ ` Config::memory_reservation ` is less than 4GiB then that's a hard limit on the
417+ size of linear memory rather than being able to copy to a new location.
418+
419+ * ** ` (memory 1) ` on 64-bit platforms with a smaller reservation** - if the
420+ ` Config::memory_reservation ` option is configured less than the default (the
421+ default is 4GiB) then the virtual memory allocated for all linear memories
422+ will be less than the 8GiB default. This means that linear memories may move
423+ over time if they grow beyond their initial limit (assuming such growth is
424+ allowed) and additionally bounds checks will be required for memory accesses.
425+
426+ * ** ` (memory 1) ` on 32-bit platforms** - unlike 64-bit platforms this memory
427+ cannot have a 4GiB virtual memory reservation. Instead the linear memory is
428+ allocated with ` Config::memory_reservation_for_growth ` unmapped bytes after it
429+ to amortize the reallocation overhead of copying bytes. Guard pages are still
430+ used and signals are used where available to deduplicate bounds checks.
431+
432+ * ** ` (memory 1 (pagesize 1)) ` on any platforms** - this WebAssembly linear
433+ memory, with a page size of 1 byte, means that virtual memory cannot be used
434+ to catch traps. Instead explicit bounds checks are always required on all
435+ accesses. This is still allocated with virtual memory where possible, however.
436+
437+ There's quite a few possible combinations for how all of these options interact
438+ with each other. The high-level design goal of Wasmtime is such that each option
439+ is independent from all the others and is a knob for just its behavior. In this
440+ way it should be possible to customize the needs of embedders. Wasmtime
441+ additionally has different default behavior across platforms, such as 32-bit and
442+ 64-bit platforms. Some platforms additionally don't have ` mmap ` by default and
443+ Wasmtime will adapt to that as well. The intention, however, is that it should
444+ be possible to mirror the default configuration on any platform into a
445+ "full-featured" platform such as 64-bit to assist with testing, fuzzing, and
446+ debugging.
411447
412448## Tables and ` externref `
413449
0 commit comments