独習mrubyバイトコード[OP_LOADNIL]

LearnByteCode, Techc, Japanese, mruby

OP_LOADNIL

Arguments

  • A:レジスタ番号

How it works?

R(A) := nil

レジスタ[A]にnilオブジェクトを代入する

When used?

nilをレジスタ引数にとる命令に使われたりしている。

class TestClass
end

t = TestClass.new

出力されるバイトコードは、こんな感じ。

00001 NODE_SCOPE:
00004   local variables:
00004     t
00001   NODE_BEGIN:
00001     NODE_CLASS:
00002       :TestClass
00002       body:
00001         NODE_BEGIN:
00004     NODE_ASGN:
00004       lhs:
00004         NODE_LVAR t
00004       rhs:
00004         NODE_CALL(.):
00004           NODE_CONST TestClass
00004           method='new' (15)
irep 0x60001a810 nregs=4 nlocals=2 pools=0 syms=2 reps=1
file: a.rb
    1 000 OP_LOADNIL    R2
    1 001 OP_LOADNIL    R3
    1 002 OP_CLASS      R2      :TestClass
    1 003 OP_EXEC       R2      I(+1)
    4 004 OP_GETCONST   R2      :TestClass
    4 005 OP_SEND       R2      :new    0
    4 006 OP_MOVE       R1      R2              ; R1:t
    4 007 OP_STOP

irep 0x600087580 nregs=2 nlocals=1 pools=0 syms=0 reps=0
file: a.rb
    1 000 OP_LOADNIL    R1
    1 001 OP_RETURN     R0      normal

OP_CLASSの引数のAがR2、R3には、Super Classが入る。ここでは継承ないので、nilが入っている。
R2には、定義したクラスが入ることになる。どうせ上書きされるのなら、R2のLOADNILは不要?処理が失敗したときのためにnilにしている?

Note

nilとは

nullではなく、nilである由来は、Smalltalk、Lispらしい。1
いろいろな言語の影響を受けてRubyは作られている。2

mruby/cの場合

オブジェクトの種別に”MRB_TT_NIL”を設定している。

  int ra = GETARG_A(code);

  mrbc_release(®s[ra]);
  regs[ra].tt = MRB_TT_NIL;

mrubyの場合

      /* A     R(A) := nil */
      int a = GETARG_A(i);

      SET_NIL_VALUE(regs[a]);

SET_***_VALUEは、NaN boxingを適用するか否かで参照するヘッダファイルが異なる。適用しない場合は、

#define BOXNIX_SET_VALUE(o, ttt, attr, v) do {\
  (o).tt = ttt;\
  (o).attr = v;\
} while (0)

#define SET_NIL_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_FALSE, value.i, 0)
#define SET_FALSE_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_FALSE, value.i, 1)

ttがオブジェクトの種別だけど、MRB_TT_NILではなくて、MRB_TT_FALSEとして扱われている。MRB_TT_FALSEとの違いを見ると、value.iの値が1か0かで区別して、種別の数が増えないように節約しているように見える。
詳しくは、Nilを扱っているコードも読んでみないといけない。

Reference

“Why does Ruby use nil to name the null object?” https://stackoverflow.com/questions/22108397/why-does-ruby-use-nil-to-name-the-null-object

松江Ruby会議09の松本さんの講演