summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-04-18 11:52:16 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-04-18 11:52:16 +0900
commitf6c70bc6e8ea472f4d1620d38745da4be0722197 (patch)
tree513b3bb83061eff3ca2156f1820d23028b9534f6 /src
parent05fceb5992c20c30a6b31f89d2b0aa0f0698a9a2 (diff)
downloadmruby-f6c70bc6e8ea472f4d1620d38745da4be0722197.tar.gz
mruby-f6c70bc6e8ea472f4d1620d38745da4be0722197.zip
`super` may call context switching method like `send`; fix #3611
Diffstat (limited to 'src')
-rw-r--r--src/vm.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/src/vm.c b/src/vm.c
index d26189ac9..c9313d868 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -991,11 +991,14 @@ RETRY_TRY_BLOCK:
CASE(OP_GETCONST) {
/* A Bx R(A) := constget(Syms(Bx)) */
mrb_value val;
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ mrb_sym sym = syms[bx];
ERR_PC_SET(mrb, pc);
- val = mrb_vm_const_get(mrb, syms[GETARG_Bx(i)]);
+ val = mrb_vm_const_get(mrb, sym);
ERR_PC_CLR(mrb);
- regs[GETARG_A(i)] = val;
+ regs[a] = val;
NEXT;
}
@@ -1276,7 +1279,6 @@ RETRY_TRY_BLOCK:
result = m->body.func(mrb, recv);
mrb_gc_arena_restore(mrb, ai);
if (mrb->exc) goto L_RAISE;
- /* pop stackpos */
ci = mrb->c->ci;
if (!ci->target_class) { /* return from context modifying method (resume/yield) */
if (ci->acc == CI_ACC_RESUMED) {
@@ -1292,6 +1294,7 @@ RETRY_TRY_BLOCK:
}
}
mrb->c->stack[0] = result;
+ /* pop stackpos */
mrb->c->stack = ci->stackent;
pc = ci->pc;
cipop(mrb);
@@ -1475,13 +1478,28 @@ RETRY_TRY_BLOCK:
ci->nregs = n + 2;
}
v = m->body.func(mrb, recv);
- mrb->c->stack[0] = v;
mrb_gc_arena_restore(mrb, ai);
if (mrb->exc) goto L_RAISE;
+ ci = mrb->c->ci;
+ if (!ci->target_class) { /* return from context modifying method (resume/yield) */
+ if (ci->acc == CI_ACC_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->stack[0] = v;
/* pop stackpos */
- mrb->c->stack = mrb->c->ci->stackent;
+ mrb->c->stack = ci->stackent;
+ pc = ci->pc;
cipop(mrb);
- NEXT;
+ JUMP;
}
else {
/* fill callinfo */