====== mruby命令セット ======
対応risv:00090000
===== 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 |||||||
FIXME 現時点では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 |||||||
現時点では何もしない。FIXME
===== 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モジュール(内側から外側に向かって遡る)
* outerモジュールは ivから__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)の内容を登録する。FIXME 二重登録時の警告は?
===== 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)がクラス/モジュールでは無い((MRB_TT_CLASS,MRB_TT_MODULE,MRB_TT_SCLASSのいずれでもない))場合、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 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、引数の個数((Array渡しのときは-1))をci->argc、レシーバのクラスをci->target_class、現在のpc+1をci->pc、A値をci->accにそれぞれ代入する。
- スタックをAずらす。つまり、呼び出し先のR'(0)が現在のR(A)となる。(だから、R(A)にレシーバを入れると丁度いいわけだ。)
- 呼び出し自体は、呼び出し先の種類(C実装のfunction/Ruby実装のmethod)によって異なる。
* 呼び出し先がC実装関数(function)である場合
- 引数の個数((Array渡しの場合は1))+2をci->nregsに記憶
- mrbとレシーバを渡して該当関数を呼ぶ
- スタック末尾(つまりR(A))に関数の戻り値を格納
- mrc->excが設定されていればOP_RAISE処理へジャンプ
- レジスタ先頭位置、スタック位置をci->stackidxを用いて元に戻す。
- callinfoバッファから1つpopする。
* 呼び出し先がrubyのmethodである場合。
- 実行中proc、irep、pool、symsを呼び出し先メソッドの内容に変更する。
- irep->nregsをci->nregsに記憶
- スタックを拡張する
* Array渡しの場合、[irep->nregs,3].max 個確保(room)し、そのうち3個をkeepする。
* レジスタ渡しの場合、irep->nregs個確保(room)し、そのうち(ci->argc+2)個をkeepする。
- レジスタ先頭位置をスタック末尾(つまりR(A)==R'(0))の位置にする。
- PCをirepの先頭にする。
===== 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 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) =====
未実装。現時点ではNOPと同じ。
===== 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) =====
FIXME
===== 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 |:::|||||||
メソッドやブロックの先頭で用いられ、スタックに積まれた引数を使用できるようにする命令。
各パラメータの意味は以下の通り。
* m1 : 引数(省略不可)の個数
* o : 引数(省略可)の個数
* r : 可変長引数を受け取るとき1
* m2 : 不明。0以外を使っているところを見たことがない…。
* k : 未使用
* kd : 未使用
* b : ブロック引数(&block)を受け取るとき1
現在のproc(ci->proc)のフラグがMRB_PROC_STRICTを持っているときは、引数の個数チェックを行う。
逆に言うと、STRICTフラグがないのはeachなどのイテレータブロックを呼び出す場合。Hash#eachだと受け側ブロックの引数が一つだと
[key, value]で受け取れるし、二つだと key, value となる。この曖昧さはSTRICTを外すことで得られている。
受け取り側の引数の数でci->argcを上書きしたあと、引数の個数差に応じて調整を行う。
* 実際に与えられた個数(argc)が受け取り数(len)より少ない場合
- ブロック引数を適切な位置(regs[len+1])にコピーする
- (argc-m2)個を、argvからregs[1]にコピーする(配列渡しなど、argvとregs[1]が別領域の場合のみ)
- (m2)個をargv[argc-m2]からregs[len-m2-1]に移動する(m2>0の場合)
- regs[m1+o+1]に空の配列を作成する(r==1の場合)
- ジャンプする
* o==0の場合、通常どおりpc++して次の命令へ
* o!=0の場合、pc+=(argc-m1-m2+1)してその命令へ。
* 省略可能引数がある場合、その省略値をロードする命令群が含まれる。それらへのJMP命令をENTER命令の直後に省略可能引数の個数(o)だけ並べるルール。
* 実際に与えられた個数(argc)が受け取り数(len)以上の場合
- (m1+o)個を、argvからregs[1]にコピーする(配列渡しなど、argvとregs[1]が別領域の場合のみ)
- 可変長引数がある場合、regs[m1+o+1]に配列を作成する(配列の内容は(argv+m1+o)から、(argc-m1-o-m2)個)
- (m2)個をargv[argc-m2]からregs[m1+o+r+1]に移動する(m2>0の場合)
- ブロック引数を適切な位置(regs[len+1])にコピーする
- pc+=(o+1)して、その命令へ (省略可能引数のジャンプテーブル末端へ飛ばす)
===== OP_KARG (0x27) =====
未実装 FIXME
===== OP_KDICT (0x28) =====
未実装 FIXME
===== 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する。
* 上位mrb_runのcatch節はL_RAISEの先頭へ飛んでくる。
* 要するに、mrb_runの再帰呼び出しで処理している間に起きた例外を、最上位のmrb_runで吸収するための機構と思われる。
- ensureバッファにある内容について、pop後の最下位ci->eidxより大きいものをすべてecall
- mrb->ciがmrb->cibaseに達していたら、ループ終了しL_RESCUE処理へ
* このとき、ci->ridx==0の場合はregs、stackをスタック先頭に戻し、L_STOP処理へ。
- ここから【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の処理へ移動
- FIXME
* 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現在、ディスアセンブリのみ対応。コード生成箇所無し。FIXME
===== OP_BLKPUSH (0x2b) =====
FIXME
===== OP_ADD (0x2c) =====
FIXME
===== OP_ADDI (0x2d) =====
FIXME
===== OP_SUB (0x2e) =====
FIXME
===== OP_SUBI (0x2f) =====
FIXME
===== OP_MUL (0x30) =====
FIXME
===== OP_DIV (0x31) =====
FIXME
===== 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の反対で、配列への代入。FIXME 現時点では使われている様子がない。
===== 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)は破壊されない。
FIXME 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入れてるけど何これ?FIXME)、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 を実行すると、FIXME
===== 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 |||||||