summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-09-05 21:12:36 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-09-05 21:12:36 +0900
commitf68f5f6b975207a02d11f7b9d6870ee1f5098f85 (patch)
tree47586d7e640c2cea55d80deab1340828c0adc92a /src
parent7f4b57bb2029b52a3ef136588e06721b53b10bf8 (diff)
downloadmruby-f68f5f6b975207a02d11f7b9d6870ee1f5098f85.tar.gz
mruby-f68f5f6b975207a02d11f7b9d6870ee1f5098f85.zip
Avoid crossing C function boundary from `OP_EPOP`; ref #3789
Diffstat (limited to 'src')
-rw-r--r--src/vm.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/src/vm.c b/src/vm.c
index f413211e7..3b8119c67 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -1319,14 +1319,30 @@ RETRY_TRY_BLOCK:
CASE(OP_EPOP) {
/* A A.times{ensure_pop().call} */
int a = GETARG_A(i);
- mrb_callinfo *ci = mrb->c->ci;
- int n, epos = ci->epos;
+ mrb_callinfo *ci, *nci;
+ mrb_value self = regs[0];
- for (n=0; n<a && mrb->c->eidx > epos; n++) {
- ecall(mrb, --mrb->c->eidx);
- mrb_gc_arena_restore(mrb, ai);
- }
- NEXT;
+ /* temporary limitation */
+ mrb_assert(a==1);
+ proc = mrb->c->ensure[--mrb->c->eidx];
+ ci = mrb->c->ci;
+ nci = cipush(mrb);
+ nci->mid = ci->mid;
+ nci->argc = 0;
+ nci->proc = proc;
+ nci->stackent = mrb->c->stack;
+ nci->nregs = irep->nregs;
+ nci->target_class = proc->target_class;
+ nci->pc = pc + 1;
+ nci->acc = nci->nregs;
+ mrb->c->stack += ci->nregs;
+ stack_extend(mrb, nci->nregs);
+ irep = proc->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+ regs[0] = self;
+ pc = irep->iseq;
+ JUMP;
}
CASE(OP_LOADNIL) {