diff --git a/include/mruby.h b/include/mruby.h index 490f344ac..3b4a1fc72 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -176,9 +176,9 @@ typedef struct { uint8_t n:4; /* (15=*) c=n|nk<<4 */ uint8_t nk:4; /* (15=*) */ uint8_t cci; /* called from C function */ - uint8_t flags; /* MRB_CI_COMPANION_BLOCK or zero */ mrb_sym mid; const struct RProc *proc; + struct RProc *blk; mrb_value *stack; const mrb_code *pc; /* current address on iseq of this proc */ union { diff --git a/include/mruby/internal.h b/include/mruby/internal.h index d8e81eafe..9f8453eaa 100644 --- a/include/mruby/internal.h +++ b/include/mruby/internal.h @@ -195,9 +195,6 @@ mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value); mrb_value mrb_mod_module_eval(mrb_state*, mrb_value); mrb_value mrb_f_send(mrb_state *mrb, mrb_value self); -/* mrb_callinfo::flags */ -#define MRB_CI_COMPANION_BLOCK 0x01 /* it means `method { ... }`, not `method(&blk)` */ - #ifdef MRB_USE_BIGINT mrb_value mrb_bint_new_int(mrb_state *mrb, mrb_int x); #ifdef MRB_INT64 diff --git a/src/vm.c b/src/vm.c index 3a30f65bd..d9416d41b 100644 --- a/src/vm.c +++ b/src/vm.c @@ -349,15 +349,9 @@ cipush(mrb_state *mrb, mrb_int push_stacks, uint8_t cci, struct RClass *target_c c->ciend = c->cibase + size * 2; } ci = ++c->ci; - ci->flags = 0; - if (blk && (blk->flags & (MRB_PROC_CFUNC_FL | MRB_PROC_ENVSET | MRB_PROC_ORPHAN)) == MRB_PROC_ENVSET && - blk->e.env == ci[-1].u.env) { - mrb_assert(blk->color != MRB_GC_RED); // no exist red object with env set - ci->flags = MRB_CI_COMPANION_BLOCK; - blk->flags |= MRB_PROC_ORPHAN; - } ci->mid = mid; CI_PROC_SET(ci, proc); + ci->blk = blk; ci->stack = ci[-1].stack + push_stacks; ci->n = argc & 0xf; ci->nk = (argc>>4) & 0xf; @@ -465,6 +459,11 @@ cipop(mrb_state *mrb) struct REnv *env = CI_ENV(ci); ci_env_set(ci, NULL); // make possible to free env by GC if not needed + struct RProc *b = ci->blk; + if (b && !mrb_object_dead_p(mrb, (struct RBasic*)b) && b->tt == MRB_TT_PROC && + !MRB_PROC_STRICT_P(b) && MRB_PROC_ENV(b) == CI_ENV(&ci[-1])) { + b->flags |= MRB_PROC_ORPHAN; + } if (env && !mrb_env_unshare(mrb, env, TRUE)) { c->ci--; // exceptions are handled at the method caller; see #3087 mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err)); @@ -2291,7 +2290,7 @@ RETRY_TRY_BLOCK: } if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN; - if (!MRB_PROC_ENV_P(proc)) { + if (MRB_PROC_ORPHAN_P(proc) || !MRB_PROC_ENV_P(proc) || !MRB_ENV_ONSTACK_P(MRB_PROC_ENV(proc))) { L_BREAK_ERROR: RAISE_LIT(mrb, E_LOCALJUMP_ERROR, "break from proc-closure"); } @@ -2307,7 +2306,7 @@ RETRY_TRY_BLOCK: while (mrb->c->cibase < ci && ci[-1].proc != proc) { ci--; } - if (ci == mrb->c->cibase || !(ci->flags & MRB_CI_COMPANION_BLOCK)) { + if (ci == mrb->c->cibase) { goto L_BREAK_ERROR; } c = a; // release the "a" variable, which can handle 32-bit values @@ -2333,7 +2332,7 @@ RETRY_TRY_BLOCK: if (MRB_PROC_ENV_P(dst)) { struct REnv *e = MRB_PROC_ENV(dst); - if (e->cxt != mrb->c) { + if (!MRB_ENV_ONSTACK_P(e) || e->cxt != mrb->c) { localjump_error(mrb, LOCALJUMP_ERROR_RETURN); goto L_RAISE; }