(本記事は カーネル/VM Advent Calendar 2011 に参加している記事です.この記事は 5 日目の記事で,前日は @naota344 でした.)
カーネル/VM 探検隊には参加したことがない sora_h です.こんにちは!
さて,カーネル/VM advent calendar はテーマなんでもいいということですが,やはり前日を見るとカーネル関連じゃないと行けない気がしなくも無いですね……………!!!!
カーネルとVMといえばまあRuby の Kernel
とRubyVM
が思い浮かぶわけです.
ネタがないのでこの二つを解説しましょう.ごめんなさい!!!!
Kernel
Kernel
とはすべてのクラスから参照できるメソッドが定義されているモジュールであり,
Object
はこいつを include している.
有名な例では puts
とかopen()
とかそういうのが Kernel
にあります.
しかしこれを解説するのはあまり面白みが無いので RubyVM を解説しようと思います.
RubyVM
今回はそれのサブクラスである RubyVM::InstructionSequence
を取り上げます.
これは Ruby 1.9 系列から搭載された VM, YARV (Yet Another Ruby Vm) の insq (instruction sequence, バイトコード(?)) に Ruby レベルからコンパイルしたりなどができるようになって います.
RubyVM::InstructionSequence.compile("puts 'a'")
等することでコンパイルする事が可能です.
コンパイルの結果は,それでかえってきた InstructionSequence
のオブジェクトに対して
disasm
したものを puts
などすると良いのではないでしょうか.
require 'pp'
puts RubyVM::InstructionSequence.compile("puts 'a'").disasm
またこの結果は ruby --dump=insns -e 'script'
とか ruby --dump=insns foo.rb
とかでも
確認することができます.
そして
RubyVM::InstructionSequence.compile("puts 'a'").eval
で実行することも出来ます.
で,これで生成されるバイトコードを見たからなんだ,という話なんですが, たとえば命令をいじってみたりとかして遊ぶことができますね.
YARV の命令群の実態は insns.def
ファイルにあって,コンパイル時にそれを一つの C ファイルに変換しています.
なので,insns.def
ファイルを編集してビルドすることで命令の動作が変わったりします.楽しいですね.
YARV の instructions を調べたりするには yhara さんが作った YARV Instructions, また YARV 自体の解説にはまだ執筆途中で中途半端なものの開発者である ささださん が書いている YARV Maniacs を読むと良いかもしれません.
参考資料
まとめ
ちゃんとネタは作っておこう