mrubyのJIT2 (仮称)


mrubyのJIT2(仮称)なるものを作ろうとしているのだが、考えがまとまらないので取りとめもなく書く。真に受けて何か損害をこうむっても知らん、その代わり何かいいことがあっても私は何も貰えない。

mrubyのJIT2(仮称)はLLVMベースを考えています。これまでLLVMのトラウマがあったわけですが、LLVMもいろいろ変わっていて(変わり過ぎですけど)、ちょっと試してみたい気もあるってのもあるしラズベリーパイも買ったのでこれでも動かしたいってのもある。
今考えている構造はこんな感じ

  • mrubyのバイトコードからさらにSSAベースの中間コード(IR)にする
  • IRを生成する際にある程度の型推論を行いその型情報はIRに入れられるようにする(LuaJITのパクリじゃなくてLuaJITにインスパイアされたって奴ですね)
  • 前作と違い、Tracingではなくmethod JITにする(LLVMでTracing JITは困難そう)
  • 今回は出来る限りmrubyで書く。 前回もmrubyそのもので書きたかったのだが、言語の完成度がそれを許さなかった。今はそれが可能であると思う。こうすることでコンパイラ自身をJITコンパイルしたりコンパイラ機能のカスタマイズをmrubyで行うとか夢が広がる
  • LLVMで使いたい機能ってのはコードにバイナリパッチが当てられるというもので、これを使って現状と同じレベルのmrubyとの互換性を狙いたい

IRについて

IRの生成は、mruby-meta-circrier mrbgemを使って行う。
レジスタについて単一代入になるようにリネームをおこなうのだが、メソッド呼び出しのパラメータになるレジスタについてはスタックと言う形にした方がいいのか悩む。つまり、ローカル変数のレジスタとパラメータのレジスタは区別すべきではないかと思う
LuaJITはIRに64bit整数を割り当てているが、mrubyではこんなんでは足りなさそう。オブジェクトにした方がいいのか悩む。複雑な型がつく場合何か特にね
IRは分岐の無いBasic Blockのグラフとして表現する。

LLVMについて

LLVMでパッチを当てて要らなくなった領域を解放することって出来るのかしらん。カスタムアロケータをしてい出来ればいいのだけど、C++レベルでnewをオーバーライドするとかできるのかしらん
GCのライトバリアをLLVMのGCサポート機能を使って高速化出来ればいいのだけど出来るのかしらん
そもそもmrubyにLLVMのバインディングが無いっぽい。ありそうな気がしたんだけどなー。