mruby Advent Calendar 2013はqiitaで書くとよさそうなので、テストを兼ねて投稿します。
mruby Advent Calendar 2013はJITの話をする予定ですが、その時使うmruby-meta-circular の話を書きます。mruby-meta-circularはmrubyからRite VMの各種情報を得たり、書き換えたりするといった、ありがちな操作を行うためのmrubyのgemです。
簡単に使い方を見てみましょう
Irep::get_irep(オブジェクト、 メソッド名)
でそのオブジェクトのメソッドのIrepをオブジェクト化したもの(Irepオブジェクト)を取り出すことができます。とりだした結果は、pool, syms, iseqといったメソッドで同名のIrep構造体のメンバーを取り出すことができます。
a = Irep::get_irep([], :each)
これで、Array#[]メソッドのIrepオブジェクトがaに入ります。
p a
→ #<Irep:0x20013d48>
p a.pool
→ [] # [1]とあったけど、これはmrubyのJITのメソッドインラインキャッシュがあったため。今はないので[]が返る
p a.syms
→ [:length, :-, :[], :+, :==, :>=, :call, :<, :<=]
a.iseq.each do |n|
p Irep::OPTABLE[n & 0x7f]
end
→
"ENTER"
"LOADI"
"LOADSELF"
"SEND"
"NOP"
"SUBI"
"NOP"
"MOVE"
"MOVE"
"JMP"
"LOADSELF"
"MOVE"
"ADDI"
"NOP"
"MOVE"
"SEND"
"NOP"
"MOVE"
"MOVE"
"JMPNOT"
"JMP"
"MOVE"
"LOADNIL"
"EQ"
"NOP"
"JMPNOT"
"MOVE"
"LOADSELF"
"SEND"
"NOP"
"GE"
"NOP"
"JMPNOT"
"JMP"
"MOVE"
"MOVE"
"SEND"
"NOP"
"MOVE"
"MOVE"
"LT"
"NOP"
"JMPNOT"
"MOVE"
"LOADSELF"
省略
なお、Irep::OPTABLE
は命令コード(整数)をインデックスにアクセスすると命令の名前のシンボルが返ってくる配列です。Irep::OPTABLE_CODE
はシンボルからコードに変換することができます。これで、アセンブラ・逆アセンブラがmrubyで実装できますね。なお、mruby-meta-circularにはまだ、アセンブラ・逆アセンブラはないです。まあ、それだけ面倒な作業になりそうということです。
これで、Irepを得るところまで説明しました。実は、Irepを新しく作ることもできるのですが13日までに仕事が入ってこなければその辺も書きたいと思います。