Keep reference to mrb_context from env; fix #3619

parent 3b0a36d3
...@@ -18,8 +18,11 @@ MRB_BEGIN_DECL ...@@ -18,8 +18,11 @@ MRB_BEGIN_DECL
struct REnv { struct REnv {
MRB_OBJECT_HEADER; MRB_OBJECT_HEADER;
mrb_value *stack; mrb_value *stack;
mrb_sym mid;
ptrdiff_t cioff; ptrdiff_t cioff;
union {
mrb_sym mid;
struct mrb_context *c;
} cxt;
}; };
#define MRB_SET_ENV_STACK_LEN(e,len) (e)->flags = (unsigned int)(len) #define MRB_SET_ENV_STACK_LEN(e,len) (e)->flags = (unsigned int)(len)
......
...@@ -30,7 +30,7 @@ get_closure_irep(mrb_state *mrb, int level) ...@@ -30,7 +30,7 @@ get_closure_irep(mrb_state *mrb, int level)
if (!e) return NULL; if (!e) return NULL;
if (!MRB_ENV_STACK_SHARED_P(e)) return NULL; if (!MRB_ENV_STACK_SHARED_P(e)) return NULL;
c = e->cxt.c;
proc = c->cibase[e->cioff].proc; proc = c->cibase[e->cioff].proc;
if (!proc || MRB_PROC_CFUNC_P(proc)) { if (!proc || MRB_PROC_CFUNC_P(proc)) {
...@@ -196,7 +196,7 @@ create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, con ...@@ -196,7 +196,7 @@ create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, con
e = c->ci[-1].proc->env; e = c->ci[-1].proc->env;
if (!e) e = c->ci[-1].env; if (!e) e = c->ci[-1].env;
e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)e); e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)e);
e->mid = c->ci[-1].mid; e->cxt.c = c;
e->cioff = c->ci - c->cibase - 1; e->cioff = c->ci - c->cibase - 1;
e->stack = c->ci->stackent; e->stack = c->ci->stackent;
MRB_SET_ENV_STACK_LEN(e, c->ci[-1].proc->body.irep->nlocals); MRB_SET_ENV_STACK_LEN(e, c->ci[-1].proc->body.irep->nlocals);
......
...@@ -593,8 +593,9 @@ mark_context(mrb_state *mrb, struct mrb_context *c) ...@@ -593,8 +593,9 @@ mark_context(mrb_state *mrb, struct mrb_context *c)
mrb_gc_mark(mrb, (struct RBasic*)c->ensure[i]); mrb_gc_mark(mrb, (struct RBasic*)c->ensure[i]);
} }
/* mark fibers */ /* mark fibers */
if (c->prev && c->prev->fib) { mrb_gc_mark(mrb, (struct RBasic*)c->fib);
mrb_gc_mark(mrb, (struct RBasic*)c->prev->fib); if (c->prev) {
mark_context(mrb, c->prev);
} }
} }
...@@ -646,6 +647,9 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) ...@@ -646,6 +647,9 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
struct REnv *e = (struct REnv*)obj; struct REnv *e = (struct REnv*)obj;
mrb_int i, len; mrb_int i, len;
if (MRB_ENV_STACK_SHARED_P(e) && e->cxt.c->fib) {
mrb_gc_mark(mrb, (struct RBasic*)e->cxt.c->fib);
}
len = MRB_ENV_STACK_LEN(e); len = MRB_ENV_STACK_LEN(e);
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
mrb_gc_mark_value(mrb, e->stack[i]); mrb_gc_mark_value(mrb, e->stack[i]);
...@@ -878,13 +882,10 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc) ...@@ -878,13 +882,10 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc)
mrb_gc_mark(mrb, (struct RBasic*)mrb->arena_err); mrb_gc_mark(mrb, (struct RBasic*)mrb->arena_err);
#endif #endif
mark_context(mrb, mrb->root_c);
if (mrb->root_c->fib) {
mrb_gc_mark(mrb, (struct RBasic*)mrb->root_c->fib);
}
if (mrb->root_c != mrb->c) { if (mrb->root_c != mrb->c) {
mark_context(mrb, mrb->c); mark_context(mrb, mrb->c);
} }
mark_context(mrb, mrb->root_c);
} }
static size_t static size_t
......
...@@ -158,7 +158,7 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) ...@@ -158,7 +158,7 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
ci = 0; /* no callinfo available */ ci = 0; /* no callinfo available */
} }
else { else {
ci = mrb->c->cibase + e->cioff; ci = e->cxt.c->cibase + e->cioff;
bp = ci[1].stackent + 1; bp = ci[1].stackent + 1;
} }
} }
...@@ -1165,8 +1165,8 @@ mrb_local_variables(mrb_state *mrb, mrb_value self) ...@@ -1165,8 +1165,8 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
while (e) { while (e) {
if (MRB_ENV_STACK_SHARED_P(e) && if (MRB_ENV_STACK_SHARED_P(e) &&
!MRB_PROC_CFUNC_P(mrb->c->cibase[e->cioff].proc)) { !MRB_PROC_CFUNC_P(e->cxt.c->cibase[e->cioff].proc)) {
irep = mrb->c->cibase[e->cioff].proc->body.irep; irep = e->cxt.c->cibase[e->cioff].proc->body.irep;
if (irep->lv) { if (irep->lv) {
for (i = 0; i + 1 < irep->nlocals; ++i) { for (i = 0; i + 1 < irep->nlocals; ++i) {
if (irep->lv[i].name) { if (irep->lv[i].name) {
......
...@@ -41,7 +41,7 @@ env_new(mrb_state *mrb, int nlocals) ...@@ -41,7 +41,7 @@ env_new(mrb_state *mrb, int nlocals)
e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env); e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env);
MRB_SET_ENV_STACK_LEN(e, nlocals); MRB_SET_ENV_STACK_LEN(e, nlocals);
e->mid = mrb->c->ci->mid; e->cxt.c = mrb->c;
e->cioff = mrb->c->ci - mrb->c->cibase; e->cioff = mrb->c->ci - mrb->c->cibase;
e->stack = mrb->c->stack; e->stack = mrb->c->stack;
......
...@@ -201,8 +201,8 @@ is_strict(mrb_state *mrb, struct REnv *e) ...@@ -201,8 +201,8 @@ is_strict(mrb_state *mrb, struct REnv *e)
{ {
int cioff = e->cioff; int cioff = e->cioff;
if (MRB_ENV_STACK_SHARED_P(e) && mrb->c->cibase[cioff].proc && if (MRB_ENV_STACK_SHARED_P(e) && e->cxt.c->cibase[cioff].proc &&
MRB_PROC_STRICT_P(mrb->c->cibase[cioff].proc)) { MRB_PROC_STRICT_P(e->cxt.c->cibase[cioff].proc)) {
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
...@@ -264,8 +264,9 @@ mrb_env_unshare(mrb_state *mrb, struct REnv *e) ...@@ -264,8 +264,9 @@ mrb_env_unshare(mrb_state *mrb, struct REnv *e)
MRB_ENV_UNSHARE_STACK(e); MRB_ENV_UNSHARE_STACK(e);
if (!e->c) { if (!e->c) {
/* save block argument position (negated) */ /* save block argument position (negated) */
e->cioff = -mrb->c->cibase[cioff].argc-1; e->cioff = -e->cxt.c->cibase[cioff].argc-1;
} }
e->cxt.mid = e->cxt.c->cibase[cioff].mid;
p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len); p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
if (len > 0) { if (len > 0) {
stack_copy(p, e->stack, len); stack_copy(p, e->stack, len);
...@@ -1236,6 +1237,10 @@ RETRY_TRY_BLOCK: ...@@ -1236,6 +1237,10 @@ RETRY_TRY_BLOCK:
bidx = a+n+1; bidx = a+n+1;
} }
if (GET_OPCODE(i) != OP_SENDB) { if (GET_OPCODE(i) != OP_SENDB) {
if (bidx >= mrb->c->ci->nregs) {
stack_extend(mrb, bidx+1);
mrb->c->ci->nregs = bidx+1;
}
SET_NIL_VALUE(regs[bidx]); SET_NIL_VALUE(regs[bidx]);
} }
else { else {
...@@ -1363,9 +1368,15 @@ RETRY_TRY_BLOCK: ...@@ -1363,9 +1368,15 @@ RETRY_TRY_BLOCK:
ci->target_class = m->target_class; ci->target_class = m->target_class;
ci->proc = m; ci->proc = m;
if (m->env) { if (m->env) {
if (m->env->mid) { mrb_sym mid;
ci->mid = m->env->mid;
if (MRB_ENV_STACK_SHARED_P(m->env)) {
mid = m->env->cxt.c->cibase[m->env->cioff].mid;
}
else {
mid = m->env->cxt.mid;
} }
if (mid) ci->mid = mid;
if (!m->env->stack) { if (!m->env->stack) {
m->env->stack = mrb->c->stack; m->env->stack = mrb->c->stack;
} }
...@@ -1990,7 +2001,8 @@ RETRY_TRY_BLOCK: ...@@ -1990,7 +2001,8 @@ RETRY_TRY_BLOCK:
if (lv == 0) stack = regs + 1; if (lv == 0) stack = regs + 1;
else { else {
struct REnv *e = uvenv(mrb, lv-1); struct REnv *e = uvenv(mrb, lv-1);
if (!e || e->mid == 0) { if (!e || e->cioff == 0 ||
(!MRB_ENV_STACK_SHARED_P(e) && e->cxt.mid == 0)) {
localjump_error(mrb, LOCALJUMP_ERROR_YIELD); localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
goto L_RAISE; goto L_RAISE;
} }
......
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