@callahad

WebAssembly

(Do we all have to learn C now?)

Dan Callahan / @callahad

Slides derived from a deck by
Luke Wagner / @luke_wagner

(Mozillian, Co-chair WebAssembly W3C Community Group)

Outline

  • What is WebAssembly
  • Tour of WebAssembly
  • WebAssembly APIs
  • Beyond compiling C/C++
  • Frequently Asked Questions

What is WebAssembly?

A portable format for binaries on the Web
emphasizing safety, speed, and size

WebAssembly is Many Things

Depending on where you're coming from:

  1. Compiler Target
  2. Virtual ISA
  3. JavaScript Feature
  4. Evolution of Asm.js

1. Compiler Target for the Web

Not a programming language

Compile from programming languages

2. Virtual ISA

As close to physical machine instructions as safety/portability allow

WebAssembly x86 ARM
i32.add addl ADD
call call BL
i32.load check + mov check + LDR

3. JavaScript Feature

Efficient loading / caching of large programs

+

Predictable, near-native performance

=

Powerful library-building tool

Why would you want that?

Websites are already using compiled libraries for:

  • Client-Side Image Compression / Filters
  • Facial Recognition
  • Cryptography
  • Audio Mixing
  • Media Decoders
  • Games
  • Simulations

4. Evolution of Asm.js

(tl;dr - asm.js is an extraordinarily optimizable, low-level subset of JavaScript that can be compiled from languages like C/C++ and shipped on the Web today)

Motivations for Asm.js

  • Avoid Plugins (Deprecation, Security, Portability)
  • Port large, existing applications
  • Port high-performance C/C++ libraries
  • Provide predictable performance

Short History of Asm.js

2009 Mozilla Research experiments:
Emscripten: C/C++ to JS compiler/toolchain
asm.js: optimize Emscripten-style output
2013 Published asm.js subset, shipped optimizations in Firefox, demonstrated on large game engines
2015

Adobe, AutoDesk, Epic, Facebook, Mega, Unity, and more shipping with Emscripten/asm.js

Asm.js Today

Shipping in Firefox and Edge

Under development in Chrome and Safari

Limitations of Asm.js

  • Large File Sizes
  • Long Parse / Load Times
  • Potential for Lower Runtime Memory Use
  • Potential for Even Greater Performance

A Binary Encoding of Asm.js

asm.js WebAssembly
(x+y)|0 i32.add 0x40
(emulate) i64.add 0x5b
f(x|0)|0 call $f 0x16
HEAP32[i>>2]|0 i32.load 0x2a

A Tour of WebAssembly

WebAssembly is a Work In Progress


Successful interop between Firefox, Chrome, and Edge!

Specifying and shipping iteratively, like JavaScript.
Goal for first release: Compile C/C++, and be a better asm.js.

We can polyfill wasm with asm!

The whole text format is under construction

Examples use a temporary S-Expression syntax:

View Source in your browser may look different

Other things that are speculative
or not yet implemented are marked ☃

Start with some C code:


// demo.c
int add(int a, int b) {
    return a + b;
}
                    

☃ then compile to wasm:


☃ clang -mwasm demo.c -o demo.wasm
                    

Render the binary as text:


$ wasm-dis demo.wasm
                    

(module
    (export "add" $add)
    (func $add (param $0 i32) (param $1 i32) (result i32)
        (i32.add
            (get_local $0)
            (get_local $1)
        )
    )
)
                    

Today, we load the wasm via JS API:


fetch('demo.wasm')
.then(response => response.arrayBuffer())
.then(buffer => {
    let bytes = new Uint8Array(buffer);
    let instance = Wasm.instantiateModule(bytes);
    alert("1 + 2 = " + instance.exports.add(1, 2));
});
                    

☃ In the future, with ES6 Module integration:



                    

Demo!

  1. Open the Debugger
  2. Click the wasm source

WebAssembly can call JavaScript too!


// main.c
extern void logInt(int);
int main() {
    logInt(42);
}
                    

then compile to wasm:


☃ clang -mwasm main.c -o main.wasm
                    

Rendering the binary as text:


$ wasm-dis main.wasm
                    

(module
    (import "imports" "logInt" (param i32))
    (func $main (call_import 0 (i32.const 42)))
    (start $main)
)
                    

☃ Write an ES6 module which is called by wasm:


// imports.js
export var logInt = i => console.log(i);
                    

☃ Load the wasm from a <script type='module'> tag:



                    

Or, pass functions to the JS API:


var wasmBytes = ...;
var imports = { logInt: i => console.log(i) };
Wasm.instantiateModule(wasmBytes, { imports });
                    

WebAssembly APIs

On a traditional virtual platform:

 

On a modern Web browser:

The Web is starting to resemble a traditional virtual platform

... with some special "Webby" properties like:

... open standards, multiple implementations, etc

Q: So what are WebAssembly APIs? A: Web APIs!

This is a key difference from plugin architectures

Web API integration

Today, WebAssembly only gets to Web APIs by
"thunking" through JavaScript

☃ In the future, support calling Web APIs directly

Web API integration

Emscripten maps common C/C++ interfaces to Web APIs

For example, using libc and SDL:


#include <SDL/SDL.h>
#include <stdio.h>

int main(int argc, char **argv) {
  SDL_Init(SDL_INIT_VIDEO);
  SDL_Surface *s = SDL_SetVideoMode(200, 200, 32, SDL_HWSURFACE);
  SDL_Rect rect = { 50, 50, 100, 100 };
  SDL_FillRect(s, &rect, 0xffff0000);
  printf("Done!\n");
  return 0;
}
                    

Compiled by Emscripten with:


    $ emcc -O2 test.c -o test.html
                    

Web API integration

Which produces a default HTML harness:

Beyond just C/C++

Beyond just C/C++

Currently, WebAssembly only has linear memory

Great if your language has a low-level memory model

But if your language has GC:

  • would need to implement/ship your own GC
  • which misses optimizations in browser GC
  • cannot collect cycles involving browser objects

Beyond just C/C++

To provide first-class support for GC languages, WebAssembly needs direct GC access

☃ Goal: add low-level GC primitives to avoid baking in one language's class model

☃ Goal: share GC heap with JS, allow objects/strings/values to flow back and forth

Beyond just C/C++

Also need some fundamental extensions
to the (shared JS + WebAssembly) GC:

  • Typed Objects
  • Postmortem Notification
  • Weak References

Beyond just C/C++

Need even more features in WebAssembly to
run dynamic languages efficiently:

  • Patching: immediates, branch targets, return address, ...
  • Fine-grained (stub) compilation
  • Good dynamic/any value support

Check the roadmap for plans

FAQ

How do I compile to wasm now?

Use the asm.js toolchain

C/C++ → Emscripten (LLVM) → Binaryen

Add a WebAssembly backend

When Can I Use WebAssembly?

Still iterating, and we'll need time for
review and feedback once the spec stabilizes

The first browsers are likely to ship this year

How will WebAssembly be Used?

Hard to predict, but we can extrapolate from asm.js today:

What about source maps?

Critical for compiled languages to feel "first class"

...Experiments are ongoing

What if I compile my JS to Wasm?

Not useful. You'd have to reimplement a JS engine in wasm.

Your browser already has a really good one of those.

Will WebAssembly Replace JS?

No. Why?

  • JS has huge and growing momentum, vibrant ecosystem
  • JS remains the privileged, built-in language of the Web
  • Many Web APIs designed specifically for JS


In fact, WebAssembly may have quite the opposite effect:

If you're targeting WebAssembly and your app needs a scripting language, JS is the natural choice...

Thanks! Questions?

More info at webassembly.github.io

Dan Callahan / @callahad