@ledsun blog

無味の味は佳境に入らざればすなわち知れず

25日間で理解するRubyVMインストラクション

kddnewton.com

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が動くって考えて実装した、笹田さんの脳みその中身どうなっているんだろう?」と不思議になりました。