LoginSignup
2
2

More than 3 years have passed since last update.

【Ruby】コードを少し変えてYARV命令の違いを確認する

Posted at

はじめに

自分が書いたRubyのコードがどのような道のりを辿って実行されるのか興味を持ったことはあるでしょうか。

RubyのしくみによるとRubyコードは以下の流れでYARV命令へと変換されます。

Rubyコード
↓
字句解析
↓ 
構文解析
↓ 
コンパイル
↓
YARV命令

この記事では、YARV命令の部分をピックアップし、YARV命令がコードによってどう変わるのか簡単に見ていきます。

なお、今回利用したRuby処理系、Rubyバージョンは以下の通りです。

Ruby処理系 Rubyバージョン
MRI 2.6.1

YARV命令表示

まず、YARV命令を表示してみます。

簡単なRubyのコード 4 + 3 のYARV命令をみてみましょう。YARV命令は RubyVM::InstructionSequence を使うことで見ることができます。

irb(main):001:0> puts RubyVM::InstructionSequence.compile('4+3').disasm
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,3)> (catch: FALSE)
0000 putobject                    4                                   (   1)[Li]
0002 putobject                    3
0004 opt_plus                     <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <callcache>
0007 leave
=> nil

putobjectでスタックに値をプッシュし、opt_plusで加算を実行するのが確認できます。

すなわち、以下の流れでコードが実行されます。

  1. 4をスタックにプッシュ
  2. 3をスタックにプッシュ
  3. 加算(4 + 3

4 + 3 * 2 vs (4 + 3) * 2

続いて、4 + 3 * 2(4 + 3) * 2のYARV命令を表示して結果を比べてみます。

irb(main):001:0> puts RubyVM::InstructionSequence.compile('4+3*2').disasm
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,5)> (catch: FALSE)
0000 putobject                    4                                   (   1)[Li]
0002 putobject                    3
0004 putobject                    2
0006 opt_mult                     <callinfo!mid:*, argc:1, ARGS_SIMPLE>, <callcache>
0009 opt_plus                     <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <callcache>
0012 leave
=> nil
irb(main):001:0> puts RubyVM::InstructionSequence.compile('(4+3)*2').disasm
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,7)> (catch: FALSE)
0000 putobject                    4                                   (   1)[Li]
0002 putobject                    3
0004 opt_plus                     <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <callcache>
0007 putobject                    2
0009 opt_mult                     <callinfo!mid:*, argc:1, ARGS_SIMPLE>, <callcache>
0012 leave
=> nil

上記2つを比べるとopt_plusの位置が変わっていることに気がつきます。

それぞれ以下の流れでコードが実行されます。

・ 4 + 3 * 2

  1. 4をスタックにプッシュ
  2. 3をスタックにプッシュ
  3. 2をスタックにプッシュ
  4. 乗算(3 * 2
  5. 加算(4 + 6

(4 + 3) * 2

  1. 4をスタックにプッシュ
  2. 3をスタックにプッシュ
  3. 加算(4 + 3
  4. 2をスタックにプッシュ
  5. 乗算(7 * 2

命令の順番によって、計算結果が変わることが確認できます。

まとめ

コードを少し変えることでYARV命令がどう変わるのかみてきました。
普段YARVの内部スタックの状態を意識することはなかったですが、より深いところまで理解できるよう知識を深めていきたいものです。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2