mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
GC must scan env from fibers even when it's not yet copied to heap; fix #3063
This commit is contained in:
@@ -27,6 +27,8 @@ struct REnv {
|
||||
#define MRB_ENV_UNSHARE_STACK(e) ((e)->cioff = -1)
|
||||
#define MRB_ENV_STACK_SHARED_P(e) ((e)->cioff >= 0)
|
||||
|
||||
MRB_API void mrb_env_unshare(mrb_state*, struct REnv*);
|
||||
|
||||
struct RProc {
|
||||
MRB_OBJECT_HEADER;
|
||||
union {
|
||||
|
||||
@@ -613,14 +613,11 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
case MRB_TT_ENV:
|
||||
{
|
||||
struct REnv *e = (struct REnv*)obj;
|
||||
mrb_int i, len;
|
||||
|
||||
if (!MRB_ENV_STACK_SHARED_P(e)) {
|
||||
mrb_int i, len;
|
||||
|
||||
len = MRB_ENV_STACK_LEN(e);
|
||||
for (i=0; i<len; i++) {
|
||||
mrb_gc_mark_value(mrb, e->stack[i]);
|
||||
}
|
||||
len = MRB_ENV_STACK_LEN(e);
|
||||
for (i=0; i<len; i++) {
|
||||
mrb_gc_mark_value(mrb, e->stack[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -725,9 +722,18 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
|
||||
case MRB_TT_FIBER:
|
||||
{
|
||||
struct mrb_context *c = ((struct RFiber*)obj)->cxt;
|
||||
if (c && c != mrb->root_c) {
|
||||
mrb_callinfo *ci = c->ci;
|
||||
mrb_callinfo *ce = c->cibase;
|
||||
|
||||
if (c != mrb->root_c)
|
||||
mrb_free_context(mrb, c);
|
||||
while (ce <= ci) {
|
||||
struct REnv *e = ci->env;
|
||||
if (e && !is_dead(&mrb->gc, e) && MRB_ENV_STACK_SHARED_P(e)) {
|
||||
mrb_env_unshare(mrb, e);
|
||||
}
|
||||
ci--;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -237,22 +237,27 @@ cipush(mrb_state *mrb)
|
||||
return ci;
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
mrb_env_unshare(mrb_state *mrb, struct REnv *e)
|
||||
{
|
||||
size_t len = (size_t)MRB_ENV_STACK_LEN(e);
|
||||
mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
|
||||
|
||||
MRB_ENV_UNSHARE_STACK(e);
|
||||
if (len > 0) {
|
||||
stack_copy(p, e->stack, len);
|
||||
}
|
||||
e->stack = p;
|
||||
mrb_write_barrier(mrb, (struct RBasic *)e);
|
||||
}
|
||||
|
||||
static void
|
||||
cipop(mrb_state *mrb)
|
||||
{
|
||||
struct mrb_context *c = mrb->c;
|
||||
|
||||
if (c->ci->env) {
|
||||
struct REnv *e = c->ci->env;
|
||||
size_t len = (size_t)MRB_ENV_STACK_LEN(e);
|
||||
mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
|
||||
|
||||
MRB_ENV_UNSHARE_STACK(e);
|
||||
if (len > 0) {
|
||||
stack_copy(p, e->stack, len);
|
||||
}
|
||||
e->stack = p;
|
||||
mrb_write_barrier(mrb, (struct RBasic *)e);
|
||||
mrb_env_unshare(mrb, c->ci->env);
|
||||
}
|
||||
|
||||
c->ci--;
|
||||
|
||||
Reference in New Issue
Block a user