What a JavaScript world
カーネル/VM Advent Calendarの25日目の記事です.VMはVirtual Machineの略らしく(オ,皆カーネルサイドばかりなのでVMサイドの記事を書きます.
最近ホットなVMといえば,どんどんその勢力が拡大しているLLVMです.世界的に有名なD言語にもLLVMをバックエンドに用いたLDCと呼ばれる処理系が存在しています.このブリッジ部分を突き詰めてもいいのですが,ちょっと今回は楽をしたいので,Node.JSによってサーバサイドでも存在感を出してきたJavaScriptネタで行きます.
Emscripten
EmscriptenはCやC++で書かれたコードをLLVMを経由することで,JavaScriptコードに変換するというプロジェクトです.サイトのサンプルにもありますが,既にPythonやLuaがデモとして存在しています.
仕組み
LLVMによって生成することが出来るllファイル(これにはLLVMの中間表現が書かれている)をEmscriptenに食わせることによって,Emscriptenが自身の内部表現に変換し最適化を施した後JavaScriptを出力します(これらメインとなるコードはJavaScriptで書かれていて,src以下にあります).
各プロセスでどういうコードになるのかはサイトにサンプルがあります.
処理系のインストール on Mac
homebrewにはllvmもV8もSpidermonkeyもあるのでbrew installすれば必要なのは全部入ります.
% brew install llvm v8 spidermonkey
Emscriptenを使う
Kernel VM Advent CalenderはBrainf*ckネタが多いので,今回もこれで(実装はここから拾いました).Emscriptenはllファイルを必要とするので,llvmを使って生成します.
% clang -emit-llvm -c bfi.c % llvm-dis -show-annotations bfi.o
これでbfi.o.llが生成されるのでこれを使います.
問題
で,これで後は
% ./emscripten.py bf.o.ll /usr/local/bin/v8 > bfi.js
とかすれば「JavaScript実装の出来上がり!」と思ったらなんかV8にreadline関数がなくてcompiler.jsで落ち,/usr/local/bin/jsを使ったらbfi.jsの変換までは行くものの,Brainf*ckのコードを食わせても何もせずに終わってしまうという状況.MacでEmscriptenの開発している人達はどうやってるのか気になる所(V8のソース読む限りはreadline周りがあるので,なんか俺がミスってそう…).
まとめ
Emscriptenで生成したBrainf*ck実装を使ったデモページを公開したかったんですが,デバッグ間に合いませんでした!
Emscriptenは現状全てのCやC++のコードを移植できるわけではないようですが,Pythonなどの例を見ても分かるように結構動くようです.「Webブラウザで動けばそれなりにクロスプラットフォームだよね」という昨今,どうしても速度が必要じゃない場面以外では結構使い道があるんじゃないかなと.
また,他のLLVM使っている言語からのJavaScript変換も考えているようなので,LLVM使っていればJavaScriptに変換してWebブラウザで実行可能!とか出来るようになるかもしれません :)
その他
似たようなプロジェクトにllvm-js-backendというのがあるようですが,こちらは詳しくはしりません(あまり話に上がらないので).また,最適化があるとはいえ自動生成でチューニングなどされているコードではないので,Google NaClのような仕組みには速度ではほぼ勝てないとは思います.
そういえば,V8とSpidermonkeyとで生成されるコードに微妙に違いがある気がするので,この辺は今後の課題になりそう.