diff --git a/src/vm.c b/src/vm.c index 23ed1f8dc..ce4848fa6 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1259,38 +1259,6 @@ hash_new_from_regs(mrb_state *mrb, mrb_int argc, mrb_int idx) return hash; } -#define ARGUMENT_NORMALIZE(arg_base, arg_info, insn) do { \ - int n = *(arg_info)&0xf; \ - int nk = (*(arg_info)>>4)&0xf; \ - mrb_int bidx = (arg_base) + mrb_bidx(n,nk); \ - if (nk == CALL_MAXARGS) { \ - mrb_ensure_hash_type(mrb, regs[(arg_base)+(n==CALL_MAXARGS?1:n)+1]); \ - } \ - else if (nk > 0) { /* pack keyword arguments */ \ - mrb_int kidx = (arg_base)+(n==CALL_MAXARGS?1:n)+1; \ - mrb_value kdict = hash_new_from_regs(mrb, nk, kidx); \ - regs[kidx] = kdict; \ - nk = CALL_MAXARGS; \ - *(arg_info) = n | (nk<<4); \ - } \ - \ - mrb_assert(bidx < irep->nregs); \ - mrb_int new_bidx = (arg_base)+mrb_bidx(n, nk); \ - if ((insn) == OP_SEND) { \ - /* clear block argument */ \ - SET_NIL_VALUE(regs[new_bidx]); \ - SET_NIL_VALUE(blk); \ - } \ - else { \ - blk = regs[bidx]; \ - if (!mrb_nil_p(blk) && !mrb_proc_p(blk)) { \ - blk = mrb_type_convert(mrb, blk, MRB_TT_PROC, MRB_SYM(to_proc)); \ - /* The stack might have been reallocated during mrb_type_convert(), see #3622 */ \ - } \ - regs[new_bidx] = blk; \ - } \ -} while (0) - static mrb_value ary_new_from_regs(mrb_state *mrb, mrb_int argc, mrb_int idx) { @@ -1724,14 +1692,46 @@ RETRY_TRY_BLOCK: struct RClass *cls; mrb_value recv, blk; - ARGUMENT_NORMALIZE(a, &c, insn); + { + int n = c&0xf; + int nk = (c>>4)&0xf; + mrb_int bidx = a + mrb_bidx(n,nk); + + if (nk == CALL_MAXARGS) { + mrb_ensure_hash_type(mrb, regs[a+(n==CALL_MAXARGS?1:n)+1]); + } + else if (nk > 0) { /* pack keyword arguments */ + mrb_int kidx = a+(n==CALL_MAXARGS?1:n)+1; + mrb_value kdict = hash_new_from_regs(mrb, nk, kidx); + regs[kidx] = kdict; + nk = CALL_MAXARGS; + c = n | (nk<<4); + } + + mrb_assert(bidx < irep->nregs); + mrb_int new_bidx = a+mrb_bidx(n, nk); + if (insn == OP_SEND) { + /* clear block argument */ + SET_NIL_VALUE(regs[new_bidx]); + SET_NIL_VALUE(blk); + } + else { + blk = regs[bidx]; + if (!mrb_nil_p(blk) && !mrb_proc_p(blk)) { + blk = mrb_type_convert(mrb, blk, MRB_TT_PROC, MRB_SYM(to_proc)); + /* The stack might have been reallocated during mrb_type_convert(), see #3622 */ + } + regs[new_bidx] = blk; + } + } recv = regs[a]; - cls = mrb_class(mrb, recv); + ci = mrb->c->ci; + cls = (insn == OP_SUPER) ? CI_TARGET_CLASS(ci)->super : mrb_class(mrb, recv); m = mrb_method_search_vm(mrb, &cls, mid); ci = cipush(mrb, a, CINFO_DIRECT, NULL, NULL, 0, c); if (MRB_METHOD_UNDEF_P(m)) { - m = prepare_missing(mrb, recv, mid, &cls, 0, &c, blk, 0); + m = prepare_missing(mrb, recv, mid, &cls, 0, &c, blk, (insn == OP_SUPER ? 1 : 0)); mid = MRB_SYM(method_missing); ci->n = (c >> 0) & 0x0f; ci->nk = (c >> 4) & 0x0f; @@ -1841,14 +1841,12 @@ RETRY_TRY_BLOCK: } CASE(OP_SUPER, BB) { - mrb_method_t m; - struct RClass *cls; mrb_callinfo *ci = mrb->c->ci; - mrb_value recv, blk; + mrb_value recv; const struct RProc *p = ci->proc; - mrb_sym mid = ci->mid; struct RClass* target_class = CI_TARGET_CLASS(ci); + mid = ci->mid; if (MRB_PROC_ENV_P(p) && p->e.env->mid && p->e.env->mid != mid) { /* alias support */ mid = p->e.env->mid; /* restore old mid */ } @@ -1870,61 +1868,9 @@ RETRY_TRY_BLOCK: goto L_RAISE; } - ARGUMENT_NORMALIZE(a, &b, OP_SUPER); - - cls = target_class->super; - m = mrb_method_search_vm(mrb, &cls, mid); - if (MRB_METHOD_UNDEF_P(m)) { - m = prepare_missing(mrb, recv, mid, &cls, a, &b, blk, 1); - mid = MRB_SYM(method_missing); - } - - /* push callinfo */ - ci = cipush(mrb, a, 0, cls, NULL, mid, b); - - /* prepare stack */ - ci->stack[0] = recv; - - if (MRB_METHOD_CFUNC_P(m)) { - mrb_value v; - - if (MRB_METHOD_PROC_P(m)) { - const struct RProc *p = MRB_METHOD_PROC(m); - CI_PROC_SET(ci, p); - } - v = MRB_METHOD_CFUNC(m)(mrb, recv); - mrb_gc_arena_restore(mrb, ai); - if (mrb->exc) goto L_RAISE; - ci = mrb->c->ci; - mrb_assert(!mrb_break_p(v)); - if (!CI_TARGET_CLASS(ci)) { /* return from context modifying method (resume/yield) */ - if (ci->cci == CINFO_RESUMED) { - mrb->jmp = prev_jmp; - return v; - } - else { - mrb_assert(!MRB_PROC_CFUNC_P(ci[-1].proc)); - proc = ci[-1].proc; - irep = proc->body.irep; - pool = irep->pool; - syms = irep->syms; - } - } - mrb->c->ci->stack[0] = v; - ci = cipop(mrb); - pc = ci->pc; - } - else { - /* setup environment for calling method */ - proc = MRB_METHOD_PROC(m); - CI_PROC_SET(ci, proc); - irep = proc->body.irep; - pool = irep->pool; - syms = irep->syms; - mrb_stack_extend(mrb, (irep->nregs < 4) ? 4 : irep->nregs); - pc = irep->iseq; - } - JUMP; + c = b; // arg info + regs[a] = recv; + goto L_SENDB_SYM; } CASE(OP_ARGARY, BS) {