mruby命令セット
OP_NOP (0x00)
OP_NOP --> No operation
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
| | | | | | | | | | | | | | | | | | | | | | | | | 0000000 |
何もしない。
OP_MOVE (0x01)
OP_MOVE A, B --> R(A) := R(B)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | | | | | | | | 0000001 |
R(B)をR(A)にコピーする。コピー後のR(B)も残ったまま。
OP_LOADL (0x02)
OP_LOADL A, Bx --> R(A) := Lit(Bx)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0000010 |
Poolにあるリテラル値[Bx]をR(A)に代入する。
OP_LOADI (0x03)
OP_LOADI A, sBx --> R(A) := sBx
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | sBx(+32767オフセットされた整数値) | 0000011 |
R(A)に整数値(-32767~+32768)を代入する。
OP_LOADSYM (0x04)
OP_LOADSYM A, Bx --> R(A) := Sym(Bx)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0000100 |
R(A)にシンボルSym(Bx)を代入する。
OP_LOADNIL (0x05)
OP_LOADNIL A --> R(A) := nil
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | | | | | | | | | | | | | | | | | 0000101 |
R(A)にnilを代入する。
OP_LOADSELF (0x06)
OP_LOADSELF A --> R(A) := self
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | | | | | | | | | | | | | | | | | 0000110 |
R(A)にselfを代入する。selfはR(0)なので、OP_MOVE A,0と等価。
OP_LOADT (0x07)
OP_LOADT A --> R(A) := true
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | | | | | | | | | | | | | | | | | 0000111 |
R(A)にtrueを代入する。
OP_LOADF (0x08)
OP_LOADF A --> R(A) := false
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | | | | | | | | | | | | | | | | | 0001000 |
R(A)にfalseを代入する。
OP_GETGLOBAL (0x09)
OP_GETGLOBAL A, Bx --> R(A) := getglobal(Sym(Bx))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0001001 |
グローバル変数Sym(Bx)を取得し、R(A)に代入する。存在しない場合はnilを代入する。
OP_SETGLOBAL (0x0a)
OP_SETGLOBAL A, Bx --> setglobal(Sym(Bx), R(A))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0001010 |
グローバル変数Sym(Bx)にR(A)を代入する。(既にあれば上書き、なければ新規作成される)
OP_GETSPECIAL (0x0b)
OP_GETSPECIAL A, Bx --> R(A) := Special[Bx]
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0001011 |
現時点ではFixnumの0がR(A)に代入される。Bxは無視。
OP_SETSPECIAL (0x0c)
OP_SETSPECIAL A, Bx --> Special[Bx] := R(A)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0001100 |
現時点では何もしない。
OP_GETIV (0x0d)
OP_GETIV A, Bx --> R(A) := ivget(Sym(Bx))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0001101 |
R(0)つまりselfのインスタンス変数リストから、シンボルSym(Bx)に対応する値を取得してR(A)に代入する。selfがオブジェクトでない場合or見つからない場合はnilを代入する。
OP_SETIV (0x0e)
OP_SETIV A, Bx --> ivset(Sym(Bx), R(A))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0001110 |
R(0)つまりselfのインスタンス変数リストのシンボルSym(Bx)にR(A)を保存する。リストやシンボルが未生成の場合は作成する。
なお、selfがオブジェクトでは無い場合、ARGUMENT_ERRORでraiseする。
OP_GETCV (0x0f)
OP_GETCV A, Bx --> R(A) := cvget(Sym(Bx))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0001111 |
クラス変数Sym(Bx)を取得し、R(A)に代入する。変数が存在しない場合はNameError例外(uninitialized class variable)を発生する。
検索対象のクラスcはci→proc→target_class(NULLならばci→target_class)である。c→iv_tblから検索し、見つからなければ
上位(c→super)へと遡って検索する。
OP_SETCV (0x10)
OP_SETCV A, Bx --> cvset(Sym(Bx), R(A))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0010000 |
OP_GETCVと同じルールでクラスを遡り、クラス変数Sym(Bx)が存在すれば、その内容をR(A)で上書きする。なお、見つからなかった場合は、ci→target_class→iv_tblに新規登録する。
OP_GETCONST (0x11)
OP_GETCONST A, Bx --> R(A) := constget(Sym(Bx))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0010001 |
定数Sym(Bx)を取得し、R(A)に代入する。以下の順序で検索し、最初に見つかった値が利用される。
c=ci→proc→target_classが非NULLならば、ci→proc→target_class→iv
c=ci→target_classが非NULLならば、ci→target_class→iv
cのouterモジュール(内側から外側に向かって遡る)
cと、そのsuperクラス(サブクラスからスーパークラスに向かって遡る)
(cがMODULEの場合のみ) Objectクラスのiv (Objectおよびそのsuperへ遡る)
見つからなかった場合、cからsuperに向かって遡りながら、const_missingというメソッドを検索する。メソッドが見つかった場合はそれを実行する。
メソッドが見つからなかった場合はNameError例外(uninitialized constant)を発生させる。
OP_SETCONST (0x12)
OP_SETCONST A, Bx --> constset(Sym(Bx), R(A))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0010010 |
定数Sym(Bx)を定義する。ci→proc→target_classまたはci→target_classのivにSym(Bx)の名前でR(A)の内容を登録する。 二重登録時の警告は?
OP_GETMCNST (0x13)
OP_GETMCNST A, Bx --> R(A) := R(A)::Sym(Bx)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0010011 |
R(A)が指すクラス(またはモジュール)レベルの定数Sym(Bx)を取得し、R(A)に代入する。なお、命令実行前のR(A)がクラス/モジュールでは無い1)場合、TypeError例外(constant look-up for non class/module)を発生させる。定数検索のルールは、OP_GETCONSTの4,5と同じ。
OP_SETMCNST (0x14)
OP_SETMCNST A, Bx --> R(A+1)::Sym(Bx) := R(A)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0010100 |
R(A+1)の指すクラス/モジュールに属する定数Sym(Bx)を定義する。OP_GETMCNSTと同じ方法でR(A+1)がクラス/モジュールであることを確認し、インスタンス変数としてSym(Bx)=R(A)を登録する。
R(A+1)がクラス/モジュールでない場合は、OP_GETMCNSTと同じく例外を発生させる。
OP_GETUPVAR (0x15)
OP_GETUPVAR A, B, C --> R(A) := uvget(B, C)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | C | 0010101 |
C段分上位のメソッド/ブロックの変数R(B)を取得し、現在のブロックのR(A)に代入する。
なお、C=0はci→proc→env、C=1はci→proc→env→c、C=2は( (REnv*)Ci→proc→env→c)→c、以下同様。対応するenvが存在しない場合はR(A)にnilを代入する。
OP_SETUPVAR (0x16)
OP_SETUPVAR A, B, C --> uvset(B, C, R(A))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | C | 0010110 |
C段分上位のメソッド/ブロックの変数R(B)に、R(A)の内容を代入する。C段の遡り方はOP_GETUPVARに同じ。
対応するenvが存在しない場合は、何もしない。(エラーにもならない)
OP_JMP (0x17)
OP_JMP sBx --> pc += sBx
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
| | | | | | | | | sBx(+32767オフセットされた整数値) | 0010111 |
PCを変更し、現在のirep中でジャンプする。なお、変更前のPCはこのJMP命令がある場所そのものであり、PC++する前の値である。
また、JMP命令なのでPC++は実施されない。従って、-32767個前~JMP命令自身~+32768個後まで合計65536通りの場所にジャンプできる。
OP_JMPIF (0x18)
OP_JMPIF A, sBx --> if R(A) pc += sBx
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | sBx(+32767オフセットされた整数値) | 0011000 |
R(A)がfalseまたはnilのときは、ジャンプしない(つまりPC++)。それ以外の時はJMP命令と同様にジャンプする。
OP_JMPNOT (0x19)
OP_JMPNOT A, sBx --> if !R(A) pc += sBx
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | sBx(+32767オフセットされた整数値) | 0011001 |
R(A)がfalseまたはnilのとき、JMP命令と同様にジャンプする。それ以外の時はジャンプしない(つまりPC++)。
OP_ONERR (0x1a)
OP_ONERR sBx --> rescue_push(pc + sBx)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
| | | | | | | | | sBx(+32767オフセットされた整数値) | 0011010 |
rescue節を登録する。登録先のmrb→rescueが未生成の場合、サイズ16で作成。mrb→rescueのサイズ(mrb→rsize)が足りない場合、自動的に2倍に拡張する。
登録はPC+sBxの計算結果をrescueの現在位置(0から昇順)に記録する。mrb→ci→ridxは次のrescue保存位置を指す。
OP_RESCUE (0x1b)
OP_RESCUE A --> clear(exc); R(A) := exception (ignore when A=0)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | | | | | | | | | | | | | | | | | 0011011 |
R(A)に現在のRObject* mrb→excの内容を設定する。mrb→excはNULLに設定される。
OP_POPERR (0x1c)
OP_POPERR A --> A.times { rescue_pop() }
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | | | | | | | | | | | | | | | | | 0011100 |
mrb→ci→ridxをAだけ減らす。ONERRで登録したrescue節を通らずに抜けるのに利用する。
OP_RAISE (0x1d)
OP_RAISE A --> raise(R(A))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | | | | | | | | | | | | | | | | | 0011101 |
例外を投げる。投げる例外オブジェクトはR(A)。なお、これは例外オブジェクトでなければならない。つまり、
NilClass,TrueClass,FalseClass,Fixnumといった型は渡せず、内部表現が mrb_value.value.p を用いる型しか渡せない(これは言語仕様でも規定されている)。
OP_EPUSH (0x1e)
OP_EPUSH Bx --> ensure_push(SEQ[Bx])
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
| | | | | | | | | Bx | 0011110 |
ensure節を登録する。(irep→idx+Bx)番目のirepのクロージャを新規作成し、それをmrb→ensureに登録する。
mrb→ensureバッファはrescueバッファ同様に、未作成ならサイズ16で作成、個数オーバーなら2倍拡張となる。
mrb→ci→eidxは次の登録番号(つまり現在の登録個数)を指す。
OP_EPOP (0x1f)
OP_EPOP A --> A.times { ensure_pop().call }
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | | | | | | | | | | | | | | | | | 0011111 |
ensureバッファの最後尾にあるクロージャをpopしてecallする作業をA回繰り返す。ensure付きのブロックを抜ける(つまりensure節が実行される)ときに利用する。
OP_SEND (0x20)
(1) OP_SEND A, B, C (C=0) --> R(A) := call(R(A), mSym(B))
(3) OP_SEND A, B, C (0<C<127) --> R(A) := call(R(A), mSym(B), R(A+1), ..., R(A+C))
(2) OP_SEND A, B, C (C=127) --> R(A) := call(R(A), mSym(B), *R(A+1))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | C | 0100000 |
mSym(B)で指定された関数/メソッドを呼び出す。レシーバがR(A)、R(A+1)~R(A+C)が引数(C=0のときは無し)、
R(A+C+1)がブロック(SENDならnilを自動代入、SENDBならブロック)となる。ただしこれは引数が126個以下の場合で、
引数が127個以上の場合は、引数を収めたArrayをR(A+1)に、R(A+2)にブロックを格納し、C=127とする。
レシーバの型内でメソッド(シンボルmSym(B))の検索を行い、該当するものが存在しない場合は、method_missingというメソッドの
呼び出しにすり替えて実行する。すり替えを実施する場合、見つからなかったシンボルが第1引数となり、第2引数以降が元々の引数となる。
callinfoバッファに1つpush。
これから呼ぶメソッドのシンボルをci→mid、そのprocをci→proc、
現在のスタックトップをci→stackidx、引数の個数
2)をci→argc、レシーバのクラスをci→target_class、現在のpc+1をci→pc、A値をci→accにそれぞれ代入する。
スタックをAずらす。つまり、呼び出し先のR'(0)が現在のR(A)となる。(だから、R(A)にレシーバを入れると丁度いいわけだ。)
呼び出し自体は、呼び出し先の種類(C実装のfunction/Ruby実装のmethod)によって異なる。
OP_SENDB (0x21)
(1) OP_SENDB A, B, C (C=0) --> R(A) := call(R(A), mSym(B), &R(A+1))
(3) OP_SENDB A, B, C (0<C<127) --> R(A) := call(R(A), mSym(B), R(A+1), ..., R(A+C), &R(A+C+1))
(2) OP_SENDB A, B, C (C=127) --> R(A) := call(R(A), mSym(B), *R(A+1), &R(A+2))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | C | 0100001 |
説明は OP_SEND を参照。
OP_FSEND (0x22)
OP_CALL (0x23)
OP_CALL --> self.call(frame.argc, frame.argv)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
| | | | | | | | | | | | | | | | | | | | | | | | | 0100011 |
Proc#callの実装用命令。codegenで生成されることはなく、Proc#call(またはProc#[])の内部実装のみに使われている。
これの命令が実行された場合、selfつまりR(0)はProcのインスタンスを指しており、それが保持しているクロージャmへのcallにすり替える作業を行う。
ci→target_classにm→target_classを上書き
ci→procにmを上書き
(m→envが存在すれば) ci→midにm→env→midを上書き
(m→envが存在し、m→env→stackが存在しなければ) m→env→stackにmrb→stackを代入
あとはSENDと同じ。
OP_SUPER (0x24)
OP_SUPER A, C --> R(A) := super(R(A+1), ..., R(A+C+1))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | | | | | | | | | | C | 0100100 |
self(==R(0))をレシーバとし、ci→target_class→superからci→midのシンボルを探して実行する。
呼び出し本体の挙動はSENDと同じ。
OP_ARGARY (0x25)
OP_ENTER (0x26)
OP_ENTER Ax --> argument setup (m1:o:r:m2:k:kd:b)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
Ax | 0100110 |
| | m1 | o | r | m2 | k | kd | b |
メソッドやブロックの先頭で用いられ、スタックに積まれた引数を使用できるようにする命令。
各パラメータの意味は以下の通り。
現在のproc(ci→proc)のフラグがMRB_PROC_STRICTを持っているときは、引数の個数チェックを行う。
逆に言うと、STRICTフラグがないのはeachなどのイテレータブロックを呼び出す場合。Hash#eachだと受け側ブロックの引数が一つだと
[key, value]で受け取れるし、二つだと key, value となる。この曖昧さはSTRICTを外すことで得られている。
受け取り側の引数の数でci→argcを上書きしたあと、引数の個数差に応じて調整を行う。
OP_KARG (0x27)
未実装
OP_KDICT (0x28)
未実装
OP_RETURN (0x29)
OP_RETURN A --> retrun R(A)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | | | | | | | | 0101001 |
* 例外(mrb→exc)がある場合【L_RAISE処理】
例外オブジェクト(以下exc)の@lastpcにpcを保存
excの@ciidxに現在のciの位置(cibaseからのインデックス)を保存
ciがcibaseと同じ(つまり最上位フレームに居る)場合、ci→ridxが非0であればL_RESCUE処理へ。ci→irdxが0であればL_STOPへ。
現在のridxと一つ上位(ci[-1])のridxが異なる値になるまで、以下を繰り返し
callinfoバッファから1つpop
popしたciのaccが-1かつmrb_run開始時のmrb→jmpが非NULLの場合、上位のmrb_runにてsetjmpが設定されている(≒擬似的なtryブロックの中にいる)とみなし、longjmp(1)でthrowする。
ensureバッファにある内容について、pop後の最下位ci→eidxより大きいものをすべてecall
mrb→ciがmrb→cibaseに達していたら、ループ終了しL_RESCUE処理へ
ここから【L_RESCUE処理】
irepをci→procのirepに設定、pool,symsも新irepに合わせて変更する
regs、stackをci[1].stackidxを用いて戻す。
pcをrescueバッファの[–ci→ridx]番目に設定してそこから実行再開
例外がない場合
B=OP_R_RETURN(2)の場合
proc→envがNULL、または、現在いるprocがSTRICTの場合はOP_R_NOMRALの処理へ移動
-
B=OP_R_NORMAL(0)の場合
mrb→ciがcallinfoバッファの先頭の場合、returnできない所にいるはずなので“LocalJumpError: unexpected return”を起こすためL_RAISEへ。
ローカル変数ciをmrb→ciとする。
B=OP_R_BREAK(1)の場合
proc→env→cioffが負の場合、breakするべきブロック内に居ないことになるので“LocalJumpError: unexpected break”を起こすためL_RAISEへ。
ローカル変数ci、mrb→ciをcallinfoバッファの[proc→env→cioff+1]番目とする。
callinfoバッファを1つpop
OP_TAILCALL (0x2a)
01/16現在、ディスアセンブリのみ対応。コード生成箇所無し。
OP_BLKPUSH (0x2b)
OP_ADD (0x2c)
OP_ADDI (0x2d)
OP_SUB (0x2e)
OP_SUBI (0x2f)
OP_MUL (0x30)
OP_DIV (0x31)
OP_EQ (0x32)
OP_EQ A, B, C --> R(A) := R(A) == R(A+1)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B (mSyms[B]=:== ) | C (0000001) | 0110010 |
OP_LT (0x33)
OP_EQ A, B, C --> R(A) := R(A) == R(A+1)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B (mSyms[B]=:< ) | C (0000001) | 0110011 |
OP_LE (0x34)
OP_EQ A, B, C --> R(A) := R(A) == R(A+1)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B (mSyms[B]=:< = ) | C (0000001) | 0110100 |
OP_GT (0x35)
OP_EQ A, B, C --> R(A) := R(A) == R(A+1)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B (mSyms[B]=:> ) | C (0000001) | 0110101 |
OP_GE (0x36)
OP_EQ A, B, C --> R(A) := R(A) == R(A+1)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B (mSyms[B]=:>= ) | C (0000001) | 0110110 |
OP_ARRAY (0x37)
OP_ARRAY A, B, C (C>0) --> R(A) := ary_new(R(B), R(B+1), ..., R(B+C))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | C (0000001) | 0110111 |
OP_ARYCAT (0x38)
OP_ARYCAT A, B --> ary_cat(R(A), R(B))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | | | | | | | | 0111000 |
OP_ARYPUSH (0x39)
OP_ARYPUSH A, B --> ary_push(R(A), R(B))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | | | | | | | | 0111001 |
OP_AREF (0x3a)
OP_AREF A, B, C --> R(A) := R(B)[C]
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | C | 0111010 |
配列の要素参照。ただし、言語仕様上で配列扱いとなる部分に対して使われる。なお、R(B)が配列では無い場合、エラーとはならずR(A)にnilが代入される。
# 次の例はOP_AREFではなく、ただの[]メソッド呼び出しである。
b = a[1]
# 000 OP_MOVE R4 (a)
# 001 OP_LOADI R5 1
# 002 OP_SEND R4 :[] 1
# 次のように多重代入を行う場合は、a,b,cに代入すべき値の取り出しがOP_AREFで行われる。
a,b,c = foo
# 000 OP_MOVE R4 (foo)
# 001 OP_AREF R1 R4 0
# 002 OP_AREF R2 R4 1
# 003 OP_AREF R3 R4 2
OP_ASET (0x3b)
OP_ASET A, B, C --> R(B)[C] := R(A)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | C | 0111011 |
OP_AREFの反対で、配列への代入。 現時点では使われている様子がない。
OP_APOST (0x3c)
OP_APOST A, B, C --> *R(A), R(A+1), ..., R(A+C) := R(A)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | C | 0111100 |
OP_STRING (0x3d)
OP_STRING A, Bx --> R(A) := str_dup(Lit(Bx))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 0111101 |
Lit(Bx)にある文字列をもつStringのインスタンスを生成し、R(A)に代入する。
OP_STRCAT (0x3e)
OP_STRCAT A, B --> str_cat(R(A), R(B))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | | | | | | | | 0111110 |
文字列R(A)の末端に文字列R(B)を連結する。R(A)に対しては破壊的。R(B)は破壊されない。
R(A)やR(B)がStringでなかった場合は?
OP_HASH (0x3f)
OP_HASH A, B, C --> R(A) := hash_new(R(B), R(B+1), ..., R(B+C))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | C | 0111111 |
OP_LAMBDA (0x40)
OP_LAMBDA A, b, c--> R(A) := lambda(SEQ[b], c)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | b | c | 1000000 |
OP_RANGE (0x41)
OP_RANGE A, B, C --> R(A) := range_new(R(B), R(B+1), C)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | C | 1000001 |
OP_OCLASS (0x42)
OP_OCLASS A --> R(A) := ::Object
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | | | | | | | | | | | | | | | | | 1000010 |
::ObjectをR(A)に代入する。
OP_CLASS (0x43)
OP_CLASS A, B --> R(A) := newclass(R(A), mSym(B), R(A+1))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | | | | | | | | 1000011 |
クラスを定義する。R(A)はbase(たいていnil入れてるけど何これ?)、R(A+1)はsuper。
OP_MODULE (0x44)
OP_MODULE A, B --> R(A) := newmodule(R(A), mSym(B))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | | | | | | | | 1000100 |
OP_EXEC (0x45)
OP_EXEC A, Bx --> R(A) := blockexec(R(A), SEQ[Bx])
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | Bx | 1000101 |
OP_METHOD (0x46)
OP_METHOD A, B --> R(A).newmethod(mSym(B), R(A+1))
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | | | | | | | | 1000110 |
OP_SCLASS (0x47)
OP_SCLASS A, B --> R(A) := R(B).singleton_class
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | B | | | | | | | | 1000111 |
R(B)のクラスを元として、singletonクラスを作成する。singletonクラスとは、元のクラスと同じ機能を継承した上で、特異メソッドなどを持つインスタンス固有のクラス。
なお、singletonクラスに対して OP_SCLASS を実行すると、
OP_TCLASS (0x48)
OP_TCLASS A --> R(A) := target_class
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | | | | | | | | | | | | | | | | | 1001000 |
OP_DEBUG (0x49)
OP_DEBUG A --> print R(A)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
A | | | | | | | | | | | | | | | | | 1001001 |
OP_STOP (0x4a)
OP_STOP --> Stop VM
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
| | | | | | | | | | | | | | | | | | | | | | | | | 1001010 |
OP_ERR (0x4b)
OP_ERR Bx --> raise RuntimeError with message Lit(Bx)
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
| | | | | | | | | Bx | 1001011 |
OP_RSVD1 (0x4c)
Reserved instruction #1
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
| | | | | | | | | | | | | | | | | | | | | | | | | 1001100 |
OP_RSVD1 (0x4d)
Reserved instruction #2
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
| | | | | | | | | | | | | | | | | | | | | | | | | 1001101 |
OP_RSVD1 (0x4e)
Reserved instruction #3
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
| | | | | | | | | | | | | | | | | | | | | | | | | 1001110 |
OP_RSVD1 (0x4f)
Reserved instruction #4
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
| | | | | | | | | | | | | | | | | | | | | | | | | 1001111 |
OP_RSVD1 (0x50)
Reserved instruction #5
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
| | | | | | | | | | | | | | | | | | | | | | | | | 1010000 |