WASM is not quite a stack machine
A deep dive challenges the widespread belief that WebAssembly (Wasm) is a stack machine, arguing that its lack of stack manipulation instructions forces a register-machine-like approach for complex operations. This nuanced technical analysis offers a fresh perspective on Wasm's underlying architecture, appealing to developers and compiler enthusiasts on HN. The author's hands-on discovery and clear examples highlight a fundamental distinction often overlooked in its design.
The Lowdown
The author critically examines the common understanding that WebAssembly (Wasm) operates as a stack machine, a classification often found in official documentation and common discourse. Through the experience of writing Wasm instructions manually, the author uncovers a crucial difference that suggests this widespread belief is misleading.
- Register vs. Stack Machines: The article begins by defining and contrasting register machines (like x86 assembly, which use explicit variables/registers) and stack machines (like Forth, which implicitly manage values on a stack). Both are illustrated with examples for complex arithmetic expressions.
- The Need for Stack Manipulation: True stack machines, to efficiently reuse values and perform complex operations, rely heavily on stack manipulation instructions such as
dup(duplicate),swap, anddrop. Without these, expressions requiring value reuse become cumbersome or impossible. - Wasm's Instruction Set Anomaly: A comparison of Wasm's instruction set with that of the JVM (a well-known stack machine) reveals Wasm's striking lack of such stack rearrangement operations, beyond a basic
dropinstruction primarily for discarding function outputs. - Forced Register-like Behavior: This deficiency means that for anything beyond the simplest, sequential expressions, Wasm effectively forces the use of local variables (registers). The author argues that this design fundamentally transforms Wasm into a register machine for practical purposes, despite its RPN encoding.
- Encoding vs. Semantics: The use of Reverse Polish Notation (RPN) in Wasm's binary format is presented as merely an encoding choice, not an inherent architectural feature, as evidenced by its LISP-like textual representation. This suggests the RPN was chosen for interpreter simplicity rather than defining a true stack machine.
- Historical Context of Multi-value: The historical context of Wasm's
multi-valueextension further supports the argument, showing how control flow blocks originally had limited stack interaction, necessitating explicit local variable usage.
In conclusion, the author posits that while Wasm's simple, stack-based implementation might have aided its adoption, it is fundamentally "not quite a stack machine." This distinction is crucial for developers, as it implies that prior experience with traditional stack-based VMs may not directly apply when working with Wasm's unique architecture.