なにこれ
名前そのままブラウザからアセンブリを実行できるようにする技術であり、高速化手段、あるいはJavaScriptの処理系にできないことをするといった目的で提案された。
現在多くのブラウザでサポートされているasm.jsとの違いは、JavaScriptのサブセットであるためにロードタイムに課題があったasm.jsに対し、WebAssemblyでは直接バイナリを読み込むことでこの問題を解決している。
現在、Chrome(Canary)に実装され、簡単に試すことができるようになった。
試したよ
参考にした記事
つかうもの
- Google Chrome Canary
- llvm
- clang
- binaryen
- sexpr-wasm-prototype
Google Chrome Canary
WebAssemblyを使うには chrome://flags/#enable-webassembly
にチェックをつけて有効化する。
llvm
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly
を付けてcmake
する。
brew経由でインストールする場合にはbrew edit llvm
で追加。
clang
Macに標準で入ってるclangではうまくいかなかったのでclang-3.8
を使った。おそらくbrew install llvm38 --with-clang
のものだと思う。
binaryen
https://github.com/WebAssembly/binaryen
クローンしてきてビルド&インストール
sexpr-wasm-prototype
https://github.com/WebAssembly/sexpr-wasm-prototype
クローンしてきてビルド&インストール
(クローンしたあとgit submodule update --init
忘れずに)
変換してみる
変換はこんな感じの流れ
C/C++ -> LLVM bitecode -> Assembly -> S-expression -> binary
今回はC++のコードを変換する。
extern "C" {
int fib(int n) {
int i, t, a = 0, b = 1;
for (i = 0; i < n; i++) {
t = a + b; a = b; b = t;
}
return b;
}
}
C++の場合、関数名がmanglingされてしまうので、回避するためにextern "C" {}
をしてる。
#####1. まずC++からLLVMバイトコードに変換
clang++-3.8 sample.cpp -emit-llvm --target=wasm32 -Oz -c -o sample.bc
#####2. LLVMバイトコードからアセンブリに変換
llc sample.bc -march=wasm32 -filetype=asm -o sample.s
#####3. アセンブリからS式に変換
s2wasm sample.s > sample.wast
#####4. S式からWebAssemblyバイナリに変換
sexpr-wasm sample.wast -o sample.wasm
これで読み込むための.wasm
ができあがる。
前述の参考にした記事ではLLVM IR形式(.ll
)に変換してからアセンブリに変換していた。この方法でも同様の結果が得られる。
実行してみる
jsはこんな感じ
var xhr = new XMLHttpRequest();
xhr.open('GET', 'sample.wasm', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function() {
var binary = xhr.response;
var binarray = new Uint8Array(binary);
var module = Wasm.instantiateModule(binarray);
console.log(module.exports);
var fib = module.exports.fib;
var arr = [];
for (var i = 0; i < 20; i++) {
arr.push(fib(i));
}
console.log(arr);
};
xhr.send(null);
出来上がったバイナリをXHRで取ってきてUint8Array
に変換してWasm.instantiateModule
に投げると、オブジェクトが返ってくる。
返ってきたオブジェクトのexports
の中にC++で定義した関数が入っているのでそのまま引数を渡してアクセスできる。
今回は20個のフィボナッチ数列を表示するだけ。
で
原因がわからないのだが、clangでのビルドで最適化を切るとWebAssemblyのバイナリはできるが、実行するとエラーが出てしまった。いつか解決したい。
WebのフロントエンドにC/C++のコードが介入してくると考えるとフレームワークやライブラリのパラダイムも変わってくるのかもしれない。
いま熱くなってきているWebAssemblyだが、まだ情報は少ないため、再び試す機会があればやってみようと思う。
今回のコードはgithubにポイしておいた。