DECEMBER 2018 | VOL. 61 | NO. 12 | COMMUNICATIONS OF THE ACM 113
memories or tables externally, or accessing them as exports.
Interoperability. It is possible to link multiple modules
that have been created by different producers. However, as a
low-level language, WebAssembly does not provide any
built-in object model. It is up to producers to map their data
types to memory. This design provides maximum flexibility
to producers, and unlike previous VMs, does not privilege
any specific programming paradigm or object model.
Interested producers can define common ABIs on top of
WebAssembly such that modules can interoperate in heterogeneous applications. This separation of concerns is
vital for making WebAssembly universal as a code format.
A major design goal of WebAssembly has been high performance without sacrificing safety or portability. Throughout
its design process, we have developed independent implementations of WebAssembly in all major browsers to validate and inform the design decisions. This section describes
some points of interest of those implementations.
Implementation strategies. V8 (Chrome), SpiderMonkey
ahead-of-time. This achieves predictable high performance
and avoids the unpredictability of warmup time which has
lazily translates individual functions to an interpreted internal bytecode format upon first execution, and later Just In
Time ( JIT )-compiles the hottest functions. The advantage is
faster startup and potentially lower memory consumption.
We expect more strategies to evolve over time.
Validation. In the four aforementioned implementations, the same algorithmic strategy using abstract control
and operand stacks is used. Validation of incoming bytecodes occurs in a single pass during decoding, requiring no
additional intermediate representation. We measured single-threaded validation speed at between 75MB/s and
150MB/s on a suite of representative benchmarks on a modern workstation. This is approximately fast enough to perform validation at full network speed.
Baseline JIT compiler. The SpiderMonkey engine
includes two WebAssembly compilation tiers. The first is a
fast baseline JIT that emits machine code in a single pass
combined with validation. The JIT creates no Intermediate
Representation (IR) but does track register state and
attempts to do simple greedy register allocation in the forward pass. The baseline JIT is designed only for fast startup
while an optimizing JIT is compiling the module in parallel
in the background. V8 includes a similar baseline JIT in a
Optimizing JIT compiler. All four engines include opti-
reuse them for WebAssembly. Both V8 and SpiderMonkey
use SSA-based intermediate representations. As such, it was
important that WebAssembly can be decoded to SSA form in
a single pass. This is greatly helped by WebAssembly’s struc-
tured control flow, making the decoding algorithm simpler
curricula, a widely consumed standard cannot (yet) assume
that all its readers are familiar with formal notation for
semantics (unlike for syntax). Next to the formal rules, the
specification hence also contains corresponding prose.
This prose is intended to be a one-to-one “text rendering” of
the formal rules. Although the prose follows the highly verbose “pseudo-COBOL” style of other language definitions,
its eyeball proximity to a verified formalism aids spotting
bugs. Having the formal rules featured centrally in the standard document hence benefits even readers that do not
read them directly.
Reference interpreter. Along with the formalization and
production implementations in browsers, we developed a
reference interpreter for WebAssembly. For this we used
OCaml due to the ability to write in a high-level stylized fashion that closely matches the formalization, approximating
an “executable specification.” The interpreter is used to
develop the test suite, test production implementations and
the formal specification, and to prototype new features.
Proposal process. To maintain the current level of rigor
while evolving WebAssembly further, we have adopted a
multi-staged proposal process with strong requirements. At
various stages of a proposal, its champions must provide ( 1)
an informal description, ( 2) a prose specification, ( 3) a prototype implementation, ( 4) a comprehensive test suite, ( 5) a
formal specification, ( 6) an implementation in the reference
interpreter, and ( 7) two implementations in independent
The process is public on the working group’s Git repository, where specification, reference interpreter, and test
suite are hosted. Creating a proposal involves asking the
group to create a fork of the main “spec” repository and then
iterating and reviewing all required additions there.
Obviously, a formal semantics is not straightforward in
all cases. Where necessary, the working group is collaborating with research groups for non-trivial features, such as a
suitable weak memory model for the addition of threads.
4. 2. Embedding
WebAssembly is similar to a virtual Instruction Set Architecture
(ISA) in that it does not define how programs are loaded into
the execution engine or how they perform I/O. This intentional
design separation is captured in the notion of embedding a
WebAssembly implementation into an execution environment. The embedder defines how modules are loaded, how
imports and exports are resolved, how traps are handled, and
provides foreign functions for accessing the environment.
To strengthen platform-independence and encourage
other embeddings of WebAssembly, the standard has been
layered into separate documents: while the core specification only defines the virtual ISA, separate embedder specifications define its interaction with concrete host environments.
module from a given source, for example, as a network
resource, ( 2) instantiate it providing the necessary imports,
and ( 3) call the desired export functions. Since compilation
and instantiation may be slow, they are provided as