ruby 1.9.0がリリースされたのでVMまわりをいじってみる
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/44387
どうなることかと思ったら日付が変わったころにアナウンスがあって一安心(?)。お疲れさまでした。
1.9といえばVM化でしょう、ということでVMまわりをいじってみた。
まず、http://jp.rubyist.net/magazine/?0015-YarvManiacsのあたりを見ながら(YARVCoreをVMに読みかえて)文字列から命令列へのcompileができることを確認。命令列オブジェクトはdisassembleしたり、evalしたりできる。なかなか楽しい。
よしよし、次は自前でVM命令列を生成して実行だ、と思って、手始めにto_aで読み書きできる配列にシリアライズして、それをloadして実行しちゃろうと思ったらなんとloadがなくなってる。ソース(iseq.c)を見るとloadの実体はあるのにクラスメソッド定義がコメントアウトされてたので、コメントをはずしてmake。
よしこれで、と思ったらloadでタイプエラーがでる。どうやら今のソースだとto_aでシリアライズされる形式とloadが期待している形式が微妙に違うらしい。微妙にというか、出力される配列のサイズと期待している配列のサイズがあからさまにひとつ違う。iseq.c中のiseq_loadの中でタイプエラーを起こしてる箇所(lineを読みとっている行)をコメントアウトして一個ずらしたら、超簡単な命令列は読みこめた。実行もできた。ふー。簡単じゃない命令列がこれで大丈夫かどうかは知らない。
こんなソースが実行できた。
require 'pp' iseq = VM::InstructionSequence.compile("1+2") ar = iseq.to_a pp ar iseq2 = VM::InstructionSequence.load(ar) p iseq2.eval
結果はこんなん。
["YARVInstructionSequence/SimpleDataFormat", 1, 1, 1, {:arg_size=>0, :local_size=>1, :stack_max=>2}, "<compiled>", "<compiled>", :top, [], 0, [], [1, [:putobject, 1], [:putobject, 2], [:opt_plus], [:leave]]] 3
しかしどうにも無理矢理くさい。他に命令列を加工(シリアライズしてload)するやり方で推奨されてる方法とかあんのかな。The RHG Strikes Back(http://qwik.jp/rhg-strikes-back/)みたいなことをやろうとすると、このへんのツールはあったほうが絶対やりやすいと思うんだけど。んー。disassembleして読めりゃそれでいいかな。