Top Banner
asm.js x Emscripten: The foundation of the next l eve l web games Mozi ll a Japan テクニカルマーケティング 清水智公 (nshimizu @ mozi ll a-japan.org / @ chikoski) 第6 3 HTML5 とか勉強会 with html 5j ゲーム部発足記念合同勉強会
95

asm.js x emscripten: The foundation of the next level Web games

Apr 15, 2017

Download

Technology

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: asm.js x emscripten: The foundation of the next level Web games

asm.js x Emscripten: The foundation of the next level web games

Mozilla Japan テクニカルマーケティング 清水智公 ([email protected] / @chikoski)

第63回 HTML5とか勉強会 with html5jゲーム部発足記念合同勉強会

Page 2: asm.js x emscripten: The foundation of the next level Web games

N. Shimizu

• Mozilla Japan (L10N, Game, Devtools, Web Animation)

• html5j Web プラットフォーム部、

Firefox OS、Firefox OS コードリーディング、

html5j ゲーム部 (NEW!)

• @chikoski

• プログラミング言語、分類、ベイジアン、サッカー、圏論(NEW!)

Page 3: asm.js x emscripten: The foundation of the next level Web games
Page 4: asm.js x emscripten: The foundation of the next level Web games
Page 5: asm.js x emscripten: The foundation of the next level Web games
Page 7: asm.js x emscripten: The foundation of the next level Web games
Page 8: asm.js x emscripten: The foundation of the next level Web games
Page 11: asm.js x emscripten: The foundation of the next level Web games
Page 12: asm.js x emscripten: The foundation of the next level Web games

文字列 実行コード

Page 13: asm.js x emscripten: The foundation of the next level Web games

文字列 実行コード抽象構文木トークン列 中間表現

字句解析 構文解析 意味解析 最適化・コード生成

Page 14: asm.js x emscripten: The foundation of the next level Web games

文字列 実行コード抽象構文木トークン列 中間表現

字句解析 構文解析 意味解析 最適化・コード生成

Page 15: asm.js x emscripten: The foundation of the next level Web games
Page 16: asm.js x emscripten: The foundation of the next level Web games

文字列 AST バイトコード字句解析 / 構文解析 生成

実行

* AST: Abstract Syntax Tree / 抽象構文木

Page 17: asm.js x emscripten: The foundation of the next level Web games

function addOne(a){ return a + 1;}

Page 18: asm.js x emscripten: The foundation of the next level Web games

loc op----- --main:00000: getarg 000003: one00004: add00005: return00006: retrval

Page 19: asm.js x emscripten: The foundation of the next level Web games

aのデータ型 a + 1 のデータ型

number number

undefined number

null number

string string

object string

Page 20: asm.js x emscripten: The foundation of the next level Web games

Just In Time Compile

Page 21: asm.js x emscripten: The foundation of the next level Web games

データ型Data Type

Page 22: asm.js x emscripten: The foundation of the next level Web games
Page 23: asm.js x emscripten: The foundation of the next level Web games

文字列字句解析 / 構文解析

実行

バイトコードASTBaseline

Compiled Code

MIRIron

Compiled Code

実行と プロファイル 実行Bail

生成Baseline Compile

Iron BuildIron Compile

* AST: Abstract Syntax Tree / 抽象構文木  MIR: Medium-level Intermediate Representation / 中間表現

Page 24: asm.js x emscripten: The foundation of the next level Web games

* AST: Abstract Syntax Tree / 抽象構文木  MIR: Medium-level Intermediate Representation / 中間表現

文字列字句解析 / 構文解析

実行

バイトコードASTBaseline

Compiled Code

MIRIron

Compiled Code

実行と プロファイル 実行Bail

生成Baseline Compile

Iron BuildIron Compile• JITは重い

• hot code(よく実行されるコード)しかコンパイルされない

• JITが始まるまでは、遅いまま • 型推論に失敗するなどして、JITをやり直すことがある

ダウンロード 実行開始 コンパイル

Page 25: asm.js x emscripten: The foundation of the next level Web games

Ahead-Of-Time Compile

Page 26: asm.js x emscripten: The foundation of the next level Web games

AOT ダウンロード コンパイル 実行開始

JIT ダウンロード 実行開始 コンパイル

Native ダウンロードコンパイル 実行開始

Page 27: asm.js x emscripten: The foundation of the next level Web games

データ型Data Type

Page 28: asm.js x emscripten: The foundation of the next level Web games

asm.js

Page 29: asm.js x emscripten: The foundation of the next level Web games

asm.js : an extraordinarily optimizable, low-level subset of JavaScript

• JavaScript として評価可能

• 数値計算、関数の定義と呼び出し、ArrayBufferの操作のみ可能

• その他のことは不可能

• 型アノテーションと、フォーマルな検証プロセス

• FFIを通じたJavaScript との相互呼び出し

• ArrayBuffer の共有によるデータの受け渡し

Page 31: asm.js x emscripten: The foundation of the next level Web games

function add1(a){ return a + 1;}

Page 32: asm.js x emscripten: The foundation of the next level Web games

function Peano(stdlib, ffi, heap){"use asm";function add1(a){a = a | 0;

return (a + 1) | 0;}return { suc: add1}}

Page 33: asm.js x emscripten: The foundation of the next level Web games

const add1 = Peano(window).suc;const zero = 0;const one = add1(zero);

console.log(one); // 1

asm.js で定義したモジュールの利用

Page 34: asm.js x emscripten: The foundation of the next level Web games

function Peano(stdlib, ffi, heap){"use asm"; // 外部からインポートするシンボルの宣言

// 関数宣言

// 関数表の宣言

// モジュールのエキスポート

}

asm モジュールの構造

Page 35: asm.js x emscripten: The foundation of the next level Web games

#include <stdio.h> // 標準ライブラリのインクルード

#include "log.h"   // その他のライブラリのインクルード

extern void log(int); // 外部からインポートするシンボルの宣言

int add1(int n){ // 関数宣言

log(n); return n + 1;}

Page 36: asm.js x emscripten: The foundation of the next level Web games

function Peano(stdlib, ffi, heap){"use asm";var abs = stdlib.Math.abs; // 標準ライブラリからのインポート

var z = ffi.zero | 0; // 定数の受け渡し

var log = ffi.log; // JS関数のインポート

外部からインポートするシンボルの宣言

Page 37: asm.js x emscripten: The foundation of the next level Web games

const ffi = { zero: 0, log: text => console.log(text)};

const add1 = Peano(window, ffi).suc;

JS から asm.js へのシンボルの受け渡し

Page 38: asm.js x emscripten: The foundation of the next level Web games

function Peano(stdlib, ffi, heap){"use asm";var abs = stdlib.Math.abs; // 標準ライブラリからのインポート

var z = ffi.zero | 0; // 定数の受け渡し

var log = ffi.log; // JS関数のインポート

型アノテーション

Page 39: asm.js x emscripten: The foundation of the next level Web games

変数x のアノテーション 引数 x の型

x = x | 0; int

x = +x; double

x = f(x); float

Page 40: asm.js x emscripten: The foundation of the next level Web games

function addOne(n){// 引数の型宣言

// 変数宣言

// 関数本体の記述

}

関数宣言の構造

Page 41: asm.js x emscripten: The foundation of the next level Web games

function addOne(n){ n = n | 0; // 引数の型宣言

var one = 1; // 変数宣言

one = (one + n) | 0; // 関数本体

return one | 0;}

Page 42: asm.js x emscripten: The foundation of the next level Web games

返り値の ret アノテーション 返り値の型

return +ret; double

return ret | 0; int

return 3; double

return f(ret); float

return; void

Page 43: asm.js x emscripten: The foundation of the next level Web games

function addOne(n){ n = n | 0; // 引数の型宣言

var one = 1; // 変数宣言

one = (one + n) | 0; // 関数本体

return one | 0;}

関数の型: (引数の型) → 返り値の型

Page 44: asm.js x emscripten: The foundation of the next level Web games

function addOne(n){ n = n | 0; return (n + 1)| 0;}function addTwo(n){ n = n | 0; return (n + 2) | 0;}

int -> int の関数

Page 45: asm.js x emscripten: The foundation of the next level Web games

var addFunctions = [addOne, addTwo];

関数表宣言(関数ポインタの列)

Page 46: asm.js x emscripten: The foundation of the next level Web games

function Peano(stdlib, ffi, heap){"use asm";var abs = stdlib.Math.abs; // 標準ライブラリからのインポート

var z = ffi.zero | 0; // 定数の受け渡し

var log = ffi.log; // JS関数のインポート

標準ライブラリ、外部関数、ヒープ

Page 47: asm.js x emscripten: The foundation of the next level Web games

標準ライブラリ 型Infinity

NaNdouble

Math.acos Math.asin Math.atan Math.cos Math.sin Math.tan Math.exp

(double?) → double

Page 48: asm.js x emscripten: The foundation of the next level Web games

標準ライブラリ 型Math.ceil

Math.floor Math.sqrt

(double?) → double ∧ (float?) → float

Math.abs (signed) → signed ∧ (double?) → double ∧

(float?) → floatMath.min Math.max

(int, int…) → signed ∧ (double, double…) → double

Math.atan2 Math.pow

(double?, double?) → double

Page 49: asm.js x emscripten: The foundation of the next level Web games

標準ライブラリ 型Math.imul (int, int) → signed

Math.fround froundMath.E

Math.LN10 Math.LN2

Math.LOG2E Math.LOG10E

Math.PI Math.SQRT1_2

Math.SQRT2

double

Page 50: asm.js x emscripten: The foundation of the next level Web games

var log = ffi.log; // 外部関数

log(n | 0);     // これはリンク時にエラー

log((n | 0) >>> 0); // これはリンクできる

外部関数の呼び出しにも配慮が必要

Page 51: asm.js x emscripten: The foundation of the next level Web games

asm.js における型(矢印は継承を表す)

Page 52: asm.js x emscripten: The foundation of the next level Web games

JavaScript の環境と行き来できる型

Page 53: asm.js x emscripten: The foundation of the next level Web games

単項演算子 型

+ (signed) → double ∧(unsigned) → double ∧ (double?) → double ∧(float?) → double

- (int) → intish ∧(double?) → double ∧ (float?) → floatish

~ (intish) → signed

! (int) → int

Page 54: asm.js x emscripten: The foundation of the next level Web games

二項演算子 型

+ (double, double) → double ∧ (float?, float?) → floatish

- (double?, double?) → double ∧ (float?, float?) → floatish

* (double?, double?) → double ∧ (float?, float?) → floatish

/ (signed, signed) → intish ∧ (unsigned, unsigned) → intish ∧ (double?, double?) → double ∧ (float?, float?) → floatish

Page 55: asm.js x emscripten: The foundation of the next level Web games

二項演算子 型

% (signed, signed) → intish ∧ (unsigned, unsigned) → intish ∧ (double?, double?) → double

|, &, ^, <<, >> (intish, intish) → signed>>> (intish, intish) → unsigned

<, <=, >, >=, ==, != (signed, signed) → int ∧ (unsigned, unsigned) → int ∧ (double, double) → int ∧ (float, float) → int

Page 56: asm.js x emscripten: The foundation of the next level Web games

var memo = new stdlib.Uint32Array(heap);

if(memo[n >> 2] | 0 != 0){ return memo[n >> 2] | 0;}if(n >>> 0 > 2){ result = ((fib(n - 1 | 0) | 0) + (fib(n - 2 | 0) | 0)) | 0;}

return result | 0; heap の利用例

Page 57: asm.js x emscripten: The foundation of the next level Web games

Heap View Type 要素サイズ load type store type

Uint8Array 1 intish intish

Int8Array 1 intish intish

Uint16Array 2 intish intish

Int16Array 2 intish intish

Uint32Array 4 intish intish

Int32Array 4 intish intish

Float32Array 4 float? floatish, double?Float64Array 8 double? float?, double?

Page 58: asm.js x emscripten: The foundation of the next level Web games

var memo = new stdlib.Uint32Array(heap);

if(memo[n >> 2] | 0 != 0){ return memo[n >> 2] | 0;}if(n >>> 0 > 2){ result = ((fib(n - 1 | 0) | 0) + (fib(n - 2 | 0) | 0)) | 0;}

return result | 0;log2(要素のバイト数) ぶんだけ右にシフトしなくてはならない

Page 59: asm.js x emscripten: The foundation of the next level Web games
Page 60: asm.js x emscripten: The foundation of the next level Web games
Page 61: asm.js x emscripten: The foundation of the next level Web games

• 例外を投げることなく return まで到達すること

• 全ての属性アクセスは、データアクセスとして解決されること

• heap があるなら、それは ArrayBuffer であること • heap の大きさは [212 , 224) 、もしくは 224 の倍数であること

• stdlibから取られたシンボルは、 標準ライブラリ中のものを指すこと

リンクに成功する条件

Page 62: asm.js x emscripten: The foundation of the next level Web games
Page 63: asm.js x emscripten: The foundation of the next level Web games
Page 64: asm.js x emscripten: The foundation of the next level Web games
Page 66: asm.js x emscripten: The foundation of the next level Web games

% emcc -o hello.js hello.c% node hello.jshello world

% emcc -o hello.html hello.c% open hello.html

-o オプションで html / js へ出力

Page 67: asm.js x emscripten: The foundation of the next level Web games

Emscripten compiles C / C++ into JavaScript in asm.js format

• ファイル入出力: XHR に書き換え / ファイルを JS に結合

• JavaScript からC/C++コードの呼び出し

• cwrap / ccall を利用

• WebIDL を作成し、binding を生成

• CからJavaScriptコードの呼び出し

• EM_ASMマクロの利用したコード埋め込み

• 外部関数 (extern)として呼び出し、リンク時に解決

Page 68: asm.js x emscripten: The foundation of the next level Web games

ファイルアクセス

Page 69: asm.js x emscripten: The foundation of the next level Web games

% emcc —preload-file hello.txt -o file.html fileio.c

—preload-file オプションをつけると read を XHR に変更

Page 70: asm.js x emscripten: The foundation of the next level Web games

% emcc —preload-file hello.txt -o file.html fileio.c

% emcc --embed-file hello.txt -o hello.html file.c

—embed-file オプションで、ファイルを埋め込む

Page 71: asm.js x emscripten: The foundation of the next level Web games

ccall / cwrap

Page 72: asm.js x emscripten: The foundation of the next level Web games

extern "C" { unsigned int fib(unsigned int n){ if(n < 3){ return 1; } return fib(n - 1) + fib(n - 2); }}

C++ での記述: エキスポートする関数名のマングリングを防ぐ

Page 73: asm.js x emscripten: The foundation of the next level Web games

% emcc -o fib.html \ -s EXPORTED_FUNCTIONS="['_fib']" \ fib.cpp

不要なコードの削除を防ぐために EXPORTED_FUNCTIONS を指定

Page 74: asm.js x emscripten: The foundation of the next level Web games

var fib = Module.cwrap("fib", "number", ["number"]);console.log(fib(30));

var result = Module.ccall("fib", "number", ["number"], [30]);console.log(result);

JavaScriptからの呼び出し: 識別子、型情報の指定が必要

Page 75: asm.js x emscripten: The foundation of the next level Web games

WebIDL

Page 76: asm.js x emscripten: The foundation of the next level Web games

class Peano{public: Peano(); int current(); void suc();};

C++ でクラスを定義

Page 77: asm.js x emscripten: The foundation of the next level Web games

class Peano{public: Peano(); int current(); void suc();};

interface Peano{ void Peano(); long current(); void suc();};

インタフェースを定義するWebIDLファイルを作成

Page 78: asm.js x emscripten: The foundation of the next level Web games

% python tools/webidl_binder.py peano.webidl peano-glue

グルーコードを生成

Page 79: asm.js x emscripten: The foundation of the next level Web games

#include "peano.cpp"#include "peano-glue.cpp"

ラッパーを作成

Page 80: asm.js x emscripten: The foundation of the next level Web games

% emcc -o peano.html \ --post-js peano-glue.js \ peano.cpp \ peano-wrapper.cpp

—post-js オプションをつけてemcc コンパイル

Page 81: asm.js x emscripten: The foundation of the next level Web games

p = new Module.Peano();console.log(p.current()); // 0 を出力

p.next();console.log(p.current()); // 1 を出力

JavaScriptからはModule オブジェクトの属性として参照できる

Page 82: asm.js x emscripten: The foundation of the next level Web games

CへのJavaScriptの埋め込み

Page 83: asm.js x emscripten: The foundation of the next level Web games

#include <stdio.h>#include <emscripten.h>int main(int argc, char **argv){ EM_ASM({ alert("hello!"); });}

EM_ASM マクロを使って JavaScript コードを埋め込める

Page 84: asm.js x emscripten: The foundation of the next level Web games

x = EM_ASM_INT({ console.log("argument:"+ [$0, $1]); return Math.pow($0, $1);}, 2, 24);

printf("x = %d\n", x);

引数、返り値のあるコードの埋め込み例

Page 85: asm.js x emscripten: The foundation of the next level Web games

CからJavaScriptコードの呼び出し

Page 86: asm.js x emscripten: The foundation of the next level Web games

#include <stdio.h>

extern "C"{ extern int id(int); extern void hi();}

外部関数を宣言

Page 87: asm.js x emscripten: The foundation of the next level Web games

int main(int argc, char **argv){ int x = 10;

printf("id(%d) = %d\n", x, id(x)); hi();

return 0;}

リンクされる前提で呼び出す

Page 88: asm.js x emscripten: The foundation of the next level Web games

mergeInto(LibraryManager.library, { id: function(n){ return n; }, hi: function(){ alert("hi"); }});

library.js に関数を実装

Page 89: asm.js x emscripten: The foundation of the next level Web games

-rw-r--r-- 1 chiko staff 81B 2 17 19:25 hello.c-rw-r--r-- 1 chiko staff 100K 3 24 18:17 hello.html-rw-r--r-- 1 chiko staff 466K 3 24 18:17 hello.js

Page 90: asm.js x emscripten: The foundation of the next level Web games
Page 91: asm.js x emscripten: The foundation of the next level Web games
Page 92: asm.js x emscripten: The foundation of the next level Web games
Page 93: asm.js x emscripten: The foundation of the next level Web games
Page 94: asm.js x emscripten: The foundation of the next level Web games
Page 95: asm.js x emscripten: The foundation of the next level Web games