diff options
Diffstat (limited to 'insns.def')
-rw-r--r-- | insns.def | 310 |
1 files changed, 16 insertions, 294 deletions
@@ -84,35 +84,7 @@ getspecial () (VALUE val) { - if (type == 0) { - if (FIXNUM_P(key)) key = FIX2INT(key); - val = lfp_svar_get(th, GET_LFP(), key); - } - else { - VALUE backref = lfp_svar_get(th, GET_LFP(), 1); - - if (type & 0x01) { - switch (type >> 1) { - case '&': - val = rb_reg_last_match(backref); - break; - case '`': - val = rb_reg_match_pre(backref); - break; - case '\'': - val = rb_reg_match_post(backref); - break; - case '+': - val = rb_reg_match_last(backref); - break; - default: - rb_bug("unexpected back-ref"); - } - } - else { - val = rb_reg_nth_match(type >> 1, backref); - } - } + val = vm_getspecial(th, GET_LFP(), key, type); } /** @@ -930,7 +902,7 @@ defined ip = ip->parent_iseq; } if (ip) { - VALUE klass = vm_search_super_klass(ip->klass, GET_SELF()); + VALUE klass = vm_search_normal_super_klass(ip->klass, GET_SELF()); if (rb_method_boundp(klass, ip->defined_method_id, 0)) { expr_type = "super"; } @@ -1124,49 +1096,18 @@ send NODE *mn; VALUE recv, klass; rb_block_t *blockptr = 0; - rb_num_t num = caller_setup_args(th, GET_CFP(), op_flag, op_argc, blockiseq, &blockptr); + 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 */ - if (flag & VM_CALL_FCALL_BIT) { - /* method(...) */ - recv = GET_SELF(); - } - else { - /* recv.method(...) */ - recv = TOPN(num); - } - + 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) && mn && nd_type(mn->nd_body) == NODE_CFUNC) { - NODE *node = mn->nd_body; - extern VALUE rb_f_funcall(int argc, VALUE *argv, VALUE recv); - extern VALUE rb_f_send(int argc, VALUE *argv, VALUE recv); - - if (node->nd_cfnc == rb_f_funcall || node->nd_cfnc == rb_f_send) { - int i; - VALUE sym = TOPN(num - 1); - id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym); - - /* shift arguments */ - for (i=num-1; i>0; i--) { - TOPN(i) = TOPN(i-1); - } - - mn = rb_method_node(klass, id); - - num -= 1; - DEC_SP(1); - } - - if (node->nd_cfnc == rb_f_funcall) { - flag |= VM_CALL_FCALL_BIT; - } + 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); @@ -1183,58 +1124,15 @@ invokesuper (...) (VALUE val) // inc += - op_argc; { - rb_block_t *blockptr = 0; - VALUE flag = op_flag; - int num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &blockptr); - rb_iseq_t *iseq = GET_ISEQ(); - rb_iseq_t *ip = iseq; + 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; - ID id; NODE *mn; - - if (!blockptr && !(flag & VM_CALL_ARGS_BLOCKARG_BIT)) { - blockptr = GET_BLOCK_PTR(); - } + ID id; + const VALUE flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT; recv = GET_SELF(); - - while (ip && !ip->klass) { - ip = ip->parent_iseq; - } - - if (ip == 0) { - rb_raise(rb_eNoMethodError, "super called outside of method"); - } - - id = ip->defined_method_id; - - if (ip != ip->local_iseq) { - /* defined by Module#define_method() */ - rb_control_frame_t *lcfp = GET_CFP(); - - while (lcfp->iseq != ip) { - VALUE *tdfp = GET_PREV_DFP(lcfp->dfp); - while (1) { - lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp); - if (lcfp->dfp == tdfp) { - break; - } - } - } - - id = lcfp->method_id; - klass = vm_search_super_klass(lcfp->method_klass, recv); - - if (TOPN(num) == Qfalse) { - /* zsuper */ - rb_raise(rb_eRuntimeError, "implicit argument passing of super from method defined by define_method() is not supported. Specify all arguments explicitly."); - } - } - else { - klass = vm_search_super_klass(ip->klass, recv); - } - - flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT; + vm_search_super_klass(GET_CFP(), GET_ISEQ(), recv, TOPN(num), &id, &klass); mn = rb_method_node(klass, id); CALL_METHOD(num, blockptr, flag, id, mn, recv, klass); @@ -1251,42 +1149,10 @@ invokeblock (...) (VALUE val) // inc += 1 - num; { - rb_block_t *block = GET_BLOCK_PTR(); - rb_iseq_t *iseq; - int argc = num; - - if (GET_ISEQ()->local_iseq->type != ISEQ_TYPE_METHOD || block == 0) { - vm_localjump_error("no block given (yield)", Qnil, 0); - } - iseq = block->iseq; - - if (BUILTIN_TYPE(iseq) != T_NODE) { - int opt_pc; - - argc = caller_setup_args(th, GET_CFP(), flag, argc, 0, 0); - - CHECK_STACK_OVERFLOW(GET_CFP(), iseq->stack_max); - - DEC_SP(argc); - opt_pc = vm_yield_setup_args(th, iseq, argc, GET_SP(), 0, - block_proc_is_lambda(block->proc)); - argc = iseq->arg_size; - INC_SP(argc); - - vm_push_frame(th, iseq, - FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp, - iseq->iseq_encoded + opt_pc, GET_SP(), block->lfp, - iseq->local_size - argc); - - reg_cfp->sp -= argc; + val = vm_invoke_block(th, GET_CFP(), num, flag); + if (val == Qundef) { RESTORE_REGS(); NEXT_INSN(); - /* unreachable */ - } - else { - val = vm_yield_with_cfunc(th, block, block->self, - num, STACK_ADDR_FROM_TOP(num)); - POPN(num); } } @@ -1347,147 +1213,8 @@ throw (VALUE throwobj) (VALUE val) { - rb_num_t state = throw_state & 0xff; - rb_num_t flag = throw_state & 0x8000; - rb_num_t level = throw_state >> 16; - val = Qnil; /* dummy */ - - if (state != 0) { - VALUE *pt; - int i; - if (flag != 0) { - if (throw_state & 0x4000) { - pt = (void *)1; - } - else { - pt = 0; - } - } - else { - if (state == TAG_BREAK) { - rb_control_frame_t *cfp = GET_CFP(); - VALUE *dfp = GET_DFP(); - int is_orphan = 1; - rb_iseq_t *base_iseq = GET_ISEQ(); - - INSN_LABEL(search_parent): - if (cfp->iseq->type != ISEQ_TYPE_BLOCK) { - dfp = GC_GUARDED_PTR_REF((VALUE *) *dfp); - base_iseq = base_iseq->parent_iseq; - - while ((VALUE *) cfp < th->stack + th->stack_size) { - if (cfp->dfp == dfp) { - goto INSN_LABEL(search_parent); - } - cfp++; - } - rb_bug("VM (throw): can't find break base."); - } - - if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_LAMBDA) { - /* lambda{... break ...} */ - is_orphan = 0; - pt = dfp; - } - else { - dfp = GC_GUARDED_PTR_REF((VALUE *) *dfp); - - while ((VALUE *)cfp < th->stack + th->stack_size) { - if (cfp->dfp == dfp) { - VALUE epc = epc = cfp->pc - cfp->iseq->iseq_encoded; - rb_iseq_t *iseq = cfp->iseq; - int i; - - for (i=0; i<iseq->catch_table_size; i++) { - struct iseq_catch_table_entry *entry = &iseq->catch_table[i]; - - if (entry->type == CATCH_TYPE_BREAK && - entry->start < epc && entry->end >= epc) { - if (entry->cont == epc) { - goto INSN_LABEL(found); - } - else { - break; - } - } - } - break; - - INSN_LABEL(found): - - pt = dfp; - is_orphan = 0; - break; - } - cfp++; - } - } - - if (is_orphan) { - vm_localjump_error("break from proc-closure", throwobj, TAG_BREAK); - } - } - else if (state == TAG_RETRY) { - pt = GC_GUARDED_PTR_REF((VALUE *) * GET_DFP()); - for (i = 0; i < level; i++) { - pt = GC_GUARDED_PTR_REF((VALUE *) * pt); - } - } - else if (state == TAG_RETURN) { - rb_control_frame_t *cfp = GET_CFP(); - VALUE *dfp = GET_DFP(); - int is_orphan = 1; - - /** - * check orphan: - */ - while ((VALUE *) cfp < th->stack + th->stack_size) { - if (GET_DFP() == dfp) { - if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_LAMBDA) { - /* in lambda */ - is_orphan = 0; - break; - } - } - cfp++; - if (GET_LFP() == cfp->lfp && - cfp->iseq->type == ISEQ_TYPE_METHOD) { - is_orphan = 0; - break; - } - } - - if (is_orphan) { - vm_localjump_error("unexpected return", throwobj, TAG_RETURN); - } - - pt = GET_LFP(); - } - else { - rb_bug("isns(throw): unsupport throw type"); - } - } - th->state = state; - THROW_EXCEPTION(NEW_THROW_OBJECT(throwobj, (VALUE) pt, state)); - } - else { - /* continue throw */ - VALUE err = throwobj; - - if (FIXNUM_P(err)) { - th->state = FIX2INT(err); - } - else if (SYMBOL_P(err)) { - th->state = TAG_THROW; - } - else if (BUILTIN_TYPE(err) == T_NODE) { - th->state = GET_THROWOBJ_STATE(err); - } - else { - th->state = FIX2INT(rb_ivar_get(err, idThrowState)); - } - THROW_EXCEPTION(err); - } + val = vm_throw(th, GET_CFP(), throw_state, throwobj); + THROW_EXCEPTION(val); /* unreachable */ } @@ -1936,18 +1663,13 @@ opt_mod double y = RFLOAT(obj)->value; double div, mod; - /* copied from numeric.c#flodivmod */ -#if 0 && defined(HAVE_FMOD) && !__x86_64__ /* temporary */ - mod = fmod(x, y); - printf("-- %f %% %f = %f\n", x, y, mod); -#else { double z; modf(x / y, &z); mod = x - z * y; } -#endif + div = (x - mod) / y; if (y * mod < 0) { mod += y; |