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

LearnByteCode, Techc, Japanese, mruby, mruby/c

OP_LOADI

Arguments

  • A:レジスタ番号
  • sBx:整数

How it works?

R(A) := sBx

レジスタ[A]にFixnumとしてsBxの値を代入する。
sBxは16bitの符号付き整数である。

When used?

値の小さな整数値の定数値をレジスタ上に読み出すときに用いる。
定数や、文字列を利用するときに用いる。

例えば下記のようなコードは、

a = 1 

次のようなバイトコードに変換され、LOADLは使用されない。

    3 000 OP_LOADI      R2      1
    3 001 OP_MOVE       R1      R2              ; R1:a
    3 002 OP_STOP

このようにすることで、pools[]の容量を節約しつつ、処理も簡略化できる。

Note

ここで、sBxに指定できる値の範囲は、バイトコードの命令フォーマットに依存している。
sBxは16bitなので、-32768~32767が指定できる。

それを踏まえて、下記のコードをバイトコンパイルすると…

a = 32767 
    1 000 OP_LOADL      R2      L(0)    ; 32767
    1 001 OP_MOVE       R1      R2              ; R1:a
    1 002 OP_STOP

LOADIが使われると想定されたが、なぜか、LOADLが使用されている。

1引いて32766を試してみると…

a = 32766 
    1 000 OP_LOADI      R2      32766
    1 001 OP_MOVE       R1      R2              ; R1:a
    1 002 OP_STOP

これはLOADIが使用された。

codegen.cの実装を探してみると、

        if (i < MAXARG_sBx && i > -MAXARG_sBx) {
          co = MKOP_AsBx(OP_LOADI, cursp(), i);
        }
        else {
          int off = new_lit(s, mrb_fixnum_value(i));
          co = MKOP_ABx(OP_LOADL, cursp(), off);
        }

おそらくLOADIかLOADLを使い分ける判定の”i < MAXARG_sBx”の比較が”<=”でないためと思われる。
これに何らかの意図があるのかどうかは、わからなかった。

Reference

https://github.com/mrubyhw/mrubyhw/wiki/%E3%83%90%E3%82%A4%E3%83%88%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

mrubyのバイトコードフォーマット解説


https://qiita.com/miura1729/items/256d205bc2a464bfb3c6