JS 漫谈

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);
}

那些编译到 JS 的语言

  • CoffeeScript
  • TypeScript
  • ClojureScript
  • Google Web Toolkit (GWT), Java to JS
  • pyjamas, Python into JS
  • ......

asm.js

&
Emscripten

C/C++ => LLVM => asm.js

Define an asm.js module

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);

Invoke the module

asm.js

  • LLVM bitcode to JS

  • AOT

    • 避免运行时类型检查

    • 基于 TypedArray 的虚拟 heap

  • ​显式定义整数与浮点数(强类型)

    • ​x | 0

  • 当 AOT 失败,可以退化到 JIT

Pros

Cons

  • 优化场景有限

    • 只限于整数、浮点数计算,二进制数组优化

  • 浏览器支持有限

http://caniuse.com/#feat=asmjs

Emscripten

LLVM to asm.js compiler

OpenGL to WebGL or HTML5 API

PNaCl

(Portable Native Client)

C/C++ => LLVM => PNaCl Bitcode

WebAssembly

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:

  • the JS engine can skip the parsing step
  • it's much more compact than the JS original source

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)

  • 设计一个可移植,体积小,加载快的二进制格式
  • 设计人类友好可读的文本格式
  • 多平台
    • Browser
    • Android
    • iOS
    • NodeJS
    • IoT
  • 优化解码和解析速度
  • 兼容性
    • 兼容现有的 web 平台
    • 与 JavaScript 在相同的语义领域下执行

实质

  • 基于现有的 JavaScript 引擎 + wasm 解析器
  • 服务端提前编译
  • 重点在优化代码解析效率 (decode + parse),
    而非代码执行效率 (execute)

意义

Q: 执行效率还是那么低,有意义吗?

Demo

如果你使用 chrome 浏览器,通过 chrome://flags/  开启 webassembly 选项

ArrayBuffer

&

TypedArray

WebGL

Three.js, Canvas, OpenGL ES...

SIMD

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

嵌入式/物联网

  • duktape
    • embeddable Javascript engine with a focus on portability and compact footprint
  • Tessel

游戏引擎

JS 正在进化

  • Typescript
  • Web App
  • Hybrid App
  • Web Game
  • IoT

讲了那么多概念,你究竟想说什么?

asm.js
Emscripten

PNaCl

wasm

ArrayBuffer

TypedArray

WebGL

SIMD

IoT

WebGame Engine

JS is more universal

JavaScript maybe not 

But it's fun

the best

Made with Slides.com