diff options
Diffstat (limited to 'trunk/insns.def')
-rw-r--r-- | trunk/insns.def | 2035 |
1 files changed, 0 insertions, 2035 deletions
diff --git a/trunk/insns.def b/trunk/insns.def deleted file mode 100644 index a695630ea6..0000000000 --- a/trunk/insns.def +++ /dev/null @@ -1,2035 +0,0 @@ -/** ##skip -*- mode:c; style:ruby -*- - insns.def - YARV instruction definitions - - $Author: $ - created at: 04/01/01 01:17:55 JST - - Copyright (C) 2004-2007 Koichi Sasada -*/ - -/** ##skip - instruction comment - @c: category - @e: english description - @j: japanese description - - instruction form: - DEFINE_INSN - instrunction_name - (instruction_operands, ..) - (pop_values, ..) - (return value) - { - .. // insn body - } - - */ - - -/** - @c nop - @e nop - @j nop - */ -DEFINE_INSN -nop -() -() -() -{ - /* none */ -} - -/**********************************************************/ -/* deal with variables */ -/**********************************************************/ - -/** - @c variable - @e get local variable value (which is pointed by idx). - @j idx で指定されたローカル変数をスタックに置く。 - */ -DEFINE_INSN -getlocal -(lindex_t idx) -() -(VALUE val) -{ - val = *(GET_LFP() - idx); -} - -/** - @c variable - @e set local variable value (which is pointed by idx) as val. - @j idx で指定されたローカル変数を val に設定する。 - */ -DEFINE_INSN -setlocal -(lindex_t idx) -(VALUE val) -() -{ - (*(GET_LFP() - idx)) = val; -} - -/** - @c variable - @e get special local variable ($~, $_, ..) value. - @j 特殊なローカル変数($~, $_, ...)の値を得る。 - */ -DEFINE_INSN -getspecial -(VALUE key, rb_num_t type) -() -(VALUE val) -{ - val = vm_getspecial(th, GET_LFP(), key, type); -} - -/** - @c variable - @e set special local variable ($~, $_, ...) value as obj. - @j 特別なローカル変数($~, $_, ...)の値をを設定する。 - */ -DEFINE_INSN -setspecial -(VALUE key) -(VALUE obj) -() -{ - lfp_svar_set(th, GET_LFP(), key, obj); -} - -/** - @c variable - @e get block local variable(which is pointed by idx and level). - level means nest level of block, and specify how above this variable. - @j level, idx で指定されたブロックローカル変数の値をスタックに置く。 - level はブロックのネストレベルで、何段上かを示す。 - */ -DEFINE_INSN -getdynamic -(dindex_t idx, rb_num_t level) -() -(VALUE val) -{ - int i; - VALUE *dfp2 = GET_DFP(); - for (i = 0; i < level; i++) { - dfp2 = GET_PREV_DFP(dfp2); - } - val = *(dfp2 - idx); -} - -/** - @c variable - @e set block local variable(which is pointed by 'idx') as val. - level means nest level of block, and specify how above this variable. - @j level, idx で指定されたブロックローカル変数の値を val にする。 - level はブロックのネストレベルで、何段上かを示す。 - */ -DEFINE_INSN -setdynamic -(dindex_t idx, rb_num_t level) -(VALUE val) -() -{ - int i; - VALUE *dfp2 = GET_DFP(); - for (i = 0; i < level; i++) { - dfp2 = GET_PREV_DFP(dfp2); - } - *(dfp2 - idx) = val; -} - -/** - @c variable - @e get instance variable id of obj. - if is_local is not 0, search as class local variable. - @j self のインスタンス変数 id の値を得る。 - */ -DEFINE_INSN -getinstancevariable -(ID id) -() -(VALUE val) -{ - val = rb_ivar_get(GET_SELF(), id); -} - -/** - @c variable - @e set instance variable id of obj as val. - if is_local is not 0, search as class local variable. - @j self のインスタンス変数 id を val にする。 - */ -DEFINE_INSN -setinstancevariable -(ID id) -(VALUE val) -() -{ - rb_ivar_set(GET_SELF(), id, val); -} - -/** - @c variable - @e get class variable id of klass as val. - @j 現在のスコープのクラス変数 id の値を得る。 - */ -DEFINE_INSN -getclassvariable -(ID id) -() -(VALUE val) -{ - NODE * const cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP()); - val = rb_cvar_get(vm_get_cvar_base(cref), id); -} - -/** - @c variable - @e set class variable id of klass as val. - @j klass のクラス変数 id を val にする。 - */ -DEFINE_INSN -setclassvariable -(ID id) -(VALUE val) -() -{ - NODE * const cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP()); - rb_cvar_set(vm_get_cvar_base(cref), id, val); -} - -/** - @c variable - @e - get constant variable id. if klass is Qnil, constant - are searched in current scope. if klass is Qfalse, constant as - top level constant. otherwise, get constant under klass - class or module. - @j 定数 id の値を得る。 - klass が Qnil なら、そのスコープで得られる定数の値を得る。 - Qfalse なら、トップレベルスコープを得る。 - それ以外なら、klass クラスの下の定数を得る。 - */ -DEFINE_INSN -getconstant -(ID id) -(VALUE klass) -(VALUE val) -{ - val = vm_get_ev_const(th, GET_ISEQ(), klass, id, 0); -} - -/** - @c variable - @e - set constant variable id. if klass is Qfalse, constant - is able to access in this scope. if klass is Qnil, set - top level constant. otherwise, set constant under klass - class or module. - - @j 定数 id の値を val にする。 - klass が Qfalse なら、そのスコープで得られる定数 id の値を設定する。 - Qnil なら、トップレベルスコープの値を設定する。 - それ以外なら、klass クラスの下の定数を設定する。 - */ -DEFINE_INSN -setconstant -(ID id) -(VALUE val, VALUE cbase) -() -{ - vm_check_if_namespace(cbase); - rb_const_set(cbase, id, val); - INC_VM_STATE_VERSION(); -} - -/** - @c variable - @e get global variable id. - @j グローバル変数 id の値を得る。 - */ -DEFINE_INSN -getglobal -(GENTRY entry) -() -(VALUE val) -{ - val = GET_GLOBAL(entry); -} - -/** - @c variable - @e set global variable id as val. - @j グローバル変数 id の値を設定する。 - */ -DEFINE_INSN -setglobal -(GENTRY entry) -(VALUE val) -() -{ - SET_GLOBAL(entry, val); -} - - -/**********************************************************/ -/* deal with values */ -/**********************************************************/ - -/** - @c put - @e put nil to stack. - @j スタックに nil をプッシュする。 - */ -DEFINE_INSN -putnil -() -() -(VALUE val) -{ - val = Qnil; -} - -/** - @c put - @e put self. - @j スタックに self をプッシュする。 - */ -DEFINE_INSN -putself -() -() -(VALUE val) -{ - val = GET_SELF(); -} - -/** - @c put - @e put some object. - i.e. Fixnum, true, false, nil, and so on. - @j オブジェクト val をスタックにプッシュする。 - i.e. Fixnum, true, false, nil, and so on. - */ -DEFINE_INSN -putobject -(VALUE val) -() -(VALUE val) -{ - /* */ -} - -/** - @c put - @e put special object. "value_type" is for expansion. - @j 特別なオブジェクト val をスタックにプッシュする。 - オブジェクトの種類は value_type による. - */ -DEFINE_INSN -putspecialobject -(rb_num_t value_type) -() -(VALUE val) -{ - switch (value_type) { - case VM_SPECIAL_OBJECT_VMCORE: - val = rb_mRubyVMFrozenCore; - break; - case VM_SPECIAL_OBJECT_CBASE: - val = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP()); - break; - default: - rb_bug("putspecialobject insn: unknown value_type"); - } -} - -/** - @c put - @e put iseq value. - @j put iseq value. - */ -DEFINE_INSN -putiseq -(ISEQ iseq) -() -(VALUE ret) -{ - ret = iseq->self; -} - -/** - @c put - @e put string val. string will be copied. - @j 文字列ををコピーしてスタックにプッシュする。 - */ -DEFINE_INSN -putstring -(VALUE str) -() -(VALUE val) -{ - val = rb_str_new3(str); -} - -/** - @c put - @e put concatenate strings - @j スタックトップの文字列を n 個連結し,結果をスタックにプッシュする。 - */ -DEFINE_INSN -concatstrings -(rb_num_t num) -(...) -(VALUE val) // inc += 1 - num; -{ - int i; - - val = rb_str_new(0, 0); - for (i = num - 1; i >= 0; i--) { - const VALUE v = TOPN(i); - rb_str_append(val, v); - } - POPN(num); -} - -/** - @c put - @e to_str - @j to_str の結果をスタックにプッシュする。 - */ -DEFINE_INSN -tostring -() -(VALUE val) -(VALUE val) -{ - val = rb_obj_as_string(val); -} - -/** - @c put - @e to Regexp - @j 文字列 str を正規表現にコンパイルしてスタックにプッシュする。 - コンパイル時,opt を正規表現のオプションとする。 - */ -DEFINE_INSN -toregexp -(rb_num_t opt, rb_num_t cnt) -(...) -(VALUE val) // inc += 1 - cnt; -{ - VALUE rb_reg_new_ary(VALUE ary, int options); - int i; - const VALUE ary = rb_ary_new2(cnt); - RBASIC(ary)->klass = 0; - for (i = 0; i < cnt; i++) { - rb_ary_store(ary, cnt-i-1, TOPN(i)); - } - POPN(cnt); - val = rb_reg_new_ary(ary, opt); -} - -/** - @c put - @e put new array. - @j 新しい配列をスタック上の num 個の値で初期化して生成しプッシュする。 - */ -DEFINE_INSN -newarray -(rb_num_t num) -(...) -(VALUE val) // inc += 1 - num; -{ - val = rb_ary_new4((long)num, STACK_ADDR_FROM_TOP(num)); - POPN(num); -} - -/** - @c put - @e dup array - @j 配列 ary を dup してスタックにプッシュする。 - */ -DEFINE_INSN -duparray -(VALUE ary) -() -(VALUE val) -{ - val = rb_ary_dup(ary); -} - -/** - @c put - @e expand array to num objects. - @j スタックトップのオブジェクトが配列であれば、それを展開する。 - 配列オブジェクトの要素数が num以下ならば、代わりに nil を積む。num以上なら、 - num以上の要素は切り捨てる。 - 配列オブジェクトでなければ、num - 1 個の nil を積む。 - もし flag が真なら、残り要素の配列を積む - flag: 0x01 - 最後を配列に - flag: 0x02 - postarg 用 - flag: 0x04 - reverse? - */ -DEFINE_INSN -expandarray -(rb_num_t num, rb_num_t flag) -(..., VALUE ary) -(...) // inc += num - 1 + (flag & 1 ? 1 : 0); -{ - vm_expandarray(GET_CFP(), ary, num, flag); -} - -/** - @c put - @e concat two arrays - @j 二つの配列 ary1, ary2 を連結しスタックへプッシュする。 - */ -DEFINE_INSN -concatarray -() -(VALUE ary1, VALUE ary2st) -(VALUE ary) -{ - const VALUE ary2 = ary2st; - VALUE tmp1 = rb_check_convert_type(ary1, T_ARRAY, "Array", "to_a"); - VALUE tmp2 = rb_check_convert_type(ary2, T_ARRAY, "Array", "to_a"); - - if (NIL_P(tmp1)) { - tmp1 = rb_ary_new3(1, ary1); - } - - if (NIL_P(tmp2)) { - tmp2 = rb_ary_new3(1, ary2); - } - - if (tmp1 == ary1) { - tmp1 = rb_ary_dup(ary1); - } - ary = rb_ary_concat(tmp1, tmp2); -} - -/** - @c put - @e splat array - @j 配列 ary に対して to_a を呼び出す。 - */ -DEFINE_INSN -splatarray -(VALUE flag) -(VALUE ary) -(VALUE obj) -{ - VALUE tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a"); - if (NIL_P(tmp)) { - tmp = rb_ary_new3(1, ary); - } - obj = tmp; -} - -/** - @c put - @e check value is included in ary - @j 配列 ary に要素 obj が入っているかどうかチェック。case/when で利用する。 - */ -DEFINE_INSN -checkincludearray -(VALUE flag) -(VALUE obj, VALUE ary) -(VALUE obj, VALUE result) -{ - int i; - result = Qfalse; - - if (TYPE(ary) != T_ARRAY) { - ary = rb_Array(ary); - } - - if (flag == Qtrue) { - /* NODE_CASE */ - for (i = 0; i < RARRAY_LEN(ary); i++) { - /* TODO: fix me (use another method dispatch) */ - if (RTEST(rb_funcall2(RARRAY_PTR(ary)[i], idEqq, 1, &obj))) { - result = Qtrue; - break; - } - } - } - else { - obj = Qfalse; - /* NODE_WHEN */ - for (i = 0; i < RARRAY_LEN(ary); i++) { - if (RTEST(RARRAY_PTR(ary)[i])) { - obj = result = Qtrue; - break; - } - } - } -} - -/** - @c put - @e put new Hash. - @j 新しいハッシュをスタックトップの n 個を初期値として生成する。 - n はキーと値のペアなので 2 の倍数でなければならない。 - */ -DEFINE_INSN -newhash -(rb_num_t num) -(...) -(VALUE val) // inc += 1 - num; -{ - int i; - val = rb_hash_new(); - - for (i = num; i > 0; i -= 2) { - const VALUE v = TOPN(i - 2); - const VALUE k = TOPN(i - 1); - rb_hash_aset(val, k, v); - } - POPN(num); -} - -/** - @c put - @e put new Range object.(Range.new(low, high, flag)) - @j Range.new(low, high, flag) のようなオブジェクトを生成しスタックにプッシュする。 - */ -DEFINE_INSN -newrange -(rb_num_t flag) -(VALUE low, VALUE high) -(VALUE val) -{ - val = rb_range_new(low, high, flag); -} - -/**********************************************************/ -/* deal with stack operation */ -/**********************************************************/ - -/** - @c stack - @e pop from stack. - @j スタックから一つポップする。 - */ -DEFINE_INSN -pop -() -(VALUE val) -() -{ - val = val; - /* none */ -} - -/** - @c stack - @e duplicate stack top. - @j スタックトップをコピーしてスタックにプッシュする。 - */ -DEFINE_INSN -dup -() -(VALUE val) -(VALUE val1, VALUE val2) -{ - val1 = val2 = val; -} - -/** - @c stack - @e duplicate stack top n elements - @j スタックトップの n 個をコピーしてスタックにプッシュする。 - */ -DEFINE_INSN -dupn -(rb_num_t n) -(...) -(...) // inc += n; -{ - int i; - VALUE *sp = STACK_ADDR_FROM_TOP(n); - for (i = 0; i < n; i++) { - GET_SP()[i] = sp[i]; - } - INC_SP(n); -} - - -/** - @c stack - @e swap top 2 vals - @j スタックトップの 2 つの値を交換する。 - */ -DEFINE_INSN -swap -() -(VALUE val, VALUE obj) -(VALUE obj, VALUE val) -{ - /* none */ -} - -/** - @c stack - @e for stack caching. - @j スタックキャッシングの状態を調整するために必要な命令。 - */ -DEFINE_INSN -reput -() -(..., VALUE val) -(VALUE val) // inc += 0; -{ - /* none */ -} - -/** - @c stack - @e get nth stack value from stack top - @j スタックトップから n 個目をスタックにプッシュする。 - */ -DEFINE_INSN -topn -(rb_num_t n) -(...) -(VALUE val) // inc += 1; -{ - val = TOPN(n); -} - -/** - @c stack - @e set Nth stack entry to stack top - @j スタックトップの値を n 個目のスタックにコピー - */ -DEFINE_INSN -setn -(rb_num_t n) -(..., VALUE val) -(VALUE val) // inc += 0 -{ - TOPN(n-1) = val; -} - -/** - @c stack - @e empt current stack - @j current stack を空にする。 - */ -DEFINE_INSN -adjuststack -(rb_num_t n) -(...) -(...) // inc -= n -{ - DEC_SP(n); -} - - -/**********************************************************/ -/* deal with setting */ -/**********************************************************/ - -/** - @c setting - @e defined? - @j defined? を行う。 - */ -DEFINE_INSN -defined -(rb_num_t type, VALUE obj, VALUE needstr) -(VALUE v) -(VALUE val) -{ - VALUE klass; - const char *expr_type = 0; - val = Qnil; - - switch (type) { - case DEFINED_IVAR: - if (rb_ivar_defined(GET_SELF(), SYM2ID(obj))) { - expr_type = "instance-variable"; - } - break; - case DEFINED_IVAR2: - klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP()); - break; - case DEFINED_GVAR: - if (rb_gvar_defined((struct global_entry *)(obj & ~1))) { - expr_type = "global-variable"; - } - break; - case DEFINED_CVAR: - klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP()); - if (rb_cvar_defined(klass, SYM2ID(obj))) { - expr_type = "class variable"; - } - break; - case DEFINED_CONST: - klass = v; - if (vm_get_ev_const(th, GET_ISEQ(), klass, SYM2ID(obj), 1)) { - expr_type = "constant"; - } - break; - case DEFINED_FUNC: - klass = CLASS_OF(v); - if (rb_method_boundp(klass, SYM2ID(obj), 0)) { - expr_type = "method"; - } - break; - case DEFINED_METHOD:{ - VALUE klass = CLASS_OF(v); - NODE *method = (NODE *) rb_method_node(klass, SYM2ID(obj)); - - if (method) { - if (!(method->nd_noex & NOEX_PRIVATE)) { - if (!((method->nd_noex & NOEX_PROTECTED) && - !rb_obj_is_kind_of(GET_SELF(), - rb_class_real(klass)))) { - expr_type = "method"; - } - } - } - break; - } - case DEFINED_YIELD: - if (GET_BLOCK_PTR()) { - expr_type = "yield"; - } - break; - case DEFINED_ZSUPER:{ - rb_iseq_t *ip = GET_ISEQ(); - while (ip) { - if (ip->defined_method_id) { - break; - } - ip = ip->parent_iseq; - } - if (ip) { - VALUE klass = vm_search_normal_superclass(ip->klass, GET_SELF()); - if (rb_method_boundp(klass, ip->defined_method_id, 0)) { - expr_type = "super"; - } - } - break; - } - case DEFINED_REF:{ - val = vm_getspecial(th, GET_LFP(), Qfalse, FIX2INT(obj)); - if (val != Qnil) { - expr_type = "global-variable"; - } - break; - } - default: - rb_bug("unimplemented defined? type (VM)"); - break; - } - if (expr_type != 0) { - if (needstr != Qfalse) { - val = rb_str_new2(expr_type); - } - else { - val = Qtrue; - } - } -} - -/** - @c setting - @e trace - @j trace 用の命令。 - */ -DEFINE_INSN -trace -(rb_num_t nf) -() -() -{ - rb_event_flag_t flag = nf; - - EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* TODO: id, klass */); -} - -/**********************************************************/ -/* deal with control flow 1: class/module */ -/**********************************************************/ - -/** - @c class/module - @e - enter class definition scope. if super is Qfalse, and clsas - "klass" is defined, it's redefine. otherwise, define "klass" class. - @j クラス定義スコープへ移行する。 - もし super が Qfalse で klassクラスが定義されていれば再定義である。 - そうでなければ、klass クラスを定義する。 - */ -DEFINE_INSN -defineclass -(ID id, ISEQ class_iseq, rb_num_t define_type) -(VALUE cbase, VALUE super) -(VALUE val) -{ - VALUE klass; - - switch ((int)define_type) { - case 0: - /* val is dummy. classdef returns class scope value */ - - if (super == Qnil) { - super = rb_cObject; - } - - vm_check_if_namespace(cbase); - - /* find klass */ - if (rb_const_defined_at(cbase, id)) { - /* already exist */ - klass = rb_const_get_at(cbase, id); - if (TYPE(klass) != T_CLASS) { - rb_raise(rb_eTypeError, "%s is not a class", rb_id2name(id)); - } - - if (super != rb_cObject) { - VALUE tmp; - tmp = rb_class_real(RCLASS_SUPER(klass)); - - if (tmp != super) { - rb_raise(rb_eTypeError, "superclass mismatch for class %s", - rb_id2name(id)); - } - } - } - else { - /* new class declaration */ - klass = rb_define_class_id(id, super); - rb_set_class_path(klass, cbase, rb_id2name(id)); - rb_const_set(cbase, id, klass); - rb_class_inherited(super, klass); - } - break; - case 1: - /* val is dummy. classdef returns class scope value */ - /* super is dummy */ - klass = rb_singleton_class(cbase); - break; - case 2: - /* val is dummy. classdef returns class scope value */ - /* super is dummy */ - - vm_check_if_namespace(cbase); - - /* find klass */ - if (rb_const_defined_at(cbase, id)) { - klass = rb_const_get_at(cbase, id); - /* already exist */ - if (TYPE(klass) != T_MODULE) { - rb_raise(rb_eTypeError, "%s is not a module", rb_id2name(id)); - } - } - else { - /* new module declaration */ - klass = rb_define_module_id(id); - rb_set_class_path(klass, cbase, rb_id2name(id)); - rb_const_set(cbase, id, klass); - } - break; - default: - rb_bug("unknown defineclass type: %d", (int)define_type); - } - - COPY_CREF(class_iseq->cref_stack, vm_cref_push(th, klass, NOEX_PUBLIC)); - - /* enter scope */ - vm_push_frame(th, class_iseq, - VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02, - class_iseq->iseq_encoded, GET_SP(), 0, - class_iseq->local_size); - RESTORE_REGS(); - - INC_VM_STATE_VERSION(); - NEXT_INSN(); -} - - -/**********************************************************/ -/* deal with control flow 2: method/iterator */ -/**********************************************************/ - -/** - @c method/iterator - @e obj.send(id, args..) # args.size => num - @j メソッド呼び出しを行う。 - obj.send(id, args..) # args.size => num - flag & VM_CALL_ARGS_SPLAT_BIT != 0 -> splat last arg - flag & VM_CALL_ARGS_BLOCKARG_BIT != 0 -> Proc as Block - flag & VM_CALL_FCALL_BIT != 0 -> FCALL ( func() ) - flag & VM_CALL_VCALL_BIT != 0 -> VCALL ( func ) - ... - */ -DEFINE_INSN -send -(ID op_id, rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag, IC ic) -(...) -(VALUE val) // inc += - (op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0)); -{ - NODE *mn; - VALUE recv, klass; - rb_block_t *blockptr = 0; - rb_num_t num = caller_setup_args(th, GET_CFP(), op_flag, op_argc, - (rb_iseq_t *)blockiseq, &blockptr); - rb_num_t flag = op_flag; - ID id = op_id; - - /* get receiver */ - recv = (flag & VM_CALL_FCALL_BIT) ? GET_SELF() : TOPN(num); - klass = CLASS_OF(recv); - mn = vm_method_search(id, klass, ic); - - /* send/funcall optimization */ - if (flag & VM_CALL_SEND_BIT) { - vm_send_optimize(GET_CFP(), &mn, &flag, &num, &id, klass); - } - - CALL_METHOD(num, blockptr, flag, id, mn, recv, klass); -} - -/** - @c method/iterator - @e super(args) # args.size => num - @j super を実行する。 - super(args) # args.size => num - flag 等オペランドの意味は send と同じ。 - */ -DEFINE_INSN -invokesuper -(rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag) -(...) -(VALUE val) // inc += - (op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0)); -{ - rb_block_t *blockptr = !(op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? GET_BLOCK_PTR() : 0; - int num = caller_setup_args(th, GET_CFP(), op_flag, op_argc, blockiseq, &blockptr); - VALUE recv, klass; - NODE *mn; - ID id; - const VALUE flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT; - - recv = GET_SELF(); - vm_search_superclass(GET_CFP(), GET_ISEQ(), recv, TOPN(num), &id, &klass); - mn = rb_method_node(klass, id); - - CALL_METHOD(num, blockptr, flag, id, mn, recv, klass); -} - -/** - @c method/iterator - @e yield(args) # args.size => num, flag shows expand argument or not - @j yield を実行する。 - yield(args) # args.size => num - */ -DEFINE_INSN -invokeblock -(rb_num_t num, rb_num_t flag) -(...) -(VALUE val) // inc += 1 - num; -{ - val = vm_invoke_block(th, GET_CFP(), num, flag); - if (val == Qundef) { - RESTORE_REGS(); - NEXT_INSN(); - } -} - -/** - @c method/iterator - @e return from this scope. - @j このスコープから抜ける。 - */ -DEFINE_INSN -leave -() -(VALUE val) -(VALUE val) -{ - if (OPT_CHECKED_RUN) { - if (reg_cfp->sp != reg_cfp->bp) { - rb_bug("Stack consistency error (sp: %"PRIdPTRDIFF", bp: %"PRIdPTRDIFF")", - VM_SP_CNT(th, reg_cfp->sp), VM_SP_CNT(th, reg_cfp->bp)); - } - } - - RUBY_VM_CHECK_INTS(); - vm_pop_frame(th); - RESTORE_REGS(); -} - -/** - @c method/iterator - @e return from this vm loop - @j VM loop から抜ける。 - */ -DEFINE_INSN -finish -() -(VALUE val) -(VALUE val) -{ -#if OPT_CALL_THREADED_CODE - rb_bug("unused instruction on OPT_CALL_THREADED_CODE"); -#else - th->cfp++; - return val; -#endif -} - -/**********************************************************/ -/* deal with control flow 3: exception */ -/**********************************************************/ - -/** - @c exception - @e longjump - @j 大域ジャンプを行う。 - */ -DEFINE_INSN -throw -(rb_num_t throw_state) -(VALUE throwobj) -(VALUE val) -{ - RUBY_VM_CHECK_INTS(); - val = vm_throw(th, GET_CFP(), throw_state, throwobj); - THROW_EXCEPTION(val); - /* unreachable */ -} - -/**********************************************************/ -/* deal with control flow 4: local jump */ -/**********************************************************/ - -/** - @c jump - @e set PC to (PC + dst). - @j PC を (PC + dst) にする。 - */ -DEFINE_INSN -jump -(OFFSET dst) -() -() -{ - RUBY_VM_CHECK_INTS(); - JUMP(dst); -} - -/** - @c jump - @e if val is not false or nil, set PC to (PC + dst). - @j もし val が false か nil でなければ、PC を (PC + dst) にする。 - */ -DEFINE_INSN -branchif -(OFFSET dst) -(VALUE val) -() -{ - if (RTEST(val)) { - RUBY_VM_CHECK_INTS(); - JUMP(dst); - } -} - -/** - @c jump - @e if val is false or nil, set PC to (PC + dst). - @j もし val が false か nil ならば、PC を (PC + dst) にする。 - */ -DEFINE_INSN -branchunless -(OFFSET dst) -(VALUE val) -() -{ - if (!RTEST(val)) { - RUBY_VM_CHECK_INTS(); - JUMP(dst); - } -} - - -/**********************************************************/ -/* for optimize */ -/**********************************************************/ - -/** - @c optimize - @e inline cache - @j インラインキャッシュが有効なら、値をスタックにプッシュして dst へジャンプする。 - */ -DEFINE_INSN -getinlinecache -(IC ic, OFFSET dst) -() -(VALUE val) -{ - if (ic->ic_vmstat == GET_VM_STATE_VERSION()) { - val = ic->ic_value; - JUMP(dst); - } - else { - /* none */ - val = Qnil; - } -} - -/** - @c optimize - @e inline cache (once) - @j once を実現する。 - */ -DEFINE_INSN -onceinlinecache -(IC ic, OFFSET dst) -() -(VALUE val) -{ - if (ic->ic_vmstat) { - val = ic->ic_value; - JUMP(dst); - } - else { - /* none */ - val = Qnil; - } -} - -/** - @c optimize - @e set inline cache - @j インラインキャッシュの値を設定する。 - */ -DEFINE_INSN -setinlinecache -(OFFSET dst) -(VALUE val) -(VALUE val) -{ - IC ic = GET_CONST_INLINE_CACHE(dst); - - ic->ic_value = val; - ic->ic_vmstat = GET_VM_STATE_VERSION(); -} - -/** - @c optimize - @e case dispatcher - @j case 文で、可能なら表引きでジャンプする。 - */ -DEFINE_INSN -opt_case_dispatch -(CDHASH hash, OFFSET else_offset) -(..., VALUE key) -() // inc += -1; -{ - if (0) { - /* TODO: if some === method is overrided */ - } - else { - VALUE val; - if (st_lookup(RHASH_TBL(hash), key, &val)) { - JUMP(FIX2INT(val)); - } - else { - JUMP(else_offset); - } - } -} - -/** - @c optimize - @e check environment - @j 将来の拡張用。 - */ -DEFINE_INSN -opt_checkenv -() -() -() -{ - if (GET_CFP()->bp != GET_DFP() + 1) { - VALUE *new_dfp = GET_CFP()->bp - 1; - /* TODO: copy env and clean stack at creating env? */ - *new_dfp = *GET_DFP(); - SET_DFP(new_dfp); - } -} - - -/** simple functions */ - -/** - @c optimize - @e optimized X+Y. - @j 最適化された X+Y。 - */ -DEFINE_INSN -opt_plus -() -(VALUE recv, VALUE obj) -(VALUE val) -{ - if (0) { - - } -#if 1 - else if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { - /* fixnum + fixnum */ -#ifndef LONG_LONG_VALUE - val = (recv + (obj & (~1))); - if ((~(recv ^ obj) & (recv ^ val)) & - ((VALUE)0x01 << ((sizeof(VALUE) * CHAR_BIT) - 1))) { - val = rb_big_plus(rb_int2big(FIX2LONG(recv)), - rb_int2big(FIX2LONG(obj))); - } -#else - long a, b, c; - a = FIX2LONG(recv); - b = FIX2LONG(obj); - c = a + b; - if (FIXABLE(c)) { - val = LONG2FIX(c); - } - else { - val = rb_big_plus(rb_int2big(a), rb_int2big(b)); - } -#endif - } -#endif - - else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { - if (0) { - } -#if 1 - else if (HEAP_CLASS_OF(recv) == rb_cFloat && - HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { - val = DOUBLE2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj)); - } -#endif - -#if 1 - else if (HEAP_CLASS_OF(recv) == rb_cString && - HEAP_CLASS_OF(obj) == rb_cString && - BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { - val = rb_str_plus(recv, obj); - } -#endif -#if 1 - else if (HEAP_CLASS_OF(recv) == rb_cArray && - BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { - val = rb_ary_plus(recv, obj); - } -#endif - else { - goto INSN_LABEL(normal_dispatch); - } - } - else { - INSN_LABEL(normal_dispatch): - PUSH(recv); - PUSH(obj); - CALL_SIMPLE_METHOD(1, idPLUS, recv); - } -} - -/** - @c optimize - @e optimized X-Y. - @j 最適化された X-Y。 - */ -DEFINE_INSN -opt_minus -() -(VALUE recv, VALUE obj) -(VALUE val) -{ - if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_MINUS)) { - long a, b, c; - - a = FIX2LONG(recv); - b = FIX2LONG(obj); - c = a - b; - - if (FIXABLE(c)) { - val = LONG2FIX(c); - } - else { - val = rb_big_minus(rb_int2big(a), rb_int2big(b)); - } - } - else { - /* other */ - PUSH(recv); - PUSH(obj); - CALL_SIMPLE_METHOD(1, idMINUS, recv); - } -} - -/** - @c optimize - @e optimized X*Y. - @j 最適化された X*Y。 - */ -DEFINE_INSN -opt_mult -() -(VALUE recv, VALUE obj) -(VALUE val) -{ - if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_MULT)) { - long a, b, c; - - a = FIX2LONG(recv); - if (a == 0) { - val = recv; - } - else { - b = FIX2LONG(obj); - c = a * b; - - if (FIXABLE(c) && c / a == b) { - val = LONG2FIX(c); - } - else { - val = rb_big_mul(rb_int2big(a), rb_int2big(b)); - } - } - } - else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { - if (0) { - } -#if 1 - else if (HEAP_CLASS_OF(recv) == rb_cFloat && - HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_MULT)) { - val = DOUBLE2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj)); - } -#endif - else { - goto INSN_LABEL(normal_dispatch); - } - } - else { - INSN_LABEL(normal_dispatch): - PUSH(recv); - PUSH(obj); - CALL_SIMPLE_METHOD(1, idMULT, recv); - } -} - -/** - @c optimize - @e optimized X/Y. - @j 最適化された X/Y。 - */ -DEFINE_INSN -opt_div -() -(VALUE recv, VALUE obj) -(VALUE val) -{ - if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_DIV)) { - long x, y, div; - - x = FIX2LONG(recv); - y = FIX2LONG(obj); - { - /* copied from numeric.c#fixdivmod */ - long mod; - if (y == 0) - goto INSN_LABEL(normal_dispatch); - if (y < 0) { - if (x < 0) - div = -x / -y; - else - div = -(x / -y); - } - else { - if (x < 0) - div = -(-x / y); - else - div = x / y; - } - mod = x - div * y; - if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) { - mod += y; - div -= 1; - } - } - val = LONG2NUM(div); - } - else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { - if (0) { - } -#if 1 - else if (HEAP_CLASS_OF(recv) == rb_cFloat && - HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_DIV)) { - val = DOUBLE2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj)); - } -#endif - else { - goto INSN_LABEL(normal_dispatch); - } - } - else { - INSN_LABEL(normal_dispatch): - PUSH(recv); - PUSH(obj); - CALL_SIMPLE_METHOD(1, idDIV, recv); - } -} - -/** - @c optimize - @e optimized X%Y. - @j 最適化された X%Y。 - */ -DEFINE_INSN -opt_mod -() -(VALUE recv, VALUE obj) -(VALUE val) -{ - if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_MOD)) { - long x, y, mod; - - x = FIX2LONG(recv); - y = FIX2LONG(obj); - { - /* copied from numeric.c#fixdivmod */ - long div; - - if (y == 0) - rb_num_zerodiv(); - if (y < 0) { - if (x < 0) - div = -x / -y; - else - div = -(x / -y); - } - else { - if (x < 0) - div = -(-x / y); - else - div = x / y; - } - mod = x - div * y; - if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) { - mod += y; - div -= 1; - } - } - val = LONG2FIX(mod); - } - else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { - if (0) { - } - else if (HEAP_CLASS_OF(recv) == rb_cFloat && - HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_MOD)) { - double x = RFLOAT_VALUE(recv); - double y = RFLOAT_VALUE(obj); - double div, mod; - - { - double z; - - modf(x / y, &z); - mod = x - z * y; - } - - div = (x - mod) / y; - if (y * mod < 0) { - mod += y; - div -= 1.0; - } - val = DOUBLE2NUM(mod); - } - else { - goto INSN_LABEL(normal_dispatch); - } - } - else { - INSN_LABEL(normal_dispatch): - PUSH(recv); - PUSH(obj); - CALL_SIMPLE_METHOD(1, idMOD, recv); - } -} - -/** - @c optimize - @e optimized X==Y. - @j 最適化された X==Y。 - */ -DEFINE_INSN -opt_eq -(IC ic) -(VALUE recv, VALUE obj) -(VALUE val) -{ - val = opt_eq_func(recv, obj, ic); - - if (val == Qundef) { - /* other */ - PUSH(recv); - PUSH(obj); - CALL_SIMPLE_METHOD(1, idEq, recv); - } -} - -/** - @c optimize - @e optimized X!=Y. - @j 最適化された X!=Y。 - */ -DEFINE_INSN -opt_neq -(IC ic1, IC ic2) -(VALUE recv, VALUE obj) -(VALUE val) -{ - extern VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2); - NODE *mn = vm_method_search(idNeq, CLASS_OF(recv), ic1); - val = Qundef; - - if (check_cfunc(mn, rb_obj_not_equal)) { - val = opt_eq_func(recv, obj, ic2); - - if (val != Qundef) { - val = RTEST(val) ? Qfalse : Qtrue; - } - } - - if (val == Qundef) { - /* other */ - PUSH(recv); - PUSH(obj); - CALL_SIMPLE_METHOD(1, idNeq, recv); - } -} - -/** - @c optimize - @e optimized X<Y. - @j 最適化された X<Y。 - */ -DEFINE_INSN -opt_lt -() -(VALUE recv, VALUE obj) -(VALUE val) -{ - if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_LT)) { - SIGNED_VALUE a = recv, b = obj; - - if (a < b) { - val = Qtrue; - } - else { - val = Qfalse; - } - } - else { - PUSH(recv); - PUSH(obj); - CALL_SIMPLE_METHOD(1, idLT, recv); - } -} - -/** - @c optimize - @e optimized X<=Y. - @j 最適化された X<=Y。 - */ -DEFINE_INSN -opt_le -() -(VALUE recv, VALUE obj) -(VALUE val) -{ - if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_LE)) { - SIGNED_VALUE a = recv, b = obj; - - if (a <= b) { - val = Qtrue; - } - else { - val = Qfalse; - } - } - else { - /* other */ - PUSH(recv); - PUSH(obj); - CALL_SIMPLE_METHOD(1, idLE, recv); - } -} - -/** - @c optimize - @e optimized X>Y. - @j 最適化された X>Y。 - */ -DEFINE_INSN -opt_gt -() -(VALUE recv, VALUE obj) -(VALUE val) -{ - if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_GT)) { - SIGNED_VALUE a = recv, b = obj; - - if (a > b) { - val = Qtrue; - } - else { - val = Qfalse; - } - } - else { - PUSH(recv); - PUSH(obj); - CALL_SIMPLE_METHOD(1, idGT, recv); - } -} - -/** - @c optimize - @e optimized X>=Y. - @j 最適化された X>=Y。 - */ -DEFINE_INSN -opt_ge -() -(VALUE recv, VALUE obj) -(VALUE val) -{ - if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_GE)) { - SIGNED_VALUE a = recv, b = obj; - - if (a >= b) { - val = Qtrue; - } - else { - val = Qfalse; - } - } - else { - PUSH(recv); - PUSH(obj); - CALL_SIMPLE_METHOD(1, idGE, recv); - } -} - -/** - @c optimize - @e << - @j 最適化された X<<Y。 - */ -DEFINE_INSN -opt_ltlt -() -(VALUE recv, VALUE obj) -(VALUE val) -{ - if (!SPECIAL_CONST_P(recv)) { - if (0) { - } - else if (HEAP_CLASS_OF(recv) == rb_cString && - BASIC_OP_UNREDEFINED_P(BOP_LTLT)) { - val = rb_str_concat(recv, obj); - } - else if (HEAP_CLASS_OF(recv) == rb_cArray && - BASIC_OP_UNREDEFINED_P(BOP_LTLT)) { - val = rb_ary_push(recv, obj); - } - else { - goto INSN_LABEL(normal_dispatch); - } - } - else { - INSN_LABEL(normal_dispatch): - PUSH(recv); - PUSH(obj); - CALL_SIMPLE_METHOD(1, idLTLT, recv); - } -} - -/** - @c optimize - @e [] - @j 最適化された recv[obj]。 - */ -DEFINE_INSN -opt_aref -() -(VALUE recv, VALUE obj) -(VALUE val) -{ - if (!SPECIAL_CONST_P(recv) && BASIC_OP_UNREDEFINED_P(BOP_AREF)) { - if (HEAP_CLASS_OF(recv) == rb_cArray && FIXNUM_P(obj)) { - val = rb_ary_entry(recv, FIX2LONG(obj)); - } - else if (HEAP_CLASS_OF(recv) == rb_cHash) { - val = rb_hash_aref(recv, obj); - } - else { - goto INSN_LABEL(normal_dispatch); - } - } - else { - INSN_LABEL(normal_dispatch): - PUSH(recv); - PUSH(obj); - CALL_SIMPLE_METHOD(1, idAREF, recv); - } -} - -/** - @c optimize - @e recv[obj] = set - @j 最適化された recv[obj] = set。 - */ -DEFINE_INSN -opt_aset -() -(VALUE recv, VALUE obj, VALUE set) -(VALUE val) -{ - if (!SPECIAL_CONST_P(recv) && - BASIC_OP_UNREDEFINED_P(BOP_ASET)) { - if (HEAP_CLASS_OF(recv) == rb_cArray && FIXNUM_P(obj)) { - rb_ary_store(recv, FIX2LONG(obj), set); - val = set; - } - else if (HEAP_CLASS_OF(recv) == rb_cHash) { - rb_hash_aset(recv, obj, set); - val = set; - } - else { - goto INSN_LABEL(normal_dispatch); - } - } - else { - INSN_LABEL(normal_dispatch): - PUSH(recv); - PUSH(obj); - PUSH(set); - CALL_SIMPLE_METHOD(2, idASET, recv); - } -} - -/** - @c optimize - @e optimized length - @j 最適化された recv.length()。 - */ -DEFINE_INSN -opt_length -() -(VALUE recv) -(VALUE val) -{ - if (!SPECIAL_CONST_P(recv) && - BASIC_OP_UNREDEFINED_P(BOP_LENGTH)) { - if (HEAP_CLASS_OF(recv) == rb_cString) { - val = rb_str_length(recv); - } - else if (HEAP_CLASS_OF(recv) == rb_cArray) { - val = LONG2NUM(RARRAY_LEN(recv)); - } - else if (HEAP_CLASS_OF(recv) == rb_cHash) { - val = INT2FIX(RHASH_SIZE(recv)); - } - else { - goto INSN_LABEL(normal_dispatch); - } - } - else { - INSN_LABEL(normal_dispatch): - PUSH(recv); - CALL_SIMPLE_METHOD(0, idLength, recv); - } -} - -/** - @c optimize - @e optimized succ - @j 最適化された recv.succ()。 - */ -DEFINE_INSN -opt_succ -() -(VALUE recv) -(VALUE val) -{ - if (SPECIAL_CONST_P(recv)) { - if (FIXNUM_P(recv) && - BASIC_OP_UNREDEFINED_P(BOP_SUCC)) { - const VALUE obj = INT2FIX(1); - /* fixnum + INT2FIX(1) */ - val = (recv + (obj & (~1))); - if ((~(recv ^ obj) & (recv ^ val)) & ((unsigned long)LONG_MAX + 1)) { - val = rb_big_plus(rb_int2big(FIX2LONG(recv)), - rb_int2big(FIX2LONG(obj))); - } - } - else { - goto INSN_LABEL(normal_dispatch); - } - } - else { - if (HEAP_CLASS_OF(recv) == rb_cString && - BASIC_OP_UNREDEFINED_P(BOP_SUCC)) { - val = rb_str_succ(recv); - } - else if (HEAP_CLASS_OF(recv) == rb_cTime && - BASIC_OP_UNREDEFINED_P(BOP_SUCC)) { - val = rb_time_succ(recv); - } - else - { - goto INSN_LABEL(normal_dispatch); - } - } - if (0) { - INSN_LABEL(normal_dispatch): - PUSH(recv); - CALL_SIMPLE_METHOD(0, idSucc, recv); - } -} - -/** - @c optimize - @e optimized not - @j 最適化された recv.!()。 - */ -DEFINE_INSN -opt_not -(IC ic) -(VALUE recv) -(VALUE val) -{ - extern VALUE rb_obj_not(VALUE obj); - NODE *mn = vm_method_search(idNot, CLASS_OF(recv), ic); - - if (check_cfunc(mn, rb_obj_not)) { - val = RTEST(recv) ? Qfalse : Qtrue; - } - else { - PUSH(recv); - CALL_SIMPLE_METHOD(0, idNot, recv); - } -} - - -/** - @c optimize - @e optimized regexp match - @j 最適化された正規表現マッチ。 - */ -DEFINE_INSN -opt_regexpmatch1 -(VALUE r) -(VALUE obj) -(VALUE val) -{ - val = rb_reg_match(r, obj); -} - -/** - @c optimize - @e optimized regexp match 2 - @j 最適化された正規表現マッチ 2 - */ -DEFINE_INSN -opt_regexpmatch2 -() -(VALUE obj2, VALUE obj1) -(VALUE val) -{ - if (TYPE(obj2) == T_STRING) { - val = rb_reg_match(obj1, obj2); - } - else { - val = rb_funcall(obj2, idEqTilde, 1, obj1); - } -} - -/** - @c optimize - @e call native compiled method - @j ネイティブコンパイルしたメソッドを起動。 - */ -DEFINE_INSN -opt_call_c_function -(rb_insn_func_t funcptr) -() -() -{ - reg_cfp = (funcptr)(th, reg_cfp); - - if (reg_cfp == 0) { - VALUE err = th->errinfo; - th->errinfo = Qnil; - THROW_EXCEPTION(err); - } - - RESTORE_REGS(); - NEXT_INSN(); -} - -/** - @c joke - @e BLT - @j BLT - */ -DEFINE_INSN -bitblt -() -() -(VALUE ret) -{ - ret = rb_str_new2("a bit of bacon, lettuce and tomato"); -} - -/** - @c joke - @e The Answer to Life, the Universe, and Everything - @j 人生、宇宙、すべての答え。 - */ -DEFINE_INSN -answer -() -() -(VALUE ret) -{ - ret = INT2FIX(42); -} - |