From dba1dcdd251b17002529865c9c32aa4a92a02d20 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 24 Dec 2023 15:45:15 +0900 Subject: [PATCH] Integrates the sequence when a fiber is terminated by `OP_RETURN` In the `ensure` block while executing `fiber.transfer`, keep `fiber->cxt->prev` to be `NULL`. --- src/vm.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/vm.c b/src/vm.c index 390d0742b..998e2458f 100644 --- a/src/vm.c +++ b/src/vm.c @@ -2346,28 +2346,18 @@ RETRY_TRY_BLOCK: NORMAL_RETURN: ci = mrb->c->ci; - v = regs[a]; - mrb_gc_protect(mrb, v); if (ci == mrb->c->cibase) { struct mrb_context *c; c = mrb->c; - if (!c->prev) { - if (c != mrb->root_c) { - /* fiber termination should transfer to root */ - c->prev = mrb->root_c; - } - else { /* toplevel return */ - regs[irep->nlocals] = v; - goto CHECKPOINT_LABEL_MAKE(RBREAK_TAG_STOP); - } - } - else if (!c->vmexec && c->prev->ci == c->prev->cibase) { + if (c->prev && !c->vmexec && c->prev->ci == c->prev->cibase) { RAISE_LIT(mrb, E_FIBER_ERROR, "double resume"); } } + v = regs[a]; + mrb_gc_protect(mrb, v); CHECKPOINT_RESTORE(RBREAK_TAG_BREAK) { if (TRUE) { struct RBreak *brk = (struct RBreak*)mrb->exc; @@ -2404,11 +2394,17 @@ RETRY_TRY_BLOCK: if (ci == mrb->c->cibase) { struct mrb_context *c = mrb->c; - /* automatic yield at the end */ + if (c == mrb->root_c) { + /* toplevel return */ + regs[irep->nlocals] = v; + goto L_STOP; + } + + /* fiber termination should automatic yield or transfer to root */ c->status = MRB_FIBER_TERMINATED; - mrb->c = c->prev; - mrb->c->status = MRB_FIBER_RUNNING; + mrb->c = c->prev ? c->prev : mrb->root_c; c->prev = NULL; + mrb->c->status = MRB_FIBER_RUNNING; if (c->vmexec) { mrb_gc_arena_restore(mrb, ai); c->vmexec = FALSE;