Slides derived from a deck by
Luke Wagner / @luke_wagner
(Mozillian, Co-chair WebAssembly W3C Community Group)
A portable format for binaries on the Web
emphasizing safety, speed, and size
Depending on where you're coming from:
Not a programming language
Compile from programming languages
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 |
Efficient loading / caching of large programs
+
Predictable, near-native performance
=
Powerful library-building tool
Websites are already using compiled libraries for:
Motivations for 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 | 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 |
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:
wasm
sourceWebAssembly 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 });
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
Today, WebAssembly only gets to Web APIs by
"thunking" through JavaScript
☃ In the future, support calling Web APIs directly
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
Which produces a default HTML harness:
Currently, WebAssembly only has linear memory
Great if your language has a low-level memory model
But if your language has GC:
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
Also need some fundamental extensions
to the (shared JS + WebAssembly) GC:
Need even more features in WebAssembly to
run dynamic languages efficiently:
Check the roadmap for plans
Use the asm.js toolchain
C/C++ → Emscripten (LLVM) → Binaryen
Add a WebAssembly backend
Still iterating, and we'll need time for
review and feedback once the spec stabilizes
The first browsers are likely to ship this year
Hard to predict, but we can extrapolate from asm.js today:
Critical for compiled languages to feel "first class"
...Experiments are ongoing
Not useful. You'd have to reimplement a JS engine in wasm.
Your browser already has a really good one of those.
No. Why?
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...
More info at webassembly.github.io