From ASM.JS to WebAssembly

tl;dr I’m burying the lede with context and catch-up material first, so impatient or already-clued-in readers should skip to below the videos for today’s big news. Or just read Luke Wagner‘s blog post right now.

My Fluent 2015 “ECMAScript Harmony: Rise of the Compilers” talk given on April 21st:

Jeremy Ashkenas picked up this ball and ran into the next field’s end zone two days later in Brooklyn:

My slides for the talk I gave at on May 15th:

Perhaps you detect a theme, beyond “JS turned 20”. Something about compilers rising, Java bytecode and asm.js, shared memory threads and SIMD. The usual retort, recurrent on Hacker News, looks like this:

In an HN sub-thread sparked by my slides, I concurred with Patrick Walton on analogies between browsers and the Unix kernel, JS and C. One does not get to write kernel code in any language, at least not yet. Elsewhere in that sub-thread the analogue of JS was identified as architecture-specific assembly code, where the CPU architecture is fixed by physical reality, while software is written in virtual languages compiled to machine code, or run through interpreters.


In any event, whether analogous to C or assembly, JS has had a lock on the “kernel” of the client side. Web “userland code”, in contrast, can be written in a great many languages. Adding a second (bytecode) syntax has looked like a “now you have two problems” loss, against the alternative of one syntax. Until now.

Today’s Big News

It’s by now a cliché that JS has become the assembly language of the Web. Rather, JS is one syntax for a portable and safe machine language, let’s say. Today I’m pleased to announce that cross-browser work has begun on WebAssembly, a new intermediate representation for safe code on the Web.

What: WebAssembly, “wasm” for short, .wasm filename suffix, a new binary syntax for low-level safe code, initially co-expressive with asm.js, but in the long run able to diverge from JS’s semantics, in order to best serve as common object-level format for multiple source-level programming languages.

It’s crucial that wasm and asm stay equivalent for a decent interval, to support polyfilling of wasm support via JS. This remains crucial even as JS and asm.js evolve to sprout shared memory threads and SIMD support. Examples of possible longer-term divergence: zero-cost exceptions, dynamic linking, call/cc. Yes, we are aiming to develop the Web’s polyglot-programming-language object-file format.

Why: asm.js is great, but once engines optimize for it, the parser becomes the hot spot — very hot on mobile devices. Transport compression is required and saves bandwidth, but decompression before parsing hurts. A secondary consideration: JS has a few awkward corners even in its asm.js subset. Finally, once browsers support the WebAssembly syntax natively, JS and wasm can diverge, without introducing unsafe or inappropriate features into JS just for use by compilers sourcing a few radically different programming languages.

See the FAQ for more nuance and detail. No, JS isn’t going away in any foreseeable future. Yes, wasm should relieve JS from having to serve two masters. This is a win-win plan.

How: If you use Emscripten, then wasm support via a command-line flag will at first include and target the prototype polyfill. But as native wasm decoders appear in top engines (see the V8 native prototype decoder), Emscripten will auto-configure for best results. Another prototype: a JS AST compressor (encoder).

These prototypes will evolve and track draft specification changes as WebAssembly matures and receives progressively more developer testing. Other compilers than Emscripten, and other compiler frameworks than LLVM, will join the mix. I expect all engines will support fast native decoders. All these parts are means to the end of a common WebAssembly standard.

Who: A W3C Community Group, the WebAssembly CG, open to all. As you can see from the github logs, WebAssembly has so far been a joint effort among Google, Microsoft, Mozilla, and a few other folks. I’m sorry the work was done via a private github account at first, but that was a temporary measure to help the several big companies reach consensus and buy into the long-term cooperative game that must be played to pull this off.

Here you can see JF Bastien of Google’s PNaCl team barely able to keep a lid on the secret. Good thing I replied with a comic book reference as plausible cover. Close one! 😀


Having both the PNaCl team and the V8 team from Google, along with key people from Microsoft and the asm.js and Emscripten gurus from Mozilla, collaborating closely once everyone saw the light, has been inspiring. I’d like to single out for highest praise JF Bastien, K. Gadd, and Ben Titzer of Google; Dan Gohman of Mozilla; Abhijith Chatra and Michael Holman of Microsoft; Alon Zakai of asm.js & Emscripten fame; Filip Pizlo for JavaScriptCore/WebKit; and especially asm.js/OdinMonkey mastermind Luke Wagner.

The Big Picture

In the history of computing, the dream of a universal, language-neutral intermediate form goes back to well before Melvin Conway‘s UNCOL (1958, the same year LISP was born). I remember ANDF from the ’80s, and U-something from the ’70s. No one wants the “N x M” language sources vs. machine targets problem.

Sometimes we must take a trip or two around Fortuna’s Wheel before falling into success. Neurons appear to have evolved more than once. Believe me, I find it ha-ha funny that lowly JS (which I did not plan out this far in advance!) has paved the evo-path to WebAssembly. Yet here we are.

Although it won’t be the only compiler framework used to generate wasm, LLVM has been a boon to this project, as to wasm’s Emscripten and PNaCl progenitors. Kudos to Chris Lattner and team.

The PNaCl folks I know are good natured, but I think some are sore at me for playing Cassandra to their Troy over the years on HN. So I want to give them major credit for wringing much undefined behavior (UB) out of LLVM — really out of all levels of abstraction, from C/C++ specs down to hardware. That kind of thankless work is a big help for WebAssembly, which must be mostly-determinstic and well-defined, for interoperation and security.

(Astute readers will have by this point recalled The Birth & Death of JavaScript by Gary Bernhardt. I live to troll Gary. 😉

Bottom line: with co-evolution of JS and wasm, in a few years I believe all the top browsers will sport JS engines that have become truly polyglot virtual machines. I predict that JS over the same timespan will endure and evolve to absorb more APIs and hardware-based affordances — but not all, where wasm carries the weight.

Again we see how the Web favors a succession of “little bangs”:

  • to hold community consensus along the evolutionary path, by
  • testing each hop for fitness with developers and implementors, and
  • supporting usable polyfills for older deployed browsers.

I usually finish with a joke: “Always bet on JS”. I look forward to working “and wasm” into that line — no joke.