Skip to content

Latest commit

 

History

History
52 lines (32 loc) · 3.38 KB

RATIONALE.md

File metadata and controls

52 lines (32 loc) · 3.38 KB

Notable rationale of wazero

wazeroir

wazero's intermediate representation (IR) is called wazeroir. Compiling into an IR provides us a faster interpreter and a building block for a future JIT compilation engine. Both of these help answer demands for a more performant runtime vs interpreting Wasm directly (the naivevm interpreter).

Intermediate Representation (IR) design

wazeroir's initial design borrowed heavily from the defunct microwasm format (a.k.a. LightbeamIR). Notably, wazeroir doesn't have block operations: this simplifies the implementation.

Note: microwasm was never specified formally, and only exists in a historical codebase of wasmtime: https://github.com/bytecodealliance/wasmtime/blob/v0.29.0/crates/lightbeam/src/microwasm.rs

Implementation limitations

WebAssembly 1.0 (MVP) specification allows runtimes to limit certain aspects of Wasm module or execution.

wazero limitations are imposed pragmatically and described below.

Number of functions in a store

The possible number of function instances in a store is not specified in the WebAssembly specifications since funcaddr corresponding to a function instance can be arbitrary number. wazero limits the maximum function instances to 2^27 as even that number would occupy 1GB in function pointers.

That is because not only we believe that all use cases are fine with the limitation, but also we have no way to test wazero runtimes under these unusual circumstances.

Number of function types in a store

There's no limitation on the number of function types in a store according to the spec. In wazero implementation, we assign each function type to a unique ID, and choose to use uint32 to represent the IDs. Therefore the maximum number of function types a store can have is limited to 2^27 as even that number would occupy 512MB just to reference the function types.

This is due to the same reason for the limitation on the number of functions above.

Number of values on the stack in a function

While the the spec does not clarify a limitation of function stack values, wazero limits this to 2^27 = 134,217,728. The reason is that we internally represent all the values as 64-bit integers regardless of its types (including f32, f64), and 2^27 values means 1 GiB = (2^30). 1 GiB is the reasonable for most applications as we see a Goroutine has 250 MB as a limit on the stack for 32-bit arch, considering that WebAssembly is (currently) 32-bit environment.

All the functions are statically analyzed at module instantiation phase, and if a function can potentially reach this limit, an error is returned.

Number of globals in a module

Theoretically, a module can declare globals (including imports) up to 2^32 times. However, wazero limits this to 2^27(134,217,728) per module. That is because internally we store globals in a slice with pointer types (meaning 8 bytes on 64-bit platforms), and therefore 2^27 globals means that we have 1 GiB size of slice which seems large enough for most applications.

JIT engine implementation

See wasm/jit/RATIONALE.md.