Author:
ADoyle/蔡博文
(其实我没想好名字)
Free-Control Version
Live Version
// strict & sloppy modes
function test1() {
arguments[0] = 0;
}
// strict & sloppy modes
function test4() {
var args = [].slice.call(arguments);
}
C/C++ => LLVM => asm.js
function GeometricMean(stdlib, foreign, buffer) {
"use asm";
var exp = stdlib.Math.exp;
var log = stdlib.Math.log;
var values = new stdlib.Float64Array(buffer);
function logSum(start, end) {
start = start|0;
end = end|0;
var sum = 0.0, p = 0, q = 0;
// asm.js forces byte addressing of the heap by requiring shifting by 3
for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {
sum = sum + +log(values[p>>3]);
}
return +sum;
}
function geometricMean(start, end) {
start = start|0;
end = end|0;
return +exp(+logSum(start, end) / +((end - start)|0));
}
return { geometricMean: geometricMean };
}
// 64k heap
var heap = new ArrayBuffer(0x10000);
// fill a region with input values
init(heap, START, END);
// produce exports object linked to AOT-compiled code
var fast = GeometricMean(window, null, heap);
// computes geometric mean of input values
fast.geometricMean(START, END);
LLVM bitcode to JS
AOT
避免运行时类型检查
基于 TypedArray 的虚拟 heap
显式定义整数与浮点数(强类型)
x | 0
当 AOT 失败,可以退化到 JIT
优化场景有限
只限于整数、浮点数计算,二进制数组优化
浏览器支持有限
http://caniuse.com/#feat=asmjs
LLVM to asm.js compiler
OpenGL to WebGL or HTML5 API
C/C++ => LLVM => PNaCl Bitcode
asm.js enhanced = WebAssembly
C/C++ => LLVM => wasm
or
asm.js => wasm
54 movq rax,rsi ;; Dead code.
57 movq rbx,[rbp-0x28]
61 testb rbx,0x1
64 jnz 189 (0x7f7b20fa2a7d)
70 shrq rbx,32
74 movq rdx,[rbp-0x30]
78 testb rdx,0x1
81 jnz 237 (0x7f7b20fa2aad)
87 shrq rdx,32
91 movq rcx,[rbp-0x18]
95 xchgq rax, rdx
A binary format for JS, all JS, not only asm.js.
It's not a bytecode,
it's a binary encoding of the AST that the parser calculates.
benefits:
In s-expression (.wast)
(module
(import $i1 "m" "import1")
(import $i2 "import2" "")
(func $main (call_import $i1))
(start $main)
(func $f (call_import $i2))
(export "f" $f)
)
WebAssembly code is represented as an
Abstract Syntax Tree (AST)
Binary Encoding
Text Format
memory {
temp: zero 4;
scale: hex 02000000;
}
func ifelse(cond i32, a i32, b i32) i32 {
storeI32(temp, 10);
if (cond) {
return a > b;
} else {
return a < b;
}
}
export func main() i32 {
storeI32(temp, 0);
var i i32 = 0;
done: while (i < 10) {
i = i + 1;
if (i >= 7) {
break done;
}
}
return (i + ifelse(0, 1, 2) * 2) * loadI32(temp) + loadI32(scale);
}
In wasm format (.wasm)
Q: 执行效率还是那么低,有意义吗?
如果你使用 chrome 浏览器,通过 chrome://flags/ 开启 webassembly 选项
Three.js, Canvas, OpenGL ES...
Single Instruction Multiple Data
var a = [1, 2, 3, 4];
var b = [5, 6, 7, 8];
var c = [];
c[0] = a[0] + b[0];
c[1] = a[1] + b[1];
c[2] = a[2] + b[2];
c[3] = a[3] + b[3];
c; // Array[6, 8, 10, 12]
var a = SIMD.Float32x4(1, 2, 3, 4);
var b = SIMD.Float32x4(5, 6, 7, 8);
// Float32x4[6, 8, 10, 12]
var c = SIMD.Float32x4.add(a,b);
SIMD
var a = [1, 2, 3, 4];
var b = [5, 6, 7, 8];
var c = [];
for (var i = 0; i < 4; i++) {
if (a[i] < 3) {
c[i] = a[i] * b[i];
} else {
c[i] = b[i] + a[i];
}
}
console.log(c); // [5, 12, 10, 12]
var a = SIMD.Float32x4(1, 2, 3, 4);
var b = SIMD.Float32x4(5, 6, 7, 8);
var mask = SIMD.Float32x4.lessThan(a, SIMD.Float32x4.splat(3));
// Bool32x4[true, true, false, false]
var result = SIMD.Float32x4.select(
mask,
SIMD.Float32x4.mul(a, b),
SIMD.Float32x4.add(a, b)
);
console.log(result); // Float32x4[5, 12, 10, 12]
SIMD
讲了那么多概念,你究竟想说什么?
asm.js
Emscripten
PNaCl
wasm
ArrayBuffer
TypedArray
WebGL
SIMD
IoT
WebGame Engine
JS is more universal