ruby-jp slackで教えてもらいました。 Syntax Tree - RubyKaigi 2022 を発表したケビン・ニュートンさんが25日間でRubyVMについて解説してくれるようです。 プロローグの本記事によるとRubyVMのインストラクションを表示する方法が挙げられています。
例えば、2 +3の命令をダンプするには、ruby --dump=insns -e '2 + 3' と実行すればよいでしょう。
ledsun@MSI:~►ruby --dump=insns -e '2+3' 12:14 == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,3)> (catch: false) 0000 putobject 2 ( 1)[Li] 0002 putobject 3 0004 opt_plus <calldata!mid:+, argc:1, ARGS_SIMPLE>[CcCr] 0006 leave
第二の方法は、RubyVM::InstructionSequenceクラスを用いて、ソースから YARV バイトコードをコンパイルする方法である。
irb(main):005:0> puts RubyVM::InstructionSequence.compile('2+3').disasm == disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,3)> (catch: false) 0000 putobject 2 ( 1)[Li] 0002 putobject 3 0004 opt_plus <calldata!mid:+, argc:1, ARGS_SIMPLE>[CcCr] 0006 leave => nil
irb(main):007:0> pp RubyVM::InstructionSequence.compile('2+3').to_a ["YARVInstructionSequence/SimpleDataFormat", 3, 2, 1, {:arg_size=>0, :local_size=>0, :stack_max=>2, :node_id=>4, :code_location=>[1, 0, 1, 3], :node_ids=>[0, 1, 3, -1]}, "<compiled>", "<compiled>", "<compiled>", 1, :top, [], {}, [], [1, :RUBY_EVENT_LINE, [:putobject, 2], [:putobject, 3], [:opt_plus, {:mid=>:+, :flag=>16, :orig_argc=>1}], [:leave]]]
この配列の各要素が何を意味するかは、シリーズで解説していきます。
RubyKaigiの発表では当たり前のように「インストラクション」という言葉が出てきていました。 例えば Stories from developing YJIT - RubyKaigi 2022 では、「初期のYJITではインストラクションを1対1で機械語に翻訳した」という話がでてきました。 このシリーズを読むとRubyKaigiの発表がよりスムーズに理解できるようになりそうです。 楽しみです。
ふと「20年前に、こういうインストラクションを実行するバーチャルマシンを作るとRubyが動くって考えて実装した、笹田さんの脳みその中身どうなっているんだろう?」と不思議になりました。