mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
gc.c (gc_gray_counts): unify the function with gc_mark_children
Avoid traversing object repeatedly.
This commit is contained in:
@@ -576,9 +576,11 @@ mark_context(mrb_state *mrb, struct mrb_context *c)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static size_t
|
||||
gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
{
|
||||
size_t children = 0;
|
||||
|
||||
mrb_assert(is_gray(obj));
|
||||
paint_black(obj);
|
||||
mrb_gc_mark(mrb, (struct RBasic*)obj->c);
|
||||
@@ -589,6 +591,7 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
if (MRB_FLAG_TEST(c, MRB_FL_CLASS_IS_ORIGIN))
|
||||
mrb_gc_mark_mt(mrb, c);
|
||||
mrb_gc_mark(mrb, (struct RBasic*)((struct RClass*)obj)->super);
|
||||
children++;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -600,12 +603,15 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
|
||||
mrb_gc_mark_mt(mrb, c);
|
||||
mrb_gc_mark(mrb, (struct RBasic*)c->super);
|
||||
children += mrb_gc_mark_mt_size(mrb, c);
|
||||
children++;
|
||||
}
|
||||
/* fall through */
|
||||
|
||||
case MRB_TT_OBJECT:
|
||||
case MRB_TT_CDATA:
|
||||
mrb_gc_mark_iv(mrb, (struct RObject*)obj);
|
||||
children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
|
||||
break;
|
||||
|
||||
case MRB_TT_PROC:
|
||||
@@ -614,6 +620,7 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
|
||||
mrb_gc_mark(mrb, (struct RBasic*)p->upper);
|
||||
mrb_gc_mark(mrb, (struct RBasic*)p->e.env);
|
||||
children+=2;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -628,6 +635,7 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
for (mrb_int i=0; i<len; i++) {
|
||||
mrb_gc_mark_value(mrb, e->stack[i]);
|
||||
}
|
||||
children += len;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -635,7 +643,20 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
{
|
||||
struct mrb_context *c = ((struct RFiber*)obj)->cxt;
|
||||
|
||||
if (c) mark_context(mrb, c);
|
||||
if (!c || c->status == MRB_FIBER_TERMINATED) break;
|
||||
mark_context(mrb, c);
|
||||
if (!c->ci) break;
|
||||
|
||||
/* mark stack */
|
||||
size_t i = c->ci->stack - c->stbase;
|
||||
i += mrb_ci_nregs(c->ci);
|
||||
if (c->stbase + i > c->stend) i = c->stend - c->stbase;
|
||||
children += i;
|
||||
|
||||
/* mark closure */
|
||||
if (c->cibase) {
|
||||
children += c->ci - c->cibase + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -643,18 +664,21 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
case MRB_TT_ARRAY:
|
||||
{
|
||||
struct RArray *a = (struct RArray*)obj;
|
||||
size_t e=ARY_LEN(a);
|
||||
size_t len = ARY_LEN(a);
|
||||
mrb_value *p = ARY_PTR(a);
|
||||
|
||||
for (size_t i=0; i<e; i++) {
|
||||
for (size_t i=0; i<len; i++) {
|
||||
mrb_gc_mark_value(mrb, p[i]);
|
||||
}
|
||||
children += len;
|
||||
}
|
||||
break;
|
||||
|
||||
case MRB_TT_HASH:
|
||||
mrb_gc_mark_iv(mrb, (struct RObject*)obj);
|
||||
mrb_gc_mark_hash(mrb, (struct RHash*)obj);
|
||||
children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
|
||||
children += mrb_gc_mark_hash_size(mrb, (struct RHash*)obj);
|
||||
break;
|
||||
|
||||
case MRB_TT_STRING:
|
||||
@@ -666,12 +690,14 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
|
||||
case MRB_TT_RANGE:
|
||||
mrb_gc_mark_range(mrb, (struct RRange*)obj);
|
||||
children+=2;
|
||||
break;
|
||||
|
||||
case MRB_TT_BREAK:
|
||||
{
|
||||
struct RBreak *brk = (struct RBreak*)obj;
|
||||
mrb_gc_mark_value(mrb, mrb_break_value_get(brk));
|
||||
children++;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -679,13 +705,20 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
mrb_gc_mark_iv(mrb, (struct RObject*)obj);
|
||||
if (((struct RException*)obj)->mesg) {
|
||||
mrb_gc_mark(mrb, (struct RBasic*)((struct RException*)obj)->mesg);
|
||||
children++;
|
||||
}
|
||||
mrb_gc_mark(mrb, (struct RBasic*)((struct RException*)obj)->backtrace);
|
||||
children++;
|
||||
break;
|
||||
|
||||
case MRB_TT_BACKTRACE:
|
||||
children += ((struct RBacktrace*)obj)->len;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
@@ -890,98 +923,6 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc)
|
||||
}
|
||||
}
|
||||
|
||||
/* rough estimation of number of GC marks (non recursive) */
|
||||
static size_t
|
||||
gc_gray_counts(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
{
|
||||
size_t children = 0;
|
||||
|
||||
switch (obj->tt) {
|
||||
case MRB_TT_ICLASS:
|
||||
children++;
|
||||
break;
|
||||
|
||||
case MRB_TT_CLASS:
|
||||
case MRB_TT_SCLASS:
|
||||
case MRB_TT_MODULE:
|
||||
{
|
||||
struct RClass *c = (struct RClass*)obj;
|
||||
|
||||
children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
|
||||
children += mrb_gc_mark_mt_size(mrb, c);
|
||||
children++;
|
||||
}
|
||||
break;
|
||||
|
||||
case MRB_TT_OBJECT:
|
||||
case MRB_TT_CDATA:
|
||||
children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
|
||||
break;
|
||||
|
||||
case MRB_TT_ENV:
|
||||
children += MRB_ENV_LEN(obj);
|
||||
break;
|
||||
|
||||
case MRB_TT_FIBER:
|
||||
{
|
||||
struct mrb_context *c = ((struct RFiber*)obj)->cxt;
|
||||
size_t i;
|
||||
|
||||
if (!c || c->status == MRB_FIBER_TERMINATED) break;
|
||||
if (!c->ci) break;
|
||||
|
||||
/* mark stack */
|
||||
i = c->ci->stack - c->stbase;
|
||||
i += mrb_ci_nregs(c->ci);
|
||||
if (c->stbase + i > c->stend) i = c->stend - c->stbase;
|
||||
children += i;
|
||||
|
||||
/* mark closure */
|
||||
if (c->cibase) {
|
||||
children += c->ci - c->cibase + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MRB_TT_STRUCT:
|
||||
case MRB_TT_ARRAY:
|
||||
{
|
||||
struct RArray *a = (struct RArray*)obj;
|
||||
children += ARY_LEN(a);
|
||||
}
|
||||
break;
|
||||
|
||||
case MRB_TT_HASH:
|
||||
children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
|
||||
children += mrb_gc_mark_hash_size(mrb, (struct RHash*)obj);
|
||||
break;
|
||||
|
||||
case MRB_TT_PROC:
|
||||
case MRB_TT_RANGE:
|
||||
case MRB_TT_BREAK:
|
||||
children+=2;
|
||||
break;
|
||||
|
||||
case MRB_TT_EXCEPTION:
|
||||
children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
|
||||
if (((struct RException*)obj)->mesg) {
|
||||
children++;
|
||||
}
|
||||
if (((struct RException*)obj)->backtrace) {
|
||||
children++;
|
||||
}
|
||||
break;
|
||||
|
||||
case MRB_TT_BACKTRACE:
|
||||
children += ((struct RBacktrace*)obj)->len;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
static void
|
||||
gc_mark_gray_list(mrb_state *mrb, mrb_gc *gc) {
|
||||
while (gc->gray_list) {
|
||||
@@ -1001,8 +942,7 @@ incremental_marking_phase(mrb_state *mrb, mrb_gc *gc, size_t limit)
|
||||
struct RBasic *obj = gc->gray_list;
|
||||
gc->gray_list = obj->gcnext;
|
||||
obj->gcnext = NULL;
|
||||
gc_mark_children(mrb, gc, obj);
|
||||
tried_marks += gc_gray_counts(mrb, gc, obj);
|
||||
tried_marks += gc_mark_children(mrb, gc, obj);
|
||||
}
|
||||
|
||||
return tried_marks;
|
||||
|
||||
Reference in New Issue
Block a user