mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Keep reference to mrb_context from env; fix #3619
This commit is contained in:
@@ -18,8 +18,11 @@ MRB_BEGIN_DECL
|
||||
struct REnv {
|
||||
MRB_OBJECT_HEADER;
|
||||
mrb_value *stack;
|
||||
mrb_sym mid;
|
||||
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)
|
||||
|
||||
@@ -30,7 +30,7 @@ get_closure_irep(mrb_state *mrb, int level)
|
||||
|
||||
if (!e) return NULL;
|
||||
if (!MRB_ENV_STACK_SHARED_P(e)) return NULL;
|
||||
|
||||
c = e->cxt.c;
|
||||
proc = c->cibase[e->cioff].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
|
||||
e = c->ci[-1].proc->env;
|
||||
if (!e) e = c->ci[-1].env;
|
||||
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->stack = c->ci->stackent;
|
||||
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)
|
||||
mrb_gc_mark(mrb, (struct RBasic*)c->ensure[i]);
|
||||
}
|
||||
/* mark fibers */
|
||||
if (c->prev && c->prev->fib) {
|
||||
mrb_gc_mark(mrb, (struct RBasic*)c->prev->fib);
|
||||
mrb_gc_mark(mrb, (struct RBasic*)c->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)
|
||||
struct REnv *e = (struct REnv*)obj;
|
||||
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);
|
||||
for (i=0; i<len; i++) {
|
||||
mrb_gc_mark_value(mrb, e->stack[i]);
|
||||
@@ -878,13 +882,10 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc)
|
||||
mrb_gc_mark(mrb, (struct RBasic*)mrb->arena_err);
|
||||
#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) {
|
||||
mark_context(mrb, mrb->c);
|
||||
}
|
||||
mark_context(mrb, mrb->root_c);
|
||||
}
|
||||
|
||||
static size_t
|
||||
|
||||
+3
-3
@@ -158,7 +158,7 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
|
||||
ci = 0; /* no callinfo available */
|
||||
}
|
||||
else {
|
||||
ci = mrb->c->cibase + e->cioff;
|
||||
ci = e->cxt.c->cibase + e->cioff;
|
||||
bp = ci[1].stackent + 1;
|
||||
}
|
||||
}
|
||||
@@ -1165,8 +1165,8 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
|
||||
|
||||
while (e) {
|
||||
if (MRB_ENV_STACK_SHARED_P(e) &&
|
||||
!MRB_PROC_CFUNC_P(mrb->c->cibase[e->cioff].proc)) {
|
||||
irep = mrb->c->cibase[e->cioff].proc->body.irep;
|
||||
!MRB_PROC_CFUNC_P(e->cxt.c->cibase[e->cioff].proc)) {
|
||||
irep = e->cxt.c->cibase[e->cioff].proc->body.irep;
|
||||
if (irep->lv) {
|
||||
for (i = 0; i + 1 < irep->nlocals; ++i) {
|
||||
if (irep->lv[i].name) {
|
||||
|
||||
+1
-1
@@ -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);
|
||||
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->stack = mrb->c->stack;
|
||||
|
||||
|
||||
@@ -201,8 +201,8 @@ is_strict(mrb_state *mrb, struct REnv *e)
|
||||
{
|
||||
int cioff = e->cioff;
|
||||
|
||||
if (MRB_ENV_STACK_SHARED_P(e) && mrb->c->cibase[cioff].proc &&
|
||||
MRB_PROC_STRICT_P(mrb->c->cibase[cioff].proc)) {
|
||||
if (MRB_ENV_STACK_SHARED_P(e) && e->cxt.c->cibase[cioff].proc &&
|
||||
MRB_PROC_STRICT_P(e->cxt.c->cibase[cioff].proc)) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@@ -264,8 +264,9 @@ mrb_env_unshare(mrb_state *mrb, struct REnv *e)
|
||||
MRB_ENV_UNSHARE_STACK(e);
|
||||
if (!e->c) {
|
||||
/* 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);
|
||||
if (len > 0) {
|
||||
stack_copy(p, e->stack, len);
|
||||
@@ -1236,6 +1237,10 @@ RETRY_TRY_BLOCK:
|
||||
bidx = a+n+1;
|
||||
}
|
||||
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]);
|
||||
}
|
||||
else {
|
||||
@@ -1363,9 +1368,15 @@ RETRY_TRY_BLOCK:
|
||||
ci->target_class = m->target_class;
|
||||
ci->proc = m;
|
||||
if (m->env) {
|
||||
if (m->env->mid) {
|
||||
ci->mid = m->env->mid;
|
||||
mrb_sym 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) {
|
||||
m->env->stack = mrb->c->stack;
|
||||
}
|
||||
@@ -1990,7 +2001,8 @@ RETRY_TRY_BLOCK:
|
||||
if (lv == 0) stack = regs + 1;
|
||||
else {
|
||||
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);
|
||||
goto L_RAISE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user