diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2015-12-30 14:34:52 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2016-01-02 13:48:45 +0900 |
| commit | bd462c5edc170c0e730a154a99cc48e1a6b8e259 (patch) | |
| tree | 2f0eb20ce2922326232644648b3dbdfe97753213 /src | |
| parent | 4683b89b84cd5999847e2a9bc3f05a4732cc81a3 (diff) | |
| download | mruby-bd462c5edc170c0e730a154a99cc48e1a6b8e259.tar.gz mruby-bd462c5edc170c0e730a154a99cc48e1a6b8e259.zip | |
mruby-fiber: fiber_switch() to use nesting VM when it's called from C API or mrb_funcall(); close #3056
Diffstat (limited to 'src')
| -rw-r--r-- | src/vm.c | 36 |
1 files changed, 27 insertions, 9 deletions
@@ -209,6 +209,7 @@ top_env(mrb_state *mrb, struct RProc *proc) #define CI_ACC_SKIP -1 #define CI_ACC_DIRECT -2 +#define CI_ACC_RESUMED -3 static mrb_callinfo* cipush(mrb_state *mrb) @@ -736,9 +737,21 @@ void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value MRB_API mrb_value mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) { + mrb_irep *irep = proc->body.irep; + + if (!mrb->c->stack) { + stack_init(mrb); + } + stack_extend(mrb, irep->nregs, stack_keep); + mrb->c->stack[0] = self; + return mrb_vm_exec(mrb, proc, irep->iseq); +} + +MRB_API mrb_value +mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc) +{ /* mrb_assert(mrb_proc_cfunc_p(proc)) */ mrb_irep *irep = proc->body.irep; - mrb_code *pc = irep->iseq; mrb_value *pool = irep->pool; mrb_sym *syms = irep->syms; mrb_value *regs = NULL; @@ -782,14 +795,9 @@ RETRY_TRY_BLOCK: goto L_RAISE; } mrb->jmp = &c_jmp; - if (!mrb->c->stack) { - stack_init(mrb); - } - stack_extend(mrb, irep->nregs, stack_keep); mrb->c->ci->proc = proc; mrb->c->ci->nregs = irep->nregs; regs = mrb->c->stack; - regs[0] = self; INIT_DISPATCH { CASE(OP_NOP) { @@ -1131,19 +1139,24 @@ RETRY_TRY_BLOCK: ci->nregs = n + 2; } result = m->body.func(mrb, recv); - mrb->c->stack[0] = result; 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 (!MRB_PROC_CFUNC_P(ci[-1].proc)) { + if (ci->acc == CI_ACC_RESUMED) { + mrb->jmp = prev_jmp; + return result; + } + 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] = result; regs = mrb->c->stack = ci->stackent; pc = ci->pc; cipop(mrb); @@ -1608,14 +1621,19 @@ RETRY_TRY_BLOCK: while (eidx > mrb->c->ci[-1].eidx) { ecall(mrb, --eidx); } + if (mrb->c->vmexec && !mrb->c->ci->target_class) { + mrb->c->vmexec = FALSE; + mrb->jmp = prev_jmp; + return v; + } cipop(mrb); acc = ci->acc; - pc = ci->pc; regs = mrb->c->stack = ci->stackent; if (acc == CI_ACC_SKIP) { mrb->jmp = prev_jmp; return v; } + pc = ci->pc; DEBUG(printf("from :%s\n", mrb_sym2name(mrb, ci->mid))); proc = mrb->c->ci->proc; irep = proc->body.irep; |
