mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
New bytecode implementation of mruby VM.
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
.DS_Store
|
||||
.ccmalloc
|
||||
.svn
|
||||
.vscode
|
||||
/.git
|
||||
cscope.files
|
||||
cscope.out
|
||||
|
||||
+260
@@ -0,0 +1,260 @@
|
||||
<<<<<<< HEAD
|
||||
# The new bytecode
|
||||
|
||||
We will reimplement VM to use 8bit instruction code. By
|
||||
bytecode, we mean real byte code. The whole purpose is
|
||||
reducing the memory consumption of mruby VM.
|
||||
|
||||
# Instructions
|
||||
|
||||
Instructions are bytes. There can be 256 instructions. Currently we
|
||||
have 94 instructions. Instructions can take 0 to 3 operands.
|
||||
|
||||
## operands
|
||||
|
||||
The size of operands can be either 8bits, 16bits or 24bits.
|
||||
In the table.1 below, the second field describes the size (and
|
||||
sign) of operands.
|
||||
|
||||
* B: 8bit
|
||||
* sB: signed 8bit
|
||||
* S: 16bit
|
||||
* sS: signed 16bit
|
||||
* W: 24bit
|
||||
|
||||
First two byte operands may be extended to 16bit. When those byte
|
||||
operands are bigger than 256, the instruction will be prefixed by
|
||||
`OP_EXT1` (means 1st operand is 16bit) or `OP_EXT2` (means 2nd operand
|
||||
is 16bit) or `OP_EXT3` (means 1st and 2nd operands are 16bit).
|
||||
|
||||
For instructions marked by `'`, `OP_EXT1` can be prefixed. For those
|
||||
with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
|
||||
|
||||
## table.1 Instruction Table
|
||||
|
||||
|Instruction Name |Operand type |Semantics
|
||||
|-----------------|-------------|-----------------
|
||||
|OP_NOP | - |
|
||||
|OP_MOVE" |BB |R(a) = R(b)
|
||||
|OP_LOADL" |BB |R(a) = Pool(b)
|
||||
|OP_LOADI" |BsB |R(a) = mrb_int(b)
|
||||
|OP_LOADI_0' |B |R(a) = 0
|
||||
|OP_LOADI_1' |B |R(a) = 1
|
||||
|OP_LOADI_2' |B |R(a) = 2
|
||||
|OP_LOADI_3' |B |R(a) = 3
|
||||
|OP_LOADSYM" |BB |R(a) = Syms(b)
|
||||
|OP_LOADNIL' |B |R(a) = nil
|
||||
|OP_LOADSELF' |B |R(a) = self
|
||||
|OP_LOADT' |B |R(a) = true
|
||||
|OP_LOADF' |B |R(a) = false
|
||||
|OP_GETGV" |BB |R(a) = getglobal(Syms(b))
|
||||
|OP_SETGV" |BB |setglobal(Syms(b), R(a))
|
||||
|OP_GETSV" |BB |R(a) = Special[b]
|
||||
|OP_SETSV" |BB |Special[b] = R(a)
|
||||
|OP_GETIV" |BB |R(a) = ivget(Syms(b))
|
||||
|OP_SETIV" |BB |ivset(Syms(b),R(a))
|
||||
|OP_GETCV" |BB |R(a) = cvget(Syms(b))
|
||||
|OP_SETCV" |BB |cvset(Syms(b),R(a))
|
||||
|OP_GETCONST" |BB |R(a) = constget(Syms(b))
|
||||
|OP_SETCONST" |BB |constset(Syms(b),R(a))
|
||||
|OP_GETMCNST" |BB |R(a) = R(a)::Syms(b)
|
||||
|OP_SETMCNST" |BB |R(a+1)::Syms(b) = R(a)
|
||||
|OP_GETUPVAR' |BBB |R(a) = uvget(b,c)
|
||||
|OP_SETUPVAR' |BBB |uvset(b,c,R(a))
|
||||
|OP_JMP |S |pc+=a
|
||||
|OP_JMPIF' |SB |if R(b) pc+=a
|
||||
|OP_JMPNOT' |SB |if !R(b) pc+=a
|
||||
|OP_ONERR |sS |rescue_push(pc+a)
|
||||
|OP_EXCEPT' |B |R(a) = exc
|
||||
|OP_RESCUE" |BB |R(b) = R(a).isa?(R(b))
|
||||
|OP_POPERR |B |a.times{rescue_pop()}
|
||||
|OP_RAISE' |B |raise(R(a))
|
||||
|OP_EPUSH' |B |ensure_push(SEQ[a])
|
||||
|OP_EPOP |B |A.times{ensure_pop().call}
|
||||
|OP_SENDV" |BB |R(a) = call(R(a),Syms(b),*R(a+1))
|
||||
|OP_SENDVB" |BB |R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2))
|
||||
|OP_SEND" |BBB |R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c))
|
||||
|OP_SENDB" |BBB |R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
|
||||
|OP_CALL' |B |R(a) = self.call(frame.argc, frame.argv)
|
||||
|OP_SUPER' |BB |R(a) = super(R(a+1),... ,R(a+b+1))
|
||||
|OP_ARGARY' |BS |R(a) = argument array (16=6:1:5:4)
|
||||
|OP_ENTER |W |arg setup according to flags (23=5:5:1:5:5:1:1)
|
||||
|OP_KARG" |BB |R(a) = kdict[Syms(Bx)] # todo
|
||||
|OP_KARG2" |BB |R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
|
||||
|OP_KDICT' |B |R(a) = kdict # todo
|
||||
|OP_RETURN' |B |return R(a) (normal)
|
||||
|OP_RETURN_BLK' |B |return R(a) (in-block return)
|
||||
|OP_BREAK' |B |break R(a)
|
||||
|OP_BLKPUSH' |BS |R(a) = block (16=6:1:5:4)
|
||||
|OP_ADD" |BB |R(a) = R(a)+R(a+1) (Syms[b]=:+)
|
||||
|OP_ADDI" |BBB |R(a) = R(a)+mrb_int(c) (Syms[b]=:+)
|
||||
|OP_SUB" |BB |R(a) = R(a)-R(a+1) (Syms[b]=:-)
|
||||
|OP_SUBI" |BB |R(a) = R(a)-C (Syms[b]=:-)
|
||||
|OP_MUL" |BB |R(a) = R(a)*R(a+1) (Syms[b]=:*)
|
||||
|OP_DIV" |BB |R(a) = R(a)/R(a+1) (Syms[b]=:/)
|
||||
|OP_EQ" |BB |R(a) = R(a)==R(a+1) (Syms[b]=:==)
|
||||
|OP_LT" |BB |R(a) = R(a)<R(a+1) (Syms[b]=:<)
|
||||
|OP_LE" |BB |R(a) = R(a)<=R(a+1) (Syms[b]=:<=)
|
||||
|OP_GT" |BB |R(a) = R(a)>R(a+1) (Syms[b]=:>)
|
||||
|OP_GE" |BB |R(a) = R(a)>=R(a+1) (Syms[b]=:>=)
|
||||
|OP_ARRAY' |BB |R(a) = ary_new(R(a),R(a+1)..R(a+b))
|
||||
|OP_ARRAY2" |BB |R(a) = ary_new(R(b),R(b+1)..R(b+c))
|
||||
|OP_ARYCAT' |B |ary_cat(R(a),R(a+1))
|
||||
|OP_ARYPUSH' |B |ary_push(R(a),R(a+1))
|
||||
|OP_AREF' |BB |R(a) = R(a)[b]
|
||||
|OP_ASET' |BB |R(a)[b] = R(a+1)
|
||||
|OP_APOST' |BB |*R(a),R(A+1)..R(A+C) = R(a)[B..]
|
||||
|OP_STRING" |BB |R(a) = str_dup(Lit(b))
|
||||
|OP_STRCAT' |B |str_cat(R(a),R(a+1))
|
||||
|OP_HASH' |BB |R(a) = hash_new(R(a),R(a+1)..R(a+b))
|
||||
|OP_HASHADD' |BB |R(a) = hash_push(R(a),R(a+1)..R(a+b))
|
||||
|OP_LAMBDA" |BB |R(a) = lambda(SEQ[b],OP_L_LAMBDA)
|
||||
|OP_BLOCK" |BB |R(a) = lambda(SEQ[b],OP_L_BLOCK)
|
||||
|OP_METHOD" |BB |R(a) = lambda(SEQ[b],OP_L_METHOD)
|
||||
|OP_RANGE_INC' |B |R(a) = range_new(R(a),R(a+1),FALSE)
|
||||
|OP_RANGE_EXC' |B |R(a) = range_new(R(a),R(a+1),TRUE)
|
||||
|OP_OCLASS' |B |R(a) = ::Object
|
||||
|OP_CLASS" |BB |R(a) = newclass(R(a),Syms(b),R(a+1))
|
||||
|OP_MODULE" |BB |R(a) = newmodule(R(a),Syms(b))
|
||||
|OP_EXEC" |BB |R(a) = blockexec(R(a),SEQ[b])
|
||||
|OP_DEF" |BB |R(a).newmethod(Syms(b),R(a+1))
|
||||
|OP_ALIAS' |B |alias_method(R(a),R(a+1),R(a+2))
|
||||
|OP_UNDEF" |BB |undef_method(R(a),Syms(b))
|
||||
|OP_SCLASS' |B |R(a) = R(a).singleton_class
|
||||
|OP_TCLASS' |B |R(a) = target_class
|
||||
|OP_ERR' |B |raise(RuntimeError, Lit(Bx))
|
||||
|OP_EXT1 |- |make 1st operand 16bit
|
||||
|OP_EXT2 |- |make 2nd operand 16bit
|
||||
|OP_EXT3 |- |make 1st and 2nd operands 16bit
|
||||
|OP_STOP |- |stop VM
|
||||
||||||| parent of b6821923... New bytecode implementation of mruby VM.
|
||||
=======
|
||||
# The new bytecode
|
||||
|
||||
We will reimplement VM to use 8bit instruction code. By
|
||||
bytecode, we mean real byte code. The whole purpose is
|
||||
reducing the memory consumption of mruby VM.
|
||||
|
||||
# Instructions
|
||||
|
||||
Instructions are bytes. There can be 256 instructions. Currently we
|
||||
have 94 instructions. Instructions can take 0 to 3 operands.
|
||||
|
||||
## operands
|
||||
|
||||
The size of operands can be either 8bits, 16bits or 24bits.
|
||||
In the table.1 below, the second field describes the size (and
|
||||
sign) of operands.
|
||||
|
||||
* B: 8bit
|
||||
* sB: signed 8bit
|
||||
* S: 16bit
|
||||
* sS: signed 16bit
|
||||
* W: 24bit
|
||||
|
||||
First two byte operands may be extended to 16bit. When those byte
|
||||
operands are bigger than 256, the instruction will be prefixed by
|
||||
`OP_EXT1` (means 1st operand is 16bit) or `OP_EXT2` (means 2nd operand
|
||||
is 16bit) or `OP_EXT3` (means 1st and 2nd operands are 16bit).
|
||||
|
||||
For instructions marked by `'`, `OP_EXT1` can be prefixed. For those
|
||||
with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
|
||||
|
||||
## table.1 Instruction Table
|
||||
|
||||
|Instruction Name |Operand type |Semantics
|
||||
|-----------------|-------------|-----------------
|
||||
|OP_NOP | - |
|
||||
|OP_MOVE" |BB |R(a) = R(b)
|
||||
|OP_LOADL" |BB |R(a) = Pool(b)
|
||||
|OP_LOADI" |BsB |R(a) = mrb_int(b)
|
||||
|OP_LOADI_0' |B |R(a) = 0
|
||||
|OP_LOADI_1' |B |R(a) = 1
|
||||
|OP_LOADI_2' |B |R(a) = 2
|
||||
|OP_LOADI_3' |B |R(a) = 3
|
||||
|OP_LOADSYM" |BB |R(a) = Syms(b)
|
||||
|OP_LOADNIL' |B |R(a) = nil
|
||||
|OP_LOADSELF' |B |R(a) = self
|
||||
|OP_LOADT' |B |R(a) = true
|
||||
|OP_LOADF' |B |R(a) = false
|
||||
|OP_GETGV" |BB |R(a) = getglobal(Syms(b))
|
||||
|OP_SETGV" |BB |setglobal(Syms(b), R(a))
|
||||
|OP_GETSV" |BB |R(a) = Special[b]
|
||||
|OP_SETSV" |BB |Special[b] = R(a)
|
||||
|OP_GETIV" |BB |R(a) = ivget(Syms(b))
|
||||
|OP_SETIV" |BB |ivset(Syms(b),R(a))
|
||||
|OP_GETCV" |BB |R(a) = cvget(Syms(b))
|
||||
|OP_SETCV" |BB |cvset(Syms(b),R(a))
|
||||
|OP_GETCONST" |BB |R(a) = constget(Syms(b))
|
||||
|OP_SETCONST" |BB |constset(Syms(b),R(a))
|
||||
|OP_GETMCNST" |BB |R(a) = R(a)::Syms(b)
|
||||
|OP_SETMCNST" |BB |R(a+1)::Syms(b) = R(a)
|
||||
|OP_GETUPVAR' |BBB |R(a) = uvget(b,c)
|
||||
|OP_SETUPVAR' |BBB |uvset(b,c,R(a))
|
||||
|OP_JMP |S |pc+=a
|
||||
|OP_JMPIF' |SB |if R(b) pc+=a
|
||||
|OP_JMPNOT' |SB |if !R(b) pc+=a
|
||||
|OP_ONERR |sS |rescue_push(pc+a)
|
||||
|OP_EXCEPT' |B |R(a) = exc
|
||||
|OP_RESCUE" |BB |R(b) = R(a).isa?(R(b))
|
||||
|OP_POPERR |B |a.times{rescue_pop()}
|
||||
|OP_RAISE' |B |raise(R(a))
|
||||
|OP_EPUSH' |B |ensure_push(SEQ[a])
|
||||
|OP_EPOP |B |A.times{ensure_pop().call}
|
||||
|OP_SENDV" |BB |R(a) = call(R(a),Syms(b),*R(a+1))
|
||||
|OP_SENDVB" |BB |R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2))
|
||||
|OP_SEND" |BBB |R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c))
|
||||
|OP_SENDB" |BBB |R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
|
||||
|OP_CALL' |B |R(a) = self.call(frame.argc, frame.argv)
|
||||
|OP_SUPER' |BB |R(a) = super(R(a+1),... ,R(a+b+1))
|
||||
|OP_ARGARY' |BS |R(a) = argument array (16=6:1:5:4)
|
||||
|OP_ENTER |W |arg setup according to flags (23=5:5:1:5:5:1:1)
|
||||
|OP_KARG" |BB |R(a) = kdict[Syms(Bx)] # todo
|
||||
|OP_KARG2" |BB |R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
|
||||
|OP_KDICT' |B |R(a) = kdict # todo
|
||||
|OP_RETURN' |B |return R(a) (normal)
|
||||
|OP_RETURN_BLK' |B |return R(a) (in-block return)
|
||||
|OP_BREAK' |B |break R(a)
|
||||
|OP_BLKPUSH' |BS |R(a) = block (16=6:1:5:4)
|
||||
|OP_ADD" |BB |R(a) = R(a)+R(a+1) (Syms[b]=:+)
|
||||
|OP_ADDI" |BBB |R(a) = R(a)+mrb_int(c) (Syms[b]=:+)
|
||||
|OP_SUB" |BB |R(a) = R(a)-R(a+1) (Syms[b]=:-)
|
||||
|OP_SUBI" |BB |R(a) = R(a)-C (Syms[b]=:-)
|
||||
|OP_MUL" |BB |R(a) = R(a)*R(a+1) (Syms[b]=:*)
|
||||
|OP_DIV" |BB |R(a) = R(a)/R(a+1) (Syms[b]=:/)
|
||||
|OP_EQ" |BB |R(a) = R(a)==R(a+1) (Syms[b]=:==)
|
||||
|OP_LT" |BB |R(a) = R(a)<R(a+1) (Syms[b]=:<)
|
||||
|OP_LE" |BB |R(a) = R(a)<=R(a+1) (Syms[b]=:<=)
|
||||
|OP_GT" |BB |R(a) = R(a)>R(a+1) (Syms[b]=:>)
|
||||
|OP_GE" |BB |R(a) = R(a)>=R(a+1) (Syms[b]=:>=)
|
||||
|OP_ARRAY' |BB |R(a) = ary_new(R(a),R(a+1)..R(a+b))
|
||||
|OP_ARRAY2" |BB |R(a) = ary_new(R(b),R(b+1)..R(b+c))
|
||||
|OP_ARYCAT' |B |ary_cat(R(a),R(a+1))
|
||||
|OP_ARYPUSH' |B |ary_push(R(a),R(a+1))
|
||||
|OP_AREF' |BB |R(a) = R(a)[b]
|
||||
|OP_ASET' |BB |R(a)[b] = R(a+1)
|
||||
|OP_APOST' |BB |*R(a),R(A+1)..R(A+C) = R(a)[B..]
|
||||
|OP_STRING" |BB |R(a) = str_dup(Lit(b))
|
||||
|OP_STRCAT' |B |str_cat(R(a),R(a+1))
|
||||
|OP_HASH' |BB |R(a) = hash_new(R(a),R(a+1)..R(a+b))
|
||||
|OP_HASHADD' |BB |R(a) = hash_push(R(a),R(a+1)..R(a+b))
|
||||
|OP_LAMBDA" |BB |R(a) = lambda(SEQ[b],OP_L_LAMBDA)
|
||||
|OP_BLOCK" |BB |R(a) = lambda(SEQ[b],OP_L_BLOCK)
|
||||
|OP_METHOD" |BB |R(a) = lambda(SEQ[b],OP_L_METHOD)
|
||||
|OP_RANGE_INC' |B |R(a) = range_new(R(a),R(a+1),FALSE)
|
||||
|OP_RANGE_EXC' |B |R(a) = range_new(R(a),R(a+1),TRUE)
|
||||
|OP_OCLASS' |B |R(a) = ::Object
|
||||
|OP_CLASS" |BB |R(a) = newclass(R(a),Syms(b),R(a+1))
|
||||
|OP_MODULE" |BB |R(a) = newmodule(R(a),Syms(b))
|
||||
|OP_EXEC" |BB |R(a) = blockexec(R(a),SEQ[b])
|
||||
|OP_DEF" |BB |R(a).newmethod(Syms(b),R(a+1))
|
||||
|OP_ALIAS' |B |alias_method(R(a),R(a+1),R(a+2))
|
||||
|OP_UNDEF" |BB |undef_method(R(a),Syms(b))
|
||||
|OP_SCLASS' |B |R(a) = R(a).singleton_class
|
||||
|OP_TCLASS' |B |R(a) = target_class
|
||||
|OP_ERR' |B |raise(RuntimeError, Lit(Bx))
|
||||
|OP_EXT1 |- |make 1st operand 16bit
|
||||
|OP_EXT2 |- |make 2nd operand 16bit
|
||||
|OP_EXT3 |- |make 1st and 2nd operands 16bit
|
||||
|OP_STOP |- |stop VM
|
||||
>>>>>>> b6821923... New bytecode implementation of mruby VM.
|
||||
+8
-8
@@ -93,7 +93,7 @@
|
||||
*/
|
||||
MRB_BEGIN_DECL
|
||||
|
||||
typedef uint32_t mrb_code;
|
||||
typedef uint8_t mrb_code;
|
||||
|
||||
/**
|
||||
* Required arguments signature type.
|
||||
@@ -123,9 +123,9 @@ typedef struct {
|
||||
mrb_sym mid;
|
||||
struct RProc *proc;
|
||||
mrb_value *stackent;
|
||||
int nregs;
|
||||
int ridx;
|
||||
int epos;
|
||||
uint16_t nregs;
|
||||
uint16_t ridx;
|
||||
uint16_t epos;
|
||||
struct REnv *env;
|
||||
mrb_code *pc; /* return address */
|
||||
mrb_code *err; /* error position */
|
||||
@@ -152,10 +152,10 @@ struct mrb_context {
|
||||
mrb_callinfo *ci;
|
||||
mrb_callinfo *cibase, *ciend;
|
||||
|
||||
mrb_code **rescue; /* exception handler stack */
|
||||
uint16_t *rescue; /* exception handler stack */
|
||||
int rsize;
|
||||
struct RProc **ensure; /* ensure handler stack */
|
||||
int esize, eidx;
|
||||
uint8_t esize, eidx;
|
||||
|
||||
enum mrb_fiber_state status;
|
||||
mrb_bool vmexec;
|
||||
@@ -486,9 +486,10 @@ MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_
|
||||
* }
|
||||
* @param [mrb_state*] mrb_state* The mruby state reference.
|
||||
* @param [struct RClass*] RClass* A class the method will be undefined from.
|
||||
* @param [const char*] constchar* The name of the method to be undefined.
|
||||
* @param [const char] const char* The name of the method to be undefined.
|
||||
*/
|
||||
MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*);
|
||||
MRB_API void mrb_undef_method_id(mrb_state*, struct RClass*, mrb_sym);
|
||||
|
||||
/**
|
||||
* Undefine a class method.
|
||||
@@ -1197,7 +1198,6 @@ typedef enum call_type {
|
||||
CALL_TYPE_MAX
|
||||
} call_type;
|
||||
|
||||
MRB_API void mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2);
|
||||
MRB_API const char *mrb_class_name(mrb_state *mrb, struct RClass* klass);
|
||||
MRB_API void mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val);
|
||||
|
||||
|
||||
@@ -76,7 +76,8 @@ MRB_API struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb
|
||||
MRB_API struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
|
||||
MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, mrb_method_t);
|
||||
MRB_API void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec);
|
||||
MRB_API void mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b);
|
||||
MRB_API void mrb_alias_method(mrb_state*, struct RClass *c, mrb_sym a, mrb_sym b);
|
||||
MRB_API void mrb_define_alias(mrb_state*, struct RClass *c, const char* a, const char* b);
|
||||
|
||||
MRB_API mrb_method_t mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
|
||||
MRB_API mrb_method_t mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
|
||||
|
||||
@@ -33,6 +33,7 @@ typedef struct mrbc_context {
|
||||
mrb_bool no_exec:1;
|
||||
mrb_bool keep_lv:1;
|
||||
mrb_bool no_optimize:1;
|
||||
mrb_bool on_eval:1;
|
||||
|
||||
size_t parser_nerr;
|
||||
} mrbc_context;
|
||||
@@ -151,6 +152,7 @@ struct mrb_parser_state {
|
||||
mrb_ast_node *tree;
|
||||
|
||||
mrb_bool no_optimize:1;
|
||||
mrb_bool on_eval:1;
|
||||
mrb_bool capture_errors:1;
|
||||
struct mrb_parser_message error_buffer[10];
|
||||
struct mrb_parser_message warn_buffer[10];
|
||||
|
||||
@@ -44,7 +44,7 @@ typedef struct mrb_irep {
|
||||
uint16_t *lines;
|
||||
struct mrb_irep_debug_info* debug_info;
|
||||
|
||||
int ilen, plen, slen, rlen, refcnt;
|
||||
uint16_t ilen, plen, slen, rlen, refcnt;
|
||||
} mrb_irep;
|
||||
|
||||
#define MRB_ISEQ_NO_FREE 1
|
||||
|
||||
+47
-139
@@ -7,145 +7,10 @@
|
||||
#ifndef MRUBY_OPCODE_H
|
||||
#define MRUBY_OPCODE_H
|
||||
|
||||
#define MAXARG_Bx (0xffff)
|
||||
#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */
|
||||
|
||||
/* instructions: packed 32 bit */
|
||||
/* ------------------------------- */
|
||||
/* A:B:C:OP = 9: 9: 7: 7 */
|
||||
/* A:Bx:OP = 9:16: 7 */
|
||||
/* Ax:OP = 25: 7 */
|
||||
/* A:Bz:Cz:OP = 9:14: 2: 7 */
|
||||
|
||||
#define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f))
|
||||
#define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff))
|
||||
#define GETARG_B(i) ((int)((((mrb_code)(i)) >> 14) & 0x1ff))
|
||||
#define GETARG_C(i) ((int)((((mrb_code)(i)) >> 7) & 0x7f))
|
||||
#define GETARG_Bx(i) ((int)((((mrb_code)(i)) >> 7) & 0xffff))
|
||||
#define GETARG_sBx(i) ((int)(GETARG_Bx(i)-MAXARG_sBx))
|
||||
#define GETARG_Ax(i) ((int32_t)((((mrb_code)(i)) >> 7) & 0x1ffffff))
|
||||
#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+(n2))) & (((1<<(n1))-1))))
|
||||
#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<(n2))-1))))
|
||||
#define GETARG_b(i) GETARG_UNPACK_b(i,14,2)
|
||||
#define GETARG_c(i) GETARG_UNPACK_c(i,14,2)
|
||||
|
||||
#define MKOPCODE(op) ((op) & 0x7f)
|
||||
#define MKARG_A(c) ((mrb_code)((c) & 0x1ff) << 23)
|
||||
#define MKARG_B(c) ((mrb_code)((c) & 0x1ff) << 14)
|
||||
#define MKARG_C(c) (((c) & 0x7f) << 7)
|
||||
#define MKARG_Bx(v) ((mrb_code)((v) & 0xffff) << 7)
|
||||
#define MKARG_sBx(v) MKARG_Bx((v)+MAXARG_sBx)
|
||||
#define MKARG_Ax(v) ((mrb_code)((v) & 0x1ffffff) << 7)
|
||||
#define MKARG_PACK(b,n1,c,n2) ((((b) & ((1<<n1)-1)) << (7+n2))|(((c) & ((1<<n2)-1)) << 7))
|
||||
#define MKARG_bc(b,c) MKARG_PACK(b,14,c,2)
|
||||
|
||||
#define MKOP_A(op,a) (MKOPCODE(op)|MKARG_A(a))
|
||||
#define MKOP_AB(op,a,b) (MKOP_A(op,a)|MKARG_B(b))
|
||||
#define MKOP_ABC(op,a,b,c) (MKOP_AB(op,a,b)|MKARG_C(c))
|
||||
#define MKOP_ABx(op,a,bx) (MKOP_A(op,a)|MKARG_Bx(bx))
|
||||
#define MKOP_Bx(op,bx) (MKOPCODE(op)|MKARG_Bx(bx))
|
||||
#define MKOP_sBx(op,sbx) (MKOPCODE(op)|MKARG_sBx(sbx))
|
||||
#define MKOP_AsBx(op,a,sbx) (MKOP_A(op,a)|MKARG_sBx(sbx))
|
||||
#define MKOP_Ax(op,ax) (MKOPCODE(op)|MKARG_Ax(ax))
|
||||
#define MKOP_Abc(op,a,b,c) (MKOP_A(op,a)|MKARG_bc(b,c))
|
||||
|
||||
enum {
|
||||
/*-----------------------------------------------------------------------
|
||||
operation code operand description
|
||||
------------------------------------------------------------------------*/
|
||||
OP_NOP=0,/* */
|
||||
OP_MOVE,/* A B R(A) := R(B) */
|
||||
OP_LOADL,/* A Bx R(A) := Pool(Bx) */
|
||||
OP_LOADI,/* A sBx R(A) := sBx */
|
||||
OP_LOADSYM,/* A Bx R(A) := Syms(Bx) */
|
||||
OP_LOADNIL,/* A R(A) := nil */
|
||||
OP_LOADSELF,/* A R(A) := self */
|
||||
OP_LOADT,/* A R(A) := true */
|
||||
OP_LOADF,/* A R(A) := false */
|
||||
|
||||
OP_GETGLOBAL,/* A Bx R(A) := getglobal(Syms(Bx)) */
|
||||
OP_SETGLOBAL,/* A Bx setglobal(Syms(Bx), R(A)) */
|
||||
OP_GETSPECIAL,/*A Bx R(A) := Special[Bx] */
|
||||
OP_SETSPECIAL,/*A Bx Special[Bx] := R(A) */
|
||||
OP_GETIV,/* A Bx R(A) := ivget(Syms(Bx)) */
|
||||
OP_SETIV,/* A Bx ivset(Syms(Bx),R(A)) */
|
||||
OP_GETCV,/* A Bx R(A) := cvget(Syms(Bx)) */
|
||||
OP_SETCV,/* A Bx cvset(Syms(Bx),R(A)) */
|
||||
OP_GETCONST,/* A Bx R(A) := constget(Syms(Bx)) */
|
||||
OP_SETCONST,/* A Bx constset(Syms(Bx),R(A)) */
|
||||
OP_GETMCNST,/* A Bx R(A) := R(A)::Syms(Bx) */
|
||||
OP_SETMCNST,/* A Bx R(A+1)::Syms(Bx) := R(A) */
|
||||
OP_GETUPVAR,/* A B C R(A) := uvget(B,C) */
|
||||
OP_SETUPVAR,/* A B C uvset(B,C,R(A)) */
|
||||
|
||||
OP_JMP,/* sBx pc+=sBx */
|
||||
OP_JMPIF,/* A sBx if R(A) pc+=sBx */
|
||||
OP_JMPNOT,/* A sBx if !R(A) pc+=sBx */
|
||||
OP_ONERR,/* sBx rescue_push(pc+sBx) */
|
||||
OP_RESCUE,/* A B C if A (if C exc=R(A) else R(A) := exc);
|
||||
if B R(B) := exc.isa?(R(B)); clear(exc) */
|
||||
OP_POPERR,/* A A.times{rescue_pop()} */
|
||||
OP_RAISE,/* A raise(R(A)) */
|
||||
OP_EPUSH,/* Bx ensure_push(SEQ[Bx]) */
|
||||
OP_EPOP,/* A A.times{ensure_pop().call} */
|
||||
|
||||
OP_SEND,/* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */
|
||||
OP_SENDB,/* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/
|
||||
OP_FSEND,/* A B C R(A) := fcall(R(A),Syms(B),R(A+1),...,R(A+C-1)) */
|
||||
OP_CALL,/* A R(A) := self.call(frame.argc, frame.argv) */
|
||||
OP_SUPER,/* A C R(A) := super(R(A+1),... ,R(A+C+1)) */
|
||||
OP_ARGARY,/* A Bx R(A) := argument array (16=6:1:5:4) */
|
||||
OP_ENTER,/* Ax arg setup according to flags (23=5:5:1:5:5:1:1) */
|
||||
OP_KARG,/* A B C R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */
|
||||
OP_KDICT,/* A C R(A) := kdict */
|
||||
|
||||
OP_RETURN,/* A B return R(A) (B=normal,in-block return/break) */
|
||||
OP_TAILCALL,/* A B C return call(R(A),Syms(B),*R(C)) */
|
||||
OP_BLKPUSH,/* A Bx R(A) := block (16=6:1:5:4) */
|
||||
|
||||
OP_ADD,/* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1) */
|
||||
OP_ADDI,/* A B C R(A) := R(A)+C (Syms[B]=:+) */
|
||||
OP_SUB,/* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1) */
|
||||
OP_SUBI,/* A B C R(A) := R(A)-C (Syms[B]=:-) */
|
||||
OP_MUL,/* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1) */
|
||||
OP_DIV,/* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1) */
|
||||
OP_EQ,/* A B C R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1) */
|
||||
OP_LT,/* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1) */
|
||||
OP_LE,/* A B C R(A) := R(A)<=R(A+1) (Syms[B]=:<=,C=1) */
|
||||
OP_GT,/* A B C R(A) := R(A)>R(A+1) (Syms[B]=:>,C=1) */
|
||||
OP_GE,/* A B C R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1) */
|
||||
|
||||
OP_ARRAY,/* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */
|
||||
OP_ARYCAT,/* A B ary_cat(R(A),R(B)) */
|
||||
OP_ARYPUSH,/* A B ary_push(R(A),R(B)) */
|
||||
OP_AREF,/* A B C R(A) := R(B)[C] */
|
||||
OP_ASET,/* A B C R(B)[C] := R(A) */
|
||||
OP_APOST,/* A B C *R(A),R(A+1)..R(A+C) := R(A)[B..] */
|
||||
|
||||
OP_STRING,/* A Bx R(A) := str_dup(Lit(Bx)) */
|
||||
OP_STRCAT,/* A B str_cat(R(A),R(B)) */
|
||||
|
||||
OP_HASH,/* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */
|
||||
OP_LAMBDA,/* A Bz Cz R(A) := lambda(SEQ[Bz],Cz) */
|
||||
OP_RANGE,/* A B C R(A) := range_new(R(B),R(B+1),C) */
|
||||
|
||||
OP_OCLASS,/* A R(A) := ::Object */
|
||||
OP_CLASS,/* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */
|
||||
OP_MODULE,/* A B R(A) := newmodule(R(A),Syms(B)) */
|
||||
OP_EXEC,/* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */
|
||||
OP_METHOD,/* A B R(A).newmethod(Syms(B),R(A+1)) */
|
||||
OP_SCLASS,/* A B R(A) := R(B).singleton_class */
|
||||
OP_TCLASS,/* A R(A) := target_class */
|
||||
|
||||
OP_DEBUG,/* A B C print R(A),R(B),R(C) */
|
||||
OP_STOP,/* stop VM */
|
||||
OP_ERR,/* Bx raise RuntimeError with message Lit(Bx) */
|
||||
|
||||
OP_RSVD1,/* reserved instruction #1 */
|
||||
OP_RSVD2,/* reserved instruction #2 */
|
||||
OP_RSVD3,/* reserved instruction #3 */
|
||||
OP_RSVD4,/* reserved instruction #4 */
|
||||
OP_RSVD5,/* reserved instruction #5 */
|
||||
enum mrb_insn {
|
||||
#define OPCODE(x,_) OP_ ## x,
|
||||
#include "mruby/ops.h"
|
||||
#undef OPCODE
|
||||
};
|
||||
|
||||
#define OP_L_STRICT 1
|
||||
@@ -158,4 +23,47 @@ enum {
|
||||
#define OP_R_BREAK 1
|
||||
#define OP_R_RETURN 2
|
||||
|
||||
#define PEEK_B(pc) (*(pc))
|
||||
#define PEEK_S(pc) ((pc)[0]<<8|(pc)[1])
|
||||
#define PEEK_W(pc) ((pc)[0]<<16|(pc)[1]<<8|(pc)[2])
|
||||
|
||||
#define READ_B() PEEK_B(pc++)
|
||||
#define READ_S() (pc+=2, PEEK_S(pc-2))
|
||||
#define READ_W() (pc+=3, PEEK_W(pc-3))
|
||||
|
||||
#define FETCH_Z() /* nothing */
|
||||
#define FETCH_B() do {a=READ_B();} while (0)
|
||||
#define FETCH_BB() do {a=READ_B(); b=READ_B();} while (0)
|
||||
#define FETCH_BBB() do {a=READ_B(); b=READ_B(); c=READ_B();} while (0)
|
||||
#define FETCH_BS() do {a=READ_B(); b=READ_S();} while (0)
|
||||
#define FETCH_S() do {a=READ_S();} while (0)
|
||||
#define FETCH_W() do {a=READ_W();} while (0)
|
||||
|
||||
/* with OP_EXT1 (1st 16bit) */
|
||||
#define FETCH_Z_1() FETCH_Z()
|
||||
#define FETCH_B_1() FETCH_S()
|
||||
#define FETCH_BB_1() do {a=READ_S(); b=READ_B();} while (0)
|
||||
#define FETCH_BBB_1() do {a=READ_S(); b=READ_B(); c=READ_B();} while (0)
|
||||
#define FETCH_BS_1() do {a=READ_S(); b=READ_S();} while (0)
|
||||
#define FETCH_S_1() FETCH_S()
|
||||
#define FETCH_W_1() FETCH_W()
|
||||
|
||||
/* with OP_EXT2 (2nd 16bit) */
|
||||
#define FETCH_Z_2() FETCH_Z()
|
||||
#define FETCH_B_2() FETCH_B()
|
||||
#define FETCH_BB_2() do {a=READ_B(); b=READ_S();} while (0)
|
||||
#define FETCH_BBB_2() do {a=READ_B(); b=READ_S(); c=READ_B();} while (0)
|
||||
#define FETCH_BS_2() FETCH_BS()
|
||||
#define FETCH_S_2() FETCH_S()
|
||||
#define FETCH_W_2() FETCH_W()
|
||||
|
||||
/* with OP_EXT3 (1st & 2nd 16bit) */
|
||||
#define FETCH_Z_3() FETCH_Z()
|
||||
#define FETCH_B_3() FETCH_B()
|
||||
#define FETCH_BB_3() do {a=READ_S(); b=READ_S();} while (0)
|
||||
#define FETCH_BBB_3() do {a=READ_S(); b=READ_S(); c=READ_B();} while (0)
|
||||
#define FETCH_BS_3() do {a=READ_S(); b=READ_S();} while (0)
|
||||
#define FETCH_S_3() FETCH_S()
|
||||
#define FETCH_W_3() FETCH_W()
|
||||
|
||||
#endif /* MRUBY_OPCODE_H */
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/* operand types:
|
||||
+ Z: no operand (Z,Z,Z,Z)
|
||||
+ B: 8bit (B,S,B,B)
|
||||
+ BB: 8+8bit (BB,SB,BS,SS)
|
||||
+ BBB: 8+8+8bit (BBB,SBB,BSB,SSB)
|
||||
+ BS: 8+16bit (BS,SS,BS,BS)
|
||||
+ S: 16bit (S,S,S,S)
|
||||
+ W: 24bit (W,W,W,W)
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
operation code operands semantics
|
||||
------------------------------------------------------------------------*/
|
||||
OPCODE(NOP, Z) /* no operation */
|
||||
OPCODE(MOVE, BB) /* R(a) = R(b) */
|
||||
OPCODE(LOADL, BB) /* R(a) = Pool(b) */
|
||||
OPCODE(LOADI, BB) /* R(a) = mrb_int(b) */
|
||||
OPCODE(LOADINEG, BB) /* R(a) = mrb_int(-b) */
|
||||
OPCODE(LOADI__1, B) /* R(a) = mrb_int(-1) */
|
||||
OPCODE(LOADI_0, B) /* R(a) = mrb_int(0) */
|
||||
OPCODE(LOADI_1, B) /* R(a) = mrb_int(1) */
|
||||
OPCODE(LOADI_2, B) /* R(a) = mrb_int(2) */
|
||||
OPCODE(LOADI_3, B) /* R(a) = mrb_int(3) */
|
||||
OPCODE(LOADI_4, B) /* R(a) = mrb_int(4) */
|
||||
OPCODE(LOADI_5, B) /* R(a) = mrb_int(5) */
|
||||
OPCODE(LOADI_6, B) /* R(a) = mrb_int(6) */
|
||||
OPCODE(LOADI_7, B) /* R(a) = mrb_int(7) */
|
||||
OPCODE(LOADSYM, BB) /* R(a) = Syms(b) */
|
||||
OPCODE(LOADNIL, B) /* R(a) = nil */
|
||||
OPCODE(LOADSELF, B) /* R(a) = self */
|
||||
OPCODE(LOADT, B) /* R(a) = true */
|
||||
OPCODE(LOADF, B) /* R(a) = false */
|
||||
OPCODE(GETGV, BB) /* R(a) = getglobal(Syms(b)) */
|
||||
OPCODE(SETGV, BB) /* setglobal(Syms(b), R(a)) */
|
||||
OPCODE(GETSV, BB) /* R(a) = Special[Syms(b)] */
|
||||
OPCODE(SETSV, BB) /* Special[Syms(b)] = R(a) */
|
||||
OPCODE(GETIV, BB) /* R(a) = ivget(Syms(b)) */
|
||||
OPCODE(SETIV, BB) /* ivset(Syms(b),R(a)) */
|
||||
OPCODE(GETCV, BB) /* R(a) = cvget(Syms(b)) */
|
||||
OPCODE(SETCV, BB) /* cvset(Syms(b),R(a)) */
|
||||
OPCODE(GETCONST, BB) /* R(a) = constget(Syms(b)) */
|
||||
OPCODE(SETCONST, BB) /* constset(Syms(b),R(a)) */
|
||||
OPCODE(GETMCNST, BB) /* R(a) = R(a)::Syms(b) */
|
||||
OPCODE(SETMCNST, BB) /* R(a+1)::Syms(b) = R(a) */
|
||||
OPCODE(GETUPVAR, BBB) /* R(a) = uvget(b,c) */
|
||||
OPCODE(SETUPVAR, BBB) /* uvset(b,c,R(a)) */
|
||||
OPCODE(JMP, S) /* pc=a */
|
||||
OPCODE(JMPIF, BS) /* if R(b) pc=a */
|
||||
OPCODE(JMPNOT, BS) /* if !R(b) pc=a */
|
||||
OPCODE(JMPNIL, BS) /* if R(b)==nil pc=a */
|
||||
OPCODE(ONERR, S) /* rescue_push(a) */
|
||||
OPCODE(EXCEPT, B) /* R(a) = exc */
|
||||
OPCODE(RESCUE, BB) /* R(b) = R(a).isa?(R(b)) */
|
||||
OPCODE(POPERR, B) /* a.times{rescue_pop()} */
|
||||
OPCODE(RAISE, B) /* raise(R(a)) */
|
||||
OPCODE(EPUSH, B) /* ensure_push(SEQ[a]) */
|
||||
OPCODE(EPOP, B) /* A.times{ensure_pop().call} */
|
||||
OPCODE(SENDV, BB) /* R(a) = call(R(a),Syms(b),*R(a+1)) */
|
||||
OPCODE(SENDVB, BB) /* R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2)) */
|
||||
OPCODE(SEND, BBB) /* R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c)) */
|
||||
OPCODE(SENDB, BBB) /* R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1)) */
|
||||
OPCODE(CALL, Z) /* R(0) = self.call(frame.argc, frame.argv) */
|
||||
OPCODE(SUPER, BB) /* R(a) = super(R(a+1),... ,R(a+b+1)) */
|
||||
OPCODE(ARGARY, BS) /* R(a) = argument array (16=6:1:5:4) */
|
||||
OPCODE(ENTER, W) /* arg setup according to flags (23=5:5:1:5:5:1:1) */
|
||||
OPCODE(KARG, BB) /* R(a) = kdict[Syms(Bx)] # todo */
|
||||
OPCODE(KARG2, BB) /* R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo */
|
||||
OPCODE(KDICT, B) /* R(a) = kdict # todo */
|
||||
OPCODE(RETURN, B) /* return R(a) (normal) */
|
||||
OPCODE(RETURN_BLK, B) /* return R(a) (in-block return) */
|
||||
OPCODE(BREAK, B) /* break R(a) */
|
||||
OPCODE(BLKPUSH, BS) /* R(a) = block (16=6:1:5:4) */
|
||||
OPCODE(ADD, BB) /* R(a) = R(a)+R(a+1) (Syms[b]=:+) */
|
||||
OPCODE(ADDI, BBB) /* R(a) = R(a)+mrb_int(c) (Syms[b]=:+) */
|
||||
OPCODE(SUB, BB) /* R(a) = R(a)-R(a+1) (Syms[b]=:-) */
|
||||
OPCODE(SUBI, BBB) /* R(a) = R(a)-C (Syms[b]=:-) */
|
||||
OPCODE(MUL, BB) /* R(a) = R(a)*R(a+1) (Syms[b]=:*) */
|
||||
OPCODE(DIV, BB) /* R(a) = R(a)/R(a+1) (Syms[b]=:/) */
|
||||
OPCODE(EQ, BB) /* R(a) = R(a)==R(a+1) (Syms[b]=:==) */
|
||||
OPCODE(LT, BB) /* R(a) = R(a)<R(a+1) (Syms[b]=:<) */
|
||||
OPCODE(LE, BB) /* R(a) = R(a)<=R(a+1) (Syms[b]=:<=) */
|
||||
OPCODE(GT, BB) /* R(a) = R(a)>R(a+1) (Syms[b]=:>) */
|
||||
OPCODE(GE, BB) /* R(a) = R(a)>=R(a+1) (Syms[b]=:>=) */
|
||||
OPCODE(ARRAY, BB) /* R(a) = ary_new(R(a),R(a+1)..R(a+b)) */
|
||||
OPCODE(ARRAY2, BBB) /* R(a) = ary_new(R(b),R(b+1)..R(b+c)) */
|
||||
OPCODE(ARYCAT, B) /* ary_cat(R(a),R(a+1)) */
|
||||
OPCODE(ARYPUSH, B) /* ary_push(R(a),R(a+1)) */
|
||||
OPCODE(ARYDUP, B) /* R(a) = ary_dup(R(a)) */
|
||||
OPCODE(AREF, BBB) /* R(a) = R(b)[c] */
|
||||
OPCODE(ASET, BBB) /* R(a)[c] = R(b) */
|
||||
OPCODE(APOST, BBB) /* *R(a),R(a+1)..R(a+C) = R(a)[b..] */
|
||||
OPCODE(INTERN, B) /* R(a) = intern(R(a)) */
|
||||
OPCODE(STRING, BB) /* R(a) = str_dup(Lit(b)) */
|
||||
OPCODE(STRCAT, B) /* str_cat(R(a),R(a+1)) */
|
||||
OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b)) */
|
||||
OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b)) */
|
||||
OPCODE(LAMBDA, BB) /* R(a) = lambda(SEQ[b],L_LAMBDA) */
|
||||
OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */
|
||||
OPCODE(METHOD, BB) /* R(a) = lambda(SEQ[b],L_METHOD) */
|
||||
OPCODE(RANGE_INC, B) /* R(a) = range_new(R(a),R(a+1),FALSE) */
|
||||
OPCODE(RANGE_EXC, B) /* R(a) = range_new(R(a),R(a+1),TRUE) */
|
||||
OPCODE(OCLASS, B) /* R(a) = ::Object */
|
||||
OPCODE(CLASS, BB) /* R(a) = newclass(R(a),Syms(b),R(a+1)) */
|
||||
OPCODE(MODULE, BB) /* R(a) = newmodule(R(a),Syms(b)) */
|
||||
OPCODE(EXEC, BB) /* R(a) = blockexec(R(a),SEQ[b]) */
|
||||
OPCODE(DEF, BB) /* R(a).newmethod(Syms(b),R(a+1)) */
|
||||
OPCODE(ALIAS, BB) /* alias_method(target_class,Syms(a),Syms(b)) */
|
||||
OPCODE(UNDEF, B) /* undef_method(target_class,Syms(a)) */
|
||||
OPCODE(SCLASS, B) /* R(a) = R(a).singleton_class */
|
||||
OPCODE(TCLASS, B) /* R(a) = target_class */
|
||||
OPCODE(DEBUG, BBB) /* print a,b,c */
|
||||
OPCODE(ERR, B) /* raise(LocalJumpError, Lit(a)) */
|
||||
OPCODE(EXT1, Z) /* make 1st operand 16bit */
|
||||
OPCODE(EXT2, Z) /* make 2nd operand 16bit */
|
||||
OPCODE(EXT3, Z) /* make 1st and 2nd operands 16bit */
|
||||
OPCODE(STOP, Z) /* stop VM */
|
||||
@@ -517,7 +517,7 @@ check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value
|
||||
bpno = dbg->method_bpno;
|
||||
dbg->method_bpno = 0;
|
||||
|
||||
switch(GET_OPCODE(*pc)) {
|
||||
switch(*pc) {
|
||||
case OP_SEND:
|
||||
case OP_SENDB:
|
||||
c = mrb_class(mrb, regs[GETARG_A(*pc)]);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5534,6 +5534,7 @@ parser_init_cxt(parser_state *p, mrbc_context *cxt)
|
||||
}
|
||||
p->capture_errors = cxt->capture_errors;
|
||||
p->no_optimize = cxt->no_optimize;
|
||||
p->on_eval = cxt->on_eval;
|
||||
if (cxt->partial_hook) {
|
||||
p->cxt = cxt;
|
||||
}
|
||||
@@ -6648,6 +6649,20 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
|
||||
dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
|
||||
break;
|
||||
|
||||
case NODE_LITERAL_DELIM:
|
||||
printf("NODE_LITERAL_DELIM\n");
|
||||
break;
|
||||
|
||||
case NODE_SYMBOLS:
|
||||
printf("NODE_SYMBOLS:\n");
|
||||
dump_recur(mrb, tree, offset+1);
|
||||
break;
|
||||
|
||||
case NODE_WORDS:
|
||||
printf("NODE_SYMBOLS:\n");
|
||||
dump_recur(mrb, tree, offset+1);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("node type: %d (0x%x)\n", nodetype, (unsigned)nodetype);
|
||||
break;
|
||||
|
||||
@@ -44,7 +44,7 @@ search_irep(mrb_irep *top, int bnest, int lev, mrb_irep *bottom)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline mrb_code
|
||||
static uint16_t
|
||||
search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
|
||||
{
|
||||
mrb_irep *virep;
|
||||
@@ -57,7 +57,7 @@ search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
|
||||
}
|
||||
for (pos = 0; pos < virep->nlocals - 1; pos++) {
|
||||
if (vsym == virep->lv[pos].name) {
|
||||
return (MKARG_B(pos + 1) | MKARG_C(level + bnest));
|
||||
return (pos+1)<<8 | (level+bnest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,8 +71,8 @@ irep_argc(mrb_irep *irep)
|
||||
mrb_code c;
|
||||
|
||||
c = irep->iseq[0];
|
||||
if (GET_OPCODE(c) == OP_ENTER) {
|
||||
mrb_aspec ax = GETARG_Ax(c);
|
||||
if (c == OP_ENTER) {
|
||||
mrb_aspec ax = PEEK_W(irep->iseq+1);
|
||||
/* extra 1 means a slot for block */
|
||||
return MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1;
|
||||
}
|
||||
@@ -88,95 +88,132 @@ potential_upvar_p(struct mrb_locals *lv, uint16_t v, int argc, uint16_t nlocals)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
extern uint8_t mrb_insn_size[];
|
||||
extern uint8_t mrb_insn_size1[];
|
||||
extern uint8_t mrb_insn_size2[];
|
||||
extern uint8_t mrb_insn_size3[];
|
||||
|
||||
static void
|
||||
patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
|
||||
{
|
||||
int i;
|
||||
mrb_code c;
|
||||
uint32_t a;
|
||||
uint16_t b;
|
||||
uint8_t c;
|
||||
mrb_code insn;
|
||||
int argc = irep_argc(irep);
|
||||
|
||||
for (i = 0; i < irep->ilen; i++) {
|
||||
c = irep->iseq[i];
|
||||
switch(GET_OPCODE(c)){
|
||||
for (i = 0; i < irep->ilen; ) {
|
||||
insn = irep->iseq[i];
|
||||
switch(insn){
|
||||
case OP_EPUSH:
|
||||
patch_irep(mrb, irep->reps[GETARG_Bx(c)], bnest + 1, top);
|
||||
b = PEEK_S(irep->iseq+i+1);
|
||||
patch_irep(mrb, irep->reps[b], bnest + 1, top);
|
||||
break;
|
||||
|
||||
case OP_LAMBDA:
|
||||
{
|
||||
int arg_c = GETARG_c(c);
|
||||
if (arg_c & OP_L_CAPTURE) {
|
||||
patch_irep(mrb, irep->reps[GETARG_b(c)], bnest + 1, top);
|
||||
}
|
||||
}
|
||||
case OP_BLOCK:
|
||||
a = PEEK_B(irep->iseq+i+1);
|
||||
b = PEEK_B(irep->iseq+i+2);
|
||||
patch_irep(mrb, irep->reps[b], bnest + 1, top);
|
||||
break;
|
||||
|
||||
case OP_SEND:
|
||||
if (GETARG_C(c) != 0) {
|
||||
b = PEEK_B(irep->iseq+i+2);
|
||||
c = PEEK_B(irep->iseq+i+3);
|
||||
if (c != 0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
mrb_code arg = search_variable(mrb, irep->syms[GETARG_B(c)], bnest);
|
||||
uint16_t arg = search_variable(mrb, irep->syms[b], bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
|
||||
irep->iseq[i] = OP_GETUPVAR;
|
||||
irep->iseq[i+2] = arg >> 8;
|
||||
irep->iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_MOVE:
|
||||
a = PEEK_B(irep->iseq+i+1);
|
||||
b = PEEK_B(irep->iseq+i+2);
|
||||
/* src part */
|
||||
if (potential_upvar_p(irep->lv, GETARG_B(c), argc, irep->nlocals)) {
|
||||
mrb_code arg = search_variable(mrb, irep->lv[GETARG_B(c) - 1].name, bnest);
|
||||
if (potential_upvar_p(irep->lv, b, argc, irep->nlocals)) {
|
||||
uint16_t arg = search_variable(mrb, irep->lv[b - 1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
|
||||
irep->iseq[i] = insn = OP_GETUPVAR;
|
||||
irep->iseq[i+2] = arg >> 8;
|
||||
irep->iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
/* dst part */
|
||||
if (potential_upvar_p(irep->lv, GETARG_A(c), argc, irep->nlocals)) {
|
||||
mrb_code arg = search_variable(mrb, irep->lv[GETARG_A(c) - 1].name, bnest);
|
||||
if (potential_upvar_p(irep->lv, a, argc, irep->nlocals)) {
|
||||
uint16_t arg = search_variable(mrb, irep->lv[a - 1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_B(c)) | arg;
|
||||
irep->iseq[i] = insn = OP_SETUPVAR;
|
||||
irep->iseq[i+1] = b;
|
||||
irep->iseq[i+2] = arg >> 8;
|
||||
irep->iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_GETUPVAR:
|
||||
a = PEEK_B(irep->iseq+i+1);
|
||||
b = PEEK_B(irep->iseq+i+2);
|
||||
c = PEEK_B(irep->iseq+i+3);
|
||||
{
|
||||
int lev = GETARG_C(c)+1;
|
||||
int lev = c+1;
|
||||
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
|
||||
if (potential_upvar_p(tmp->lv, GETARG_B(c), irep_argc(tmp), tmp->nlocals)) {
|
||||
mrb_code arg = search_variable(mrb, tmp->lv[GETARG_B(c)-1].name, bnest);
|
||||
if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
|
||||
mrb_code arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
|
||||
irep->iseq[i] = OP_GETUPVAR;
|
||||
irep->iseq[i+2] = arg >> 8;
|
||||
irep->iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_SETUPVAR:
|
||||
a = PEEK_B(irep->iseq+i+1);
|
||||
b = PEEK_B(irep->iseq+i+2);
|
||||
c = PEEK_B(irep->iseq+i+3);
|
||||
{
|
||||
int lev = GETARG_C(c)+1;
|
||||
int lev = c+1;
|
||||
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
|
||||
if (potential_upvar_p(tmp->lv, GETARG_B(c), irep_argc(tmp), tmp->nlocals)) {
|
||||
mrb_code arg = search_variable(mrb, tmp->lv[GETARG_B(c)-1].name, bnest);
|
||||
if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
|
||||
mrb_code arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
|
||||
irep->iseq[i] = OP_SETUPVAR;
|
||||
irep->iseq[i+1] = a;
|
||||
irep->iseq[i+2] = arg >> 8;
|
||||
irep->iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_STOP:
|
||||
if (mrb->c->ci->acc >= 0) {
|
||||
irep->iseq[i] = MKOP_AB(OP_RETURN, irep->nlocals, OP_R_NORMAL);
|
||||
}
|
||||
break;
|
||||
case OP_EXT1:
|
||||
insn = PEEK_B(irep->iseq+1);
|
||||
i += mrb_insn_size1[insn];
|
||||
continue;
|
||||
case OP_EXT2:
|
||||
insn = PEEK_B(irep->iseq+1);
|
||||
i += mrb_insn_size2[insn];
|
||||
continue;
|
||||
case OP_EXT3:
|
||||
insn = PEEK_B(irep->iseq+1);
|
||||
i += mrb_insn_size3[insn];
|
||||
continue;
|
||||
}
|
||||
i+=mrb_insn_size[insn];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,6 +240,7 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding,
|
||||
mrbc_filename(mrb, cxt, file ? file : "(eval)");
|
||||
cxt->capture_errors = TRUE;
|
||||
cxt->no_optimize = TRUE;
|
||||
cxt->on_eval = TRUE;
|
||||
|
||||
p = mrb_parse_nstring(mrb, s, len, cxt);
|
||||
|
||||
|
||||
@@ -387,7 +387,7 @@ mrb_mruby_method_gem_init(mrb_state* mrb)
|
||||
mrb_define_method(mrb, unbound_method, "bind", unbound_method_bind, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, unbound_method, "super_method", method_super_method, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, unbound_method, "==", method_eql, MRB_ARGS_REQ(1));
|
||||
mrb_alias_method(mrb, unbound_method, mrb_intern_lit(mrb, "eql?"), mrb_intern_lit(mrb, "=="));
|
||||
mrb_define_alias(mrb, unbound_method, "eql?", "==");
|
||||
mrb_define_method(mrb, unbound_method, "to_s", method_to_s, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, unbound_method, "inspect", method_to_s, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, unbound_method, "arity", method_arity, MRB_ARGS_NONE());
|
||||
@@ -396,11 +396,11 @@ mrb_mruby_method_gem_init(mrb_state* mrb)
|
||||
|
||||
mrb_undef_class_method(mrb, method, "new");
|
||||
mrb_define_method(mrb, method, "==", method_eql, MRB_ARGS_REQ(1));
|
||||
mrb_alias_method(mrb, method, mrb_intern_lit(mrb, "eql?"), mrb_intern_lit(mrb, "=="));
|
||||
mrb_define_alias(mrb, method, "eql?", "==");
|
||||
mrb_define_method(mrb, method, "to_s", method_to_s, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, method, "inspect", method_to_s, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, method, "call", method_call, MRB_ARGS_ANY());
|
||||
mrb_alias_method(mrb, method, mrb_intern_lit(mrb, "[]"), mrb_intern_lit(mrb, "call"));
|
||||
mrb_define_alias(mrb, method, "[]", "call");
|
||||
mrb_define_method(mrb, method, "unbind", method_unbind, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, method, "super_method", method_super_method, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, method, "arity", method_arity, MRB_ARGS_NONE());
|
||||
|
||||
@@ -109,6 +109,7 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self)
|
||||
mrb_aspec aspec;
|
||||
mrb_value sname, parameters;
|
||||
int i, j;
|
||||
int max = -1;
|
||||
|
||||
if (MRB_PROC_CFUNC_P(proc)) {
|
||||
// TODO cfunc aspec is not implemented yet
|
||||
@@ -120,7 +121,7 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self)
|
||||
if (!irep->lv) {
|
||||
return mrb_ary_new(mrb);
|
||||
}
|
||||
if (GET_OPCODE(*irep->iseq) != OP_ENTER) {
|
||||
if (*irep->iseq != OP_ENTER) {
|
||||
return mrb_ary_new(mrb);
|
||||
}
|
||||
|
||||
@@ -129,7 +130,7 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self)
|
||||
parameters_list[3].name = "opt";
|
||||
}
|
||||
|
||||
aspec = GETARG_Ax(*irep->iseq);
|
||||
aspec = PEEK_W(irep->iseq+1);
|
||||
parameters_list[0].size = MRB_ASPEC_REQ(aspec);
|
||||
parameters_list[1].size = MRB_ASPEC_OPT(aspec);
|
||||
parameters_list[2].size = MRB_ASPEC_REST(aspec);
|
||||
@@ -138,13 +139,16 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self)
|
||||
|
||||
parameters = mrb_ary_new_capa(mrb, irep->nlocals-1);
|
||||
|
||||
max = irep->nlocals-1;
|
||||
for (i = 0, p = parameters_list; p->name; p++) {
|
||||
if (p->size <= 0) continue;
|
||||
sname = mrb_symbol_value(mrb_intern_cstr(mrb, p->name));
|
||||
for (j = 0; j < p->size; i++, j++) {
|
||||
mrb_value a = mrb_ary_new(mrb);
|
||||
mrb_value a;
|
||||
|
||||
a = mrb_ary_new(mrb);
|
||||
mrb_ary_push(mrb, a, sname);
|
||||
if (irep->lv[i].name) {
|
||||
if (i < max && irep->lv[i].name) {
|
||||
mrb_ary_push(mrb, a, mrb_symbol_value(irep->lv[i].name));
|
||||
}
|
||||
mrb_ary_push(mrb, parameters, a);
|
||||
|
||||
@@ -627,8 +627,8 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb)
|
||||
mrb_define_method(mrb, s, "chr", mrb_str_chr, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, s, "succ", mrb_str_succ, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, s, "succ!", mrb_str_succ_bang, MRB_ARGS_NONE());
|
||||
mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ"));
|
||||
mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!"));
|
||||
mrb_define_alias(mrb, s, "next", "succ");
|
||||
mrb_define_alias(mrb, s, "next!", "succ!");
|
||||
mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, s, "delete_prefix!", mrb_str_del_prefix_bang, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, s, "delete_prefix", mrb_str_del_prefix, MRB_ARGS_REQ(1));
|
||||
|
||||
+4
-4
@@ -1953,8 +1953,8 @@ mrb_mod_alias(mrb_state *mrb, mrb_value mod)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static void
|
||||
undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
|
||||
void
|
||||
mrb_undef_method_id(mrb_state *mrb, struct RClass *c, mrb_sym a)
|
||||
{
|
||||
if (!mrb_obj_respond_to(mrb, c, a)) {
|
||||
mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c));
|
||||
@@ -1970,7 +1970,7 @@ undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
|
||||
MRB_API void
|
||||
mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name)
|
||||
{
|
||||
undef_method(mrb, c, mrb_intern_cstr(mrb, name));
|
||||
mrb_undef_method_id(mrb, c, mrb_intern_cstr(mrb, name));
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
@@ -1988,7 +1988,7 @@ mrb_mod_undef(mrb_state *mrb, mrb_value mod)
|
||||
|
||||
mrb_get_args(mrb, "*", &argv, &argc);
|
||||
while (argc--) {
|
||||
undef_method(mrb, c, to_sym(mrb, *argv));
|
||||
mrb_undef_method_id(mrb, c, to_sym(mrb, *argv));
|
||||
argv++;
|
||||
}
|
||||
return mrb_nil_value();
|
||||
|
||||
+374
-322
@@ -6,451 +6,503 @@
|
||||
#include <mruby/proc.h>
|
||||
|
||||
#ifndef MRB_DISABLE_STDIO
|
||||
static int
|
||||
print_r(mrb_state *mrb, mrb_irep *irep, size_t n, int pre)
|
||||
static void
|
||||
print_r(mrb_state *mrb, mrb_irep *irep, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (n == 0) return 0;
|
||||
if (n == 0) return;
|
||||
|
||||
for (i=0; i+1<irep->nlocals; i++) {
|
||||
if (irep->lv[i].r == n) {
|
||||
mrb_sym sym = irep->lv[i].name;
|
||||
if (pre) printf(" ");
|
||||
printf("R%d:%s", (int)n, mrb_sym2name(mrb, sym));
|
||||
return 1;
|
||||
printf(" R%d:%s", (int)n, mrb_sym2name(mrb, sym));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RA 1
|
||||
#define RB 2
|
||||
#define RAB 3
|
||||
|
||||
static void
|
||||
print_lv(mrb_state *mrb, mrb_irep *irep, mrb_code c, int r)
|
||||
print_lv_a(mrb_state *mrb, mrb_irep *irep, uint16_t a)
|
||||
{
|
||||
int pre = 0;
|
||||
|
||||
if (!irep->lv
|
||||
|| ((!(r & RA) || GETARG_A(c) >= irep->nlocals)
|
||||
&& (!(r & RB) || GETARG_B(c) >= irep->nlocals))) {
|
||||
if (!irep->lv || a >= irep->nlocals || a == 0) {
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
printf("\t; ");
|
||||
if (r & RA) {
|
||||
pre = print_r(mrb, irep, GETARG_A(c), 0);
|
||||
}
|
||||
if (r & RB) {
|
||||
print_r(mrb, irep, GETARG_B(c), pre);
|
||||
printf("\t;");
|
||||
print_r(mrb, irep, a);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
print_lv_ab(mrb_state *mrb, mrb_irep *irep, uint16_t a, uint16_t b)
|
||||
{
|
||||
if (!irep->lv || (a >= irep->nlocals && b >= irep->nlocals) || a+b == 0) {
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
printf("\t;");
|
||||
if (a > 0) print_r(mrb, irep, a);
|
||||
if (b > 0) print_r(mrb, irep, b);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
print_header(mrb_irep *irep, int i)
|
||||
{
|
||||
int32_t line;
|
||||
|
||||
line = mrb_debug_get_line(irep, i);
|
||||
if (line < 0) {
|
||||
printf(" ");
|
||||
}
|
||||
else {
|
||||
printf("%5d ", line);
|
||||
}
|
||||
|
||||
printf("%03d ", i);
|
||||
}
|
||||
|
||||
#define CASE(insn,ops) case insn: FETCH_ ## ops (); L_ ## insn
|
||||
|
||||
static void
|
||||
codedump(mrb_state *mrb, mrb_irep *irep)
|
||||
{
|
||||
#ifndef MRB_DISABLE_STDIO
|
||||
int i;
|
||||
int ai;
|
||||
mrb_code c;
|
||||
mrb_code *pc, *pcend;
|
||||
mrb_code ins;
|
||||
const char *file = NULL, *next_file;
|
||||
int32_t line;
|
||||
|
||||
if (!irep) return;
|
||||
printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", (void*)irep,
|
||||
irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen);
|
||||
|
||||
for (i = 0; i < (int)irep->ilen; i++) {
|
||||
pc = irep->iseq;
|
||||
pcend = pc + irep->ilen;
|
||||
while (pc < pcend) {
|
||||
int i;
|
||||
uint32_t a;
|
||||
uint16_t b;
|
||||
uint8_t c;
|
||||
|
||||
ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
i = pc - irep->iseq;
|
||||
next_file = mrb_debug_get_filename(irep, i);
|
||||
if (next_file && file != next_file) {
|
||||
printf("file: %s\n", next_file);
|
||||
file = next_file;
|
||||
}
|
||||
line = mrb_debug_get_line(irep, i);
|
||||
if (line < 0) {
|
||||
printf(" ");
|
||||
}
|
||||
else {
|
||||
printf("%5d ", line);
|
||||
}
|
||||
|
||||
printf("%03d ", i);
|
||||
c = irep->iseq[i];
|
||||
switch (GET_OPCODE(c)) {
|
||||
case OP_NOP:
|
||||
print_header(irep, i);
|
||||
ins = READ_B();
|
||||
switch (ins) {
|
||||
CASE(OP_NOP, Z):
|
||||
printf("OP_NOP\n");
|
||||
break;
|
||||
case OP_MOVE:
|
||||
printf("OP_MOVE\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
|
||||
print_lv(mrb, irep, c, RAB);
|
||||
CASE(OP_MOVE, BB):
|
||||
printf("OP_MOVE\tR%d\tR%d\t", a, b);
|
||||
print_lv_ab(mrb, irep, a, b);
|
||||
break;
|
||||
case OP_LOADL:
|
||||
CASE(OP_LOADL, BB):
|
||||
{
|
||||
mrb_value v = irep->pool[GETARG_Bx(c)];
|
||||
mrb_value v = irep->pool[b];
|
||||
mrb_value s = mrb_inspect(mrb, v);
|
||||
printf("OP_LOADL\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s));
|
||||
printf("OP_LOADL\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s));
|
||||
}
|
||||
print_lv(mrb, irep, c, RA);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_LOADI:
|
||||
printf("OP_LOADI\tR%d\t%d\t", GETARG_A(c), GETARG_sBx(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_LOADI, BB):
|
||||
printf("OP_LOADI\tR%d\t%d\t", a, b);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_LOADSYM:
|
||||
printf("OP_LOADSYM\tR%d\t:%s", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_LOADINEG, BB):
|
||||
printf("OP_LOADI\tR%d\t-%d\t", a, b);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_LOADNIL:
|
||||
printf("OP_LOADNIL\tR%d\t\t", GETARG_A(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_LOADI__1, B):
|
||||
printf("OP_LOADI__1\tR%d\t\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_LOADSELF:
|
||||
printf("OP_LOADSELF\tR%d\t\t", GETARG_A(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_LOADI_0, B): goto L_LOADI;
|
||||
CASE(OP_LOADI_1, B): goto L_LOADI;
|
||||
CASE(OP_LOADI_2, B): goto L_LOADI;
|
||||
CASE(OP_LOADI_3, B): goto L_LOADI;
|
||||
CASE(OP_LOADI_4, B): goto L_LOADI;
|
||||
CASE(OP_LOADI_5, B): goto L_LOADI;
|
||||
CASE(OP_LOADI_6, B): goto L_LOADI;
|
||||
CASE(OP_LOADI_7, B):
|
||||
L_LOADI:
|
||||
printf("OP_LOADI_%d\tR%d\t\t", ins-(int)OP_LOADI_0, a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_LOADT:
|
||||
printf("OP_LOADT\tR%d\t\t", GETARG_A(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_LOADSYM, BB):
|
||||
printf("OP_LOADSYM\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_LOADF:
|
||||
printf("OP_LOADF\tR%d\t\t", GETARG_A(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_LOADNIL, B):
|
||||
printf("OP_LOADNIL\tR%d\t\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_GETGLOBAL:
|
||||
printf("OP_GETGLOBAL\tR%d\t:%s", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_LOADSELF, B):
|
||||
printf("OP_LOADSELF\tR%d\t\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_SETGLOBAL:
|
||||
printf("OP_SETGLOBAL\t:%s\tR%d\t",
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
|
||||
GETARG_A(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_LOADT, B):
|
||||
printf("OP_LOADT\tR%d\t\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_GETCONST:
|
||||
printf("OP_GETCONST\tR%d\t:%s", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_LOADF, B):
|
||||
printf("OP_LOADF\tR%d\t\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_SETCONST:
|
||||
printf("OP_SETCONST\t:%s\tR%d\t",
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
|
||||
GETARG_A(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_GETGV, BB):
|
||||
printf("OP_GETGV\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_GETMCNST:
|
||||
printf("OP_GETMCNST\tR%d\tR%d::%s", GETARG_A(c), GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
|
||||
print_lv(mrb, irep, c, RAB);
|
||||
CASE(OP_SETGV, BB):
|
||||
printf("OP_SETGV\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_SETMCNST:
|
||||
printf("OP_SETMCNST\tR%d::%s\tR%d", GETARG_A(c)+1,
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
|
||||
GETARG_A(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_GETSV, BB):
|
||||
printf("OP_GETSV\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_GETIV:
|
||||
printf("OP_GETIV\tR%d\t%s", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_SETSV, BB):
|
||||
printf("OP_SETSV\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_SETIV:
|
||||
printf("OP_SETIV\t%s\tR%d",
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
|
||||
GETARG_A(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_GETCONST, BB):
|
||||
printf("OP_GETCONST\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_GETUPVAR:
|
||||
printf("OP_GETUPVAR\tR%d\t%d\t%d",
|
||||
GETARG_A(c), GETARG_B(c), GETARG_C(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_SETCONST, BB):
|
||||
printf("OP_SETCONST\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_SETUPVAR:
|
||||
printf("OP_SETUPVAR\tR%d\t%d\t%d",
|
||||
GETARG_A(c), GETARG_B(c), GETARG_C(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_GETMCNST, BB):
|
||||
printf("OP_GETMCNST\tR%d\tR%d::%s", a, a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_GETCV:
|
||||
printf("OP_GETCV\tR%d\t%s", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_SETMCNST, BB):
|
||||
printf("OP_SETMCNST\tR%d::%s\tR%d", a+1, mrb_sym2name(mrb, irep->syms[b]), a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_SETCV:
|
||||
printf("OP_SETCV\t%s\tR%d",
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
|
||||
GETARG_A(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_GETIV, BB):
|
||||
printf("OP_GETIV\tR%d\t%s", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_JMP:
|
||||
printf("OP_JMP\t%03d (%d)\n", i+GETARG_sBx(c), GETARG_sBx(c));
|
||||
CASE(OP_SETIV, BB):
|
||||
printf("OP_SETIV\t%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_JMPIF:
|
||||
printf("OP_JMPIF\tR%d\t%03d (%d)\n", GETARG_A(c), i+GETARG_sBx(c), GETARG_sBx(c));
|
||||
CASE(OP_GETUPVAR, BBB):
|
||||
printf("OP_GETUPVAR\tR%d\t%d\t%d", a, b, c);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_JMPNOT:
|
||||
printf("OP_JMPNOT\tR%d\t%03d (%d)\n", GETARG_A(c), i+GETARG_sBx(c), GETARG_sBx(c));
|
||||
CASE(OP_SETUPVAR, BBB):
|
||||
printf("OP_SETUPVAR\tR%d\t%d\t%d", a, b, c);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_SEND:
|
||||
printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_GETCV, BB):
|
||||
printf("OP_GETCV\tR%d\t%s", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_SENDB:
|
||||
printf("OP_SENDB\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_SETCV, BB):
|
||||
printf("OP_SETCV\t%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_CALL:
|
||||
printf("OP_CALL\tR%d\n", GETARG_A(c));
|
||||
CASE(OP_JMP, S):
|
||||
printf("OP_JMP\t\t%03d\n", a);
|
||||
break;
|
||||
case OP_TAILCALL:
|
||||
printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_JMPIF, BS):
|
||||
printf("OP_JMPIF\tR%d\t%03d\t", a, b);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_SUPER:
|
||||
printf("OP_SUPER\tR%d\t%d\n", GETARG_A(c),
|
||||
GETARG_C(c));
|
||||
CASE(OP_JMPNOT, BS):
|
||||
printf("OP_JMPNOT\tR%d\t%03d\t", a, b);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_ARGARY:
|
||||
printf("OP_ARGARY\tR%d\t%d:%d:%d:%d", GETARG_A(c),
|
||||
(GETARG_Bx(c)>>10)&0x3f,
|
||||
(GETARG_Bx(c)>>9)&0x1,
|
||||
(GETARG_Bx(c)>>4)&0x1f,
|
||||
(GETARG_Bx(c)>>0)&0xf);
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_JMPNIL, BS):
|
||||
printf("OP_JMPNIL\tR%d\t%03d\t", a, b);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
|
||||
case OP_ENTER:
|
||||
CASE(OP_SENDV, BB):
|
||||
printf("OP_SENDV\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
break;
|
||||
CASE(OP_SENDVB, BB):
|
||||
printf("OP_SENDVB\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
break;
|
||||
CASE(OP_SEND, BBB):
|
||||
printf("OP_SEND\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c);
|
||||
break;
|
||||
CASE(OP_SENDB, BBB):
|
||||
printf("OP_SENDB\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c);
|
||||
break;
|
||||
CASE(OP_CALL, Z):
|
||||
printf("OP_CALL\n");
|
||||
break;
|
||||
CASE(OP_SUPER, BB):
|
||||
printf("OP_SUPER\tR%d\t%d\n", a, b);
|
||||
break;
|
||||
CASE(OP_ARGARY, BS):
|
||||
printf("OP_ARGARY\tR%d\t%d:%d:%d:%d", a,
|
||||
(b>>10)&0x3f,
|
||||
(b>>9)&0x1,
|
||||
(b>>4)&0x1f,
|
||||
(b>>0)&0xf);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_ENTER, W):
|
||||
printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n",
|
||||
(GETARG_Ax(c)>>18)&0x1f,
|
||||
(GETARG_Ax(c)>>13)&0x1f,
|
||||
(GETARG_Ax(c)>>12)&0x1,
|
||||
(GETARG_Ax(c)>>7)&0x1f,
|
||||
(GETARG_Ax(c)>>2)&0x1f,
|
||||
(GETARG_Ax(c)>>1)&0x1,
|
||||
GETARG_Ax(c) & 0x1);
|
||||
(a>>18)&0x1f,
|
||||
(a>>13)&0x1f,
|
||||
(a>>12)&0x1,
|
||||
(a>>7)&0x1f,
|
||||
(a>>2)&0x1f,
|
||||
(a>>1)&0x1,
|
||||
a & 0x1);
|
||||
break;
|
||||
case OP_RETURN:
|
||||
printf("OP_RETURN\tR%d", GETARG_A(c));
|
||||
switch (GETARG_B(c)) {
|
||||
case OP_R_NORMAL:
|
||||
printf("\tnormal\t"); break;
|
||||
case OP_R_RETURN:
|
||||
printf("\treturn\t"); break;
|
||||
case OP_R_BREAK:
|
||||
printf("\tbreak\t"); break;
|
||||
default:
|
||||
printf("\tbroken\t"); break;
|
||||
}
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_KARG, BB):
|
||||
printf("OP_KARG\tR(%d)\tK(%d)\n", a, b);
|
||||
break;
|
||||
case OP_BLKPUSH:
|
||||
printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d", GETARG_A(c),
|
||||
(GETARG_Bx(c)>>10)&0x3f,
|
||||
(GETARG_Bx(c)>>9)&0x1,
|
||||
(GETARG_Bx(c)>>4)&0x1f,
|
||||
(GETARG_Bx(c)>>0)&0xf);
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_KARG2, BB):
|
||||
printf("OP_KARG2\tR(%d)\tK(%d)\n", a, b);
|
||||
break;
|
||||
|
||||
case OP_LAMBDA:
|
||||
printf("OP_LAMBDA\tR%d\tI(%+d)\t", GETARG_A(c), GETARG_b(c)+1);
|
||||
switch (GETARG_c(c)) {
|
||||
case OP_L_METHOD:
|
||||
printf("method"); break;
|
||||
case OP_L_BLOCK:
|
||||
printf("block"); break;
|
||||
case OP_L_LAMBDA:
|
||||
printf("lambda"); break;
|
||||
}
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_KDICT, B):
|
||||
printf("OP_KDICt\tR(%d)\n", a);
|
||||
break;
|
||||
case OP_RANGE:
|
||||
printf("OP_RANGE\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
|
||||
print_lv(mrb, irep, c, RAB);
|
||||
CASE(OP_RETURN, B):
|
||||
printf("OP_RETURN\tR%d", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_METHOD:
|
||||
printf("OP_METHOD\tR%d\t:%s", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_RETURN_BLK, B):
|
||||
printf("OP_RETURN_BLK\tR%d", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
|
||||
case OP_ADD:
|
||||
printf("OP_ADD\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_BREAK, B):
|
||||
printf("OP_BREAK\tR%d", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_ADDI:
|
||||
printf("OP_ADDI\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_BLKPUSH, BS):
|
||||
printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d", a,
|
||||
(b>>10)&0x3f,
|
||||
(b>>9)&0x1,
|
||||
(b>>4)&0x1f,
|
||||
(b>>0)&0xf);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_SUB:
|
||||
printf("OP_SUB\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_LAMBDA, BB):
|
||||
printf("OP_LAMBDA\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
|
||||
break;
|
||||
case OP_SUBI:
|
||||
printf("OP_SUBI\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_BLOCK, BB):
|
||||
printf("OP_BLOCK\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
|
||||
break;
|
||||
case OP_MUL:
|
||||
printf("OP_MUL\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_METHOD, BB):
|
||||
printf("OP_METHOD\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
|
||||
break;
|
||||
case OP_DIV:
|
||||
printf("OP_DIV\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_RANGE_INC, B):
|
||||
printf("OP_RANGE_INC\tR%d\n", a);
|
||||
break;
|
||||
case OP_LT:
|
||||
printf("OP_LT\t\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_RANGE_EXC, B):
|
||||
printf("OP_RANGE_EXC\tR%d\n", a);
|
||||
break;
|
||||
case OP_LE:
|
||||
printf("OP_LE\t\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_DEF, BB):
|
||||
printf("OP_DEF\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
break;
|
||||
case OP_GT:
|
||||
printf("OP_GT\t\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_UNDEF, B):
|
||||
printf("OP_UNDEF\t:%s\n", mrb_sym2name(mrb, irep->syms[a]));
|
||||
break;
|
||||
case OP_GE:
|
||||
printf("OP_GE\t\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_ALIAS, BB):
|
||||
printf("OP_ALIAS\t:%s\t%s\n", mrb_sym2name(mrb, irep->syms[a]), mrb_sym2name(mrb, irep->syms[b]));
|
||||
break;
|
||||
case OP_EQ:
|
||||
printf("OP_EQ\t\tR%d\t:%s\t%d\n", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
|
||||
GETARG_C(c));
|
||||
CASE(OP_ADD, BB):
|
||||
printf("OP_ADD\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
break;
|
||||
|
||||
case OP_STOP:
|
||||
printf("OP_STOP\n");
|
||||
CASE(OP_ADDI, BBB):
|
||||
printf("OP_ADDI\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c);
|
||||
break;
|
||||
|
||||
case OP_ARRAY:
|
||||
printf("OP_ARRAY\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
|
||||
print_lv(mrb, irep, c, RAB);
|
||||
CASE(OP_SUB, BB):
|
||||
printf("OP_SUB\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
break;
|
||||
case OP_ARYCAT:
|
||||
printf("OP_ARYCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
|
||||
print_lv(mrb, irep, c, RAB);
|
||||
CASE(OP_SUBI, BBB):
|
||||
printf("OP_SUBI\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c);
|
||||
break;
|
||||
case OP_ARYPUSH:
|
||||
printf("OP_ARYPUSH\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
|
||||
print_lv(mrb, irep, c, RAB);
|
||||
CASE(OP_MUL, BB):
|
||||
printf("OP_MUL\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
break;
|
||||
case OP_AREF:
|
||||
printf("OP_AREF\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
|
||||
print_lv(mrb, irep, c, RAB);
|
||||
CASE(OP_DIV, BB):
|
||||
printf("OP_DIV\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
break;
|
||||
case OP_APOST:
|
||||
printf("OP_APOST\tR%d\t%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_LT, BB):
|
||||
printf("OP_LT\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
break;
|
||||
case OP_STRING:
|
||||
CASE(OP_LE, BB):
|
||||
printf("OP_LE\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
break;
|
||||
CASE(OP_GT, BB):
|
||||
printf("OP_GT\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
break;
|
||||
CASE(OP_GE, BB):
|
||||
printf("OP_GE\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
break;
|
||||
CASE(OP_EQ, BB):
|
||||
printf("OP_EQ\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
break;
|
||||
CASE(OP_ARRAY, BB):
|
||||
printf("OP_ARRAY\tR%d\t%d\t", a, b);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_ARRAY2, BBB):
|
||||
printf("OP_ARRAY\tR%d\tR%d\t%d\t", a, b, c);
|
||||
print_lv_ab(mrb, irep, a, b);
|
||||
break;
|
||||
CASE(OP_ARYCAT, B):
|
||||
printf("OP_ARYCAT\tR%d\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_ARYPUSH, B):
|
||||
printf("OP_ARYPUSH\tR%d\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_ARYDUP, B):
|
||||
printf("OP_ARYDUP\tR%d\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_AREF, BBB):
|
||||
printf("OP_AREF\tR%d\tR%d\t%d", a, b, c);
|
||||
print_lv_ab(mrb, irep, a, b);
|
||||
break;
|
||||
CASE(OP_ASET, BBB):
|
||||
printf("OP_ASET\tR%d\tR%d\t%d", a, b, c);
|
||||
print_lv_ab(mrb, irep, a, b);
|
||||
break;
|
||||
CASE(OP_APOST, BBB):
|
||||
printf("OP_APOST\tR%d\t%d\t%d", a, b, c);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_INTERN, B):
|
||||
printf("OP_INTERN\tR%d", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_STRING, BB):
|
||||
{
|
||||
mrb_value v = irep->pool[GETARG_Bx(c)];
|
||||
mrb_value v = irep->pool[b];
|
||||
mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
|
||||
printf("OP_STRING\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s));
|
||||
printf("OP_STRING\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s));
|
||||
}
|
||||
print_lv(mrb, irep, c, RA);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_STRCAT:
|
||||
printf("OP_STRCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
|
||||
print_lv(mrb, irep, c, RAB);
|
||||
CASE(OP_STRCAT, B):
|
||||
printf("OP_STRCAT\tR%d\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_HASH:
|
||||
printf("OP_HASH\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
|
||||
print_lv(mrb, irep, c, RAB);
|
||||
CASE(OP_HASH, BB):
|
||||
printf("OP_HASH\tR%d\t%d\t", a, b);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_HASHADD, BB):
|
||||
printf("OP_HASHADD\tR%d\t%d", a, b);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
|
||||
case OP_OCLASS:
|
||||
printf("OP_OCLASS\tR%d\t\t", GETARG_A(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_OCLASS, B):
|
||||
printf("OP_OCLASS\tR%d\t\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_CLASS:
|
||||
printf("OP_CLASS\tR%d\t:%s", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_CLASS, BB):
|
||||
printf("OP_CLASS\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_MODULE:
|
||||
printf("OP_MODULE\tR%d\t:%s", GETARG_A(c),
|
||||
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_MODULE, BB):
|
||||
printf("OP_MODULE\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_EXEC:
|
||||
printf("OP_EXEC\tR%d\tI(%+d)", GETARG_A(c), GETARG_Bx(c)+1);
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_EXEC, BB):
|
||||
printf("OP_EXEC\tR%d\tI(%d:%p)", a, b, irep->reps[b]);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_SCLASS:
|
||||
printf("OP_SCLASS\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
|
||||
print_lv(mrb, irep, c, RAB);
|
||||
CASE(OP_SCLASS, B):
|
||||
printf("OP_SCLASS\tR%d\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_TCLASS:
|
||||
printf("OP_TCLASS\tR%d\t\t", GETARG_A(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_TCLASS, B):
|
||||
printf("OP_TCLASS\tR%d\t\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
case OP_ERR:
|
||||
CASE(OP_ERR, B):
|
||||
{
|
||||
mrb_value v = irep->pool[GETARG_Bx(c)];
|
||||
mrb_value v = irep->pool[a];
|
||||
mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
|
||||
printf("OP_ERR\t%s\n", RSTRING_PTR(s));
|
||||
}
|
||||
break;
|
||||
case OP_EPUSH:
|
||||
printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)+1);
|
||||
CASE(OP_EPUSH, B):
|
||||
printf("OP_EPUSH\t\t:I(%d:%p)\n", a, irep->reps[a]);
|
||||
break;
|
||||
case OP_ONERR:
|
||||
printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c));
|
||||
CASE(OP_ONERR, S):
|
||||
printf("OP_ONERR\t%03d\n", a);
|
||||
break;
|
||||
CASE(OP_EXCEPT, B):
|
||||
printf("OP_EXCEPT\tR%d\t\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_RESCUE, BB):
|
||||
printf("OP_RESCUE\tR%d\tR%d", a, b);
|
||||
print_lv_ab(mrb, irep, a, b);
|
||||
break;
|
||||
CASE(OP_RAISE, B):
|
||||
printf("OP_RAISE\tR%d\t\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_POPERR, B):
|
||||
printf("OP_POPERR\t%d\t\t\n", a);
|
||||
break;
|
||||
CASE(OP_EPOP, B):
|
||||
printf("OP_EPOP\t%d\n", a);
|
||||
break;
|
||||
case OP_RESCUE:
|
||||
{
|
||||
int a = GETARG_A(c);
|
||||
int b = GETARG_B(c);
|
||||
int cnt = GETARG_C(c);
|
||||
|
||||
if (b == 0) {
|
||||
printf("OP_RESCUE\tR%d\t\t%s", a, cnt ? "cont" : "");
|
||||
print_lv(mrb, irep, c, RA);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
printf("OP_RESCUE\tR%d\tR%d\t%s", a, b, cnt ? "cont" : "");
|
||||
print_lv(mrb, irep, c, RAB);
|
||||
break;
|
||||
}
|
||||
CASE(OP_DEBUG, BBB):
|
||||
printf("OP_DEBUG\t%d\t%d\t%d\n", a, b, c);
|
||||
break;
|
||||
|
||||
CASE(OP_STOP, Z):
|
||||
printf("OP_STOP\n");
|
||||
break;
|
||||
|
||||
CASE(OP_EXT1, Z):
|
||||
ins = READ_B();
|
||||
printf("OP_EXT1\n");
|
||||
print_header(irep, pc-irep->iseq-2);
|
||||
switch (ins) {
|
||||
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); goto L_OP_ ## i;
|
||||
#include "mruby/ops.h"
|
||||
#undef OPCODE
|
||||
}
|
||||
break;
|
||||
case OP_RAISE:
|
||||
printf("OP_RAISE\tR%d\t\t", GETARG_A(c));
|
||||
print_lv(mrb, irep, c, RA);
|
||||
CASE(OP_EXT2, Z):
|
||||
ins = READ_B();
|
||||
printf("OP_EXT2\n");
|
||||
print_header(irep, pc-irep->iseq-2);
|
||||
switch (ins) {
|
||||
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); goto L_OP_ ## i;
|
||||
#include "mruby/ops.h"
|
||||
#undef OPCODE
|
||||
}
|
||||
break;
|
||||
case OP_POPERR:
|
||||
printf("OP_POPERR\t%d\t\t\n", GETARG_A(c));
|
||||
CASE(OP_EXT3, Z):
|
||||
ins = READ_B();
|
||||
printf("OP_EXT3\n");
|
||||
print_header(irep, pc-irep->iseq-2);
|
||||
switch (ins) {
|
||||
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); goto L_OP_ ## i;
|
||||
#include "mruby/ops.h"
|
||||
#undef OPCODE
|
||||
}
|
||||
break;
|
||||
case OP_EPOP:
|
||||
printf("OP_EPOP\t%d\n", GETARG_A(c));
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
printf("OP_unknown %d\t%d\t%d\t%d\n", GET_OPCODE(c),
|
||||
GETARG_A(c), GETARG_B(c), GETARG_C(c));
|
||||
printf("OP_unknown (0x%x)\n", ins);
|
||||
break;
|
||||
}
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
|
||||
+1
-1
@@ -1266,5 +1266,5 @@ mrb_init_kernel(mrb_state *mrb)
|
||||
mrb_define_method(mrb, krn, "class_defined?", mrb_krn_class_defined, MRB_ARGS_REQ(1));
|
||||
|
||||
mrb_include_module(mrb, mrb->object_class, mrb->kernel_module);
|
||||
mrb_alias_method(mrb, mrb->module_class, mrb_intern_lit(mrb, "dup"), mrb_intern_lit(mrb, "clone"));
|
||||
mrb_define_alias(mrb, mrb->module_class, "dup", "clone"); /* XXX */
|
||||
}
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
|
||||
if ((flags & FLAG_SRC_MALLOC) == 0 &&
|
||||
(flags & FLAG_BYTEORDER_NATIVE)) {
|
||||
irep->iseq = (mrb_code*)src;
|
||||
src += sizeof(uint32_t) * irep->ilen;
|
||||
src += sizeof(mrb_code) * irep->ilen;
|
||||
irep->flags |= MRB_ISEQ_NO_FREE;
|
||||
}
|
||||
else {
|
||||
|
||||
+5
-5
@@ -10,7 +10,7 @@
|
||||
#include <mruby/opcode.h>
|
||||
|
||||
static mrb_code call_iseq[] = {
|
||||
MKOP_A(OP_CALL, 0),
|
||||
OP_CALL,
|
||||
};
|
||||
|
||||
struct RProc*
|
||||
@@ -223,7 +223,7 @@ mrb_proc_arity(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct RProc *p = mrb_proc_ptr(self);
|
||||
struct mrb_irep *irep;
|
||||
mrb_code *iseq;
|
||||
mrb_code *pc;
|
||||
mrb_aspec aspec;
|
||||
int ma, op, ra, pa, arity;
|
||||
|
||||
@@ -237,13 +237,13 @@ mrb_proc_arity(mrb_state *mrb, mrb_value self)
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
|
||||
iseq = irep->iseq;
|
||||
pc = irep->iseq;
|
||||
/* arity is depend on OP_ENTER */
|
||||
if (GET_OPCODE(*iseq) != OP_ENTER) {
|
||||
if (*pc != OP_ENTER) {
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
|
||||
aspec = GETARG_Ax(*iseq);
|
||||
aspec = PEEK_W(pc+1);
|
||||
ma = MRB_ASPEC_REQ(aspec);
|
||||
op = MRB_ASPEC_OPT(aspec);
|
||||
ra = MRB_ASPEC_REST(aspec);
|
||||
|
||||
Reference in New Issue
Block a user