Simplify ensure stack management; fix #3683

parent 72b635f7
...@@ -113,7 +113,7 @@ typedef struct { ...@@ -113,7 +113,7 @@ typedef struct {
mrb_value *stackent; mrb_value *stackent;
int nregs; int nregs;
int ridx; int ridx;
int eidx; int epos;
struct REnv *env; struct REnv *env;
mrb_code *pc; /* return address */ mrb_code *pc; /* return address */
mrb_code *err; /* error position */ mrb_code *err; /* error position */
...@@ -143,7 +143,7 @@ struct mrb_context { ...@@ -143,7 +143,7 @@ struct mrb_context {
mrb_code **rescue; /* exception handler stack */ mrb_code **rescue; /* exception handler stack */
int rsize; int rsize;
struct RProc **ensure; /* ensure handler stack */ struct RProc **ensure; /* ensure handler stack */
int esize; int esize, eidx;
enum mrb_fiber_state status; enum mrb_fiber_state status;
mrb_bool vmexec; mrb_bool vmexec;
......
...@@ -933,7 +933,7 @@ gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) ...@@ -933,7 +933,7 @@ gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
children += i; children += i;
/* mark ensure stack */ /* mark ensure stack */
children += (c->ci) ? c->ci->eidx : 0; children += c->eidx;
/* mark closure */ /* mark closure */
if (c->cibase) { if (c->cibase) {
......
...@@ -234,7 +234,6 @@ cipush(mrb_state *mrb) ...@@ -234,7 +234,6 @@ cipush(mrb_state *mrb)
struct mrb_context *c = mrb->c; struct mrb_context *c = mrb->c;
mrb_callinfo *ci = c->ci; mrb_callinfo *ci = c->ci;
int eidx = ci->eidx;
int ridx = ci->ridx; int ridx = ci->ridx;
if (ci + 1 == c->ciend) { if (ci + 1 == c->ciend) {
...@@ -245,7 +244,7 @@ cipush(mrb_state *mrb) ...@@ -245,7 +244,7 @@ cipush(mrb_state *mrb)
c->ciend = c->cibase + size * 2; c->ciend = c->cibase + size * 2;
} }
ci = ++c->ci; ci = ++c->ci;
ci->eidx = eidx; ci->epos = mrb->c->eidx;
ci->ridx = ridx; ci->ridx = ridx;
ci->env = 0; ci->env = 0;
ci->pc = 0; ci->pc = 0;
...@@ -311,8 +310,6 @@ ecall(mrb_state *mrb, int i) ...@@ -311,8 +310,6 @@ ecall(mrb_state *mrb, int i)
p = mrb->c->ensure[i]; p = mrb->c->ensure[i];
if (!p) return; if (!p) return;
mrb->c->ensure[i] = NULL; mrb->c->ensure[i] = NULL;
if (ci->eidx > i)
ci->eidx = i;
cioff = ci - mrb->c->cibase; cioff = ci - mrb->c->cibase;
ci = cipush(mrb); ci = cipush(mrb);
ci->stackent = mrb->c->stack; ci->stackent = mrb->c->stack;
...@@ -1200,13 +1197,13 @@ RETRY_TRY_BLOCK: ...@@ -1200,13 +1197,13 @@ RETRY_TRY_BLOCK:
p = mrb_closure_new(mrb, irep->reps[GETARG_Bx(i)]); p = mrb_closure_new(mrb, irep->reps[GETARG_Bx(i)]);
/* push ensure_stack */ /* push ensure_stack */
if (mrb->c->esize <= mrb->c->ci->eidx+1) { if (mrb->c->esize <= mrb->c->eidx+1) {
if (mrb->c->esize == 0) mrb->c->esize = ENSURE_STACK_INIT_SIZE; if (mrb->c->esize == 0) mrb->c->esize = ENSURE_STACK_INIT_SIZE;
else mrb->c->esize *= 2; else mrb->c->esize *= 2;
mrb->c->ensure = (struct RProc **)mrb_realloc(mrb, mrb->c->ensure, sizeof(struct RProc*) * mrb->c->esize); mrb->c->ensure = (struct RProc **)mrb_realloc(mrb, mrb->c->ensure, sizeof(struct RProc*) * mrb->c->esize);
} }
mrb->c->ensure[mrb->c->ci->eidx++] = p; mrb->c->ensure[mrb->c->eidx++] = p;
mrb->c->ensure[mrb->c->ci->eidx] = NULL; mrb->c->ensure[mrb->c->eidx] = NULL;
ARENA_RESTORE(mrb, ai); ARENA_RESTORE(mrb, ai);
NEXT; NEXT;
} }
...@@ -1215,11 +1212,10 @@ RETRY_TRY_BLOCK: ...@@ -1215,11 +1212,10 @@ RETRY_TRY_BLOCK:
/* A A.times{ensure_pop().call} */ /* A A.times{ensure_pop().call} */
int a = GETARG_A(i); int a = GETARG_A(i);
mrb_callinfo *ci = mrb->c->ci; mrb_callinfo *ci = mrb->c->ci;
int n, eidx = ci->eidx; int n, epos = ci->epos;
for (n=0; n<a && (ci == mrb->c->cibase || eidx > ci[-1].eidx); n++) { for (n=0; n<a && mrb->c->eidx > epos; n++) {
ecall(mrb, --eidx); ecall(mrb, --mrb->c->eidx);
ci = mrb->c->ci;
ARENA_RESTORE(mrb, ai); ARENA_RESTORE(mrb, ai);
} }
NEXT; NEXT;
...@@ -1757,11 +1753,9 @@ RETRY_TRY_BLOCK: ...@@ -1757,11 +1753,9 @@ RETRY_TRY_BLOCK:
if (mrb->exc) { if (mrb->exc) {
mrb_callinfo *ci, *ci0; mrb_callinfo *ci, *ci0;
mrb_value *stk; mrb_value *stk;
int eidx;
L_RAISE: L_RAISE:
ci0 = ci = mrb->c->ci; ci0 = ci = mrb->c->ci;
eidx = ci->eidx;
if (ci == mrb->c->cibase) { if (ci == mrb->c->cibase) {
if (ci->ridx == 0) goto L_FTOP; if (ci->ridx == 0) goto L_FTOP;
goto L_RESCUE; goto L_RESCUE;
...@@ -1795,8 +1789,8 @@ RETRY_TRY_BLOCK: ...@@ -1795,8 +1789,8 @@ RETRY_TRY_BLOCK:
} }
/* call ensure only when we skip this callinfo */ /* call ensure only when we skip this callinfo */
if (ci[0].ridx == ci[-1].ridx) { if (ci[0].ridx == ci[-1].ridx) {
while (eidx > ci[-1].eidx) { while (mrb->c->eidx > ci->epos) {
ecall(mrb, --eidx); ecall(mrb, --mrb->c->eidx);
ci = mrb->c->ci; ci = mrb->c->ci;
} }
} }
...@@ -1814,7 +1808,7 @@ RETRY_TRY_BLOCK: ...@@ -1814,7 +1808,7 @@ RETRY_TRY_BLOCK:
} }
else { else {
mrb_callinfo *ci = mrb->c->ci; mrb_callinfo *ci = mrb->c->ci;
int acc, eidx = mrb->c->ci->eidx; int acc;
mrb_value v = regs[GETARG_A(i)]; mrb_value v = regs[GETARG_A(i)];
mrb_gc_protect(mrb, v); mrb_gc_protect(mrb, v);
...@@ -1859,8 +1853,8 @@ RETRY_TRY_BLOCK: ...@@ -1859,8 +1853,8 @@ RETRY_TRY_BLOCK:
mrb_exc_set(mrb, exc); mrb_exc_set(mrb, exc);
goto L_RAISE; goto L_RAISE;
} }
while (eidx > 0) { while (mrb->c->eidx > 0) {
ecall(mrb, --eidx); ecall(mrb, --mrb->c->eidx);
} }
/* automatic yield at the end */ /* automatic yield at the end */
mrb->c->status = MRB_FIBER_TERMINATED; mrb->c->status = MRB_FIBER_TERMINATED;
...@@ -1883,16 +1877,16 @@ RETRY_TRY_BLOCK: ...@@ -1883,16 +1877,16 @@ RETRY_TRY_BLOCK:
if (mrb->c->ci == mrb->c->cibase && mrb->c->ci->pc) { if (mrb->c->ci == mrb->c->cibase && mrb->c->ci->pc) {
struct mrb_context *c = mrb->c; struct mrb_context *c = mrb->c;
while (eidx > 0) { while (mrb->c->eidx > 0) {
ecall(mrb, --eidx); ecall(mrb, --mrb->c->eidx);
} }
mrb->c = c->prev; mrb->c = c->prev;
c->prev = NULL; c->prev = NULL;
ci = mrb->c->ci; ci = mrb->c->ci;
} }
if (ci->acc < 0) { if (ci->acc < 0) {
while (eidx > mrb->c->ci[-1].eidx) { while (mrb->c->eidx > mrb->c->ci->epos) {
ecall(mrb, --eidx); ecall(mrb, --mrb->c->eidx);
} }
ARENA_RESTORE(mrb, ai); ARENA_RESTORE(mrb, ai);
mrb->c->vmexec = FALSE; mrb->c->vmexec = FALSE;
...@@ -1916,8 +1910,8 @@ RETRY_TRY_BLOCK: ...@@ -1916,8 +1910,8 @@ RETRY_TRY_BLOCK:
/* cannot happen */ /* cannot happen */
break; break;
} }
while (eidx > mrb->c->ci[-1].eidx) { while (mrb->c->eidx > mrb->c->ci->epos) {
ecall(mrb, --eidx); ecall(mrb, --mrb->c->eidx);
} }
if (mrb->c->vmexec && !mrb->c->ci->target_class) { if (mrb->c->vmexec && !mrb->c->ci->target_class) {
ARENA_RESTORE(mrb, ai); ARENA_RESTORE(mrb, ai);
...@@ -2693,10 +2687,10 @@ RETRY_TRY_BLOCK: ...@@ -2693,10 +2687,10 @@ RETRY_TRY_BLOCK:
/* stop VM */ /* stop VM */
L_STOP: L_STOP:
{ {
int eidx_stop = mrb->c->ci == mrb->c->cibase ? 0 : mrb->c->ci[-1].eidx; int epos = mrb->c->ci->epos;
int eidx = mrb->c->ci->eidx;
while (eidx > eidx_stop) { while (mrb->c->eidx > epos) {
ecall(mrb, --eidx); ecall(mrb, --mrb->c->eidx);
} }
} }
ERR_PC_CLR(mrb); ERR_PC_CLR(mrb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment