generated at
asm.js
概要
2013年ごろ
ブラウザ上でのプログラムの高速実行を目指して設計されたJavaScriptのサブセット
JSの文法に対する後方互換性がある
Emscriptenを用いるとC, C++から、LLVM IRを通して(?)、asm.jsにコンパイル可能
ちょっと頑張ればasm.jsを直接手書きすることもできる
JS実行環境ではAOT compileして実行の直前にネイティブコードにコンパイル
これが高速さの理由
高速実行を目指して設計


JIT Compilerの恩恵を受けられる ← これほんま #?? どこに書いてる?
型の恩恵もある
Firefox 22 (2013/6/25公開)からサポート
ArrayBufferをヒープとして利用する
JavaScriptの関数を呼ぶこともできるし、JavaScript側からasm.jsのmoduleを呼ぶこともできる


Links
更新が止まっている

特徴 ref
変数、式、関数の型が静的解析可能
数値計算に特化
オブジェクトに関する操作ができない
メソッド呼び出しなど
利用できるコレクション型は Typed Array のみ

速い
GCしない
>ガベージコレクタは不要となる。メモリは大きな型つき配列ヒープの中で、mallocとfreeのような機能によってマニュアルで管理されるようになるからだ。 ref
DOM操作は速くならない
計算処理的な部分が速くなる

OdionMonkey
Mozillaasm.jsとほぼ同時期に開発していたJSエンジン
SpiderMonekyのasm.js実装
asm..jsとの組み合わせでこのベンチマーク
ネイティブの2倍程度の実行時間

対応 いつの?
firefox
chrome
edge
Node.js

普通のJSコードの話 ref
インタプリタ的に動作する
SpiderMonkey, Chakra, V8, Node.jsなどはJSのインタプリタ
構文解析してASTを作って、VM用のバイトコードに変換する
バイトコードはスタックマシンを操作するコードの様なもの
(a,b,c)=>a+b*c というコードをSpiderMonkeyプロセスVM用に変換したバイトコード
vm
getarg 0 getarg 1 getarg 2 mul add return retrval
バイトコードをひとつずつ取ってきて、switch文を通して各命令を実行する関数が呼ばれる
型がわからないとネイティブコードは冗長になる
たとえば、IntelのPCUは20種類以上の加算の命令がある
データ型とデータの保存場所によって使用する命令が異なるから
型が決まっていると、命令は一つで済む
決まっていない場合、ひとつずつチェックしないといけない
実行時間が遅くなる
SpiderMonkeyなどJIT compileを使って速度向上を目指す処理系もある

コンパイルまでの過程
AST作って、意味解析して、ネイティブコードへコンパイル
ネイティブコードはメモリ上へ展開される
これとは別にあるJSの関数やasm.jsの標準ライブラリとのリンクが行われる
失敗するパターン
意味解析で失敗
型エラーが起こった時
リンクで失敗
メソッドの呼び出し、JSにExportできない種類のデータを引数に指定した関数呼び出しを行った場合
モジュール単位でコンパイル
JSエンジンがAOT compileを試みる
js
// ↓これが一つのmoduleになる function AddFunctions(){ "use asm"; // 関数を宣言 function add1(value){ value = value | 0; // 変数の宣言. int型 var result = 0; result = (value + 1) | 0; // 加算の結果はintishになるので、intにキャスト return result; } // 関数表の宣言 return { add1: add1 } }

ヒープを利用する
asm.jsで定義できる関数は数値演算しか出来ない
文字列やオブジェクトを用いたコードは使えない
ヒープを使う
Cが文字列を数値の配列として扱っているアイディアを使う
HEAP というArrayBufferに格納する
コード例
部分的にだけどこんなの
js
for(;(HEAP[i << 0 >> 0] | 0) != 0; i = i + 1 | 0){ buffer[i << 0 >> 0] = ((buffer[i << 0 >> 0] | 0) + key) | 0; }

型がある ref
あくまでもJSの記法で型アノテーションをする
同値として解釈できるような冗長なJSを書いている感じ
asm.js処理系には型だとわかるが、それ以外の処理系にはちょっと冗長なJSコードに見える
+hoge はdouble
hoge | 0 はint
f(hoge) はfloat
型を付けられるもの
変数
関数の引数
int double
関数の戻り値
double , signed , float , void
型の継承関係

ゲームエンジンによるサポート
UE, Unity

asm.jsの課題
ファイルサイズ増大による
通信量の増加
構文解析時間の増加
asm.jsを拡張するためには、まずJSを拡張しないといけない #??


関連
並列化
データを纏めて処理




参考
Mozilla@chikoskiさんの連載
Alon Zakai氏のスライド
当時の時代背景や、GoogleMozillaのノリや思想に触れていてとても良い