mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #5775 from dearblue/integrate-super
Integrate the second half of `OP_SUPER` with `OP_SENDB`
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user