独習mrubyバイトコード[OP_LOADI]
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”の比較が”<=”でないためと思われる。
これに何らかの意図があるのかどうかは、わからなかった。
Recent Comments