gc.c (gc_gray_counts): unify the function with gc_mark_children

Avoid traversing object repeatedly.
This commit is contained in:
Yukihiro "Matz" Matsumoto
2024-03-14 11:44:06 +09:00
parent 2b597c596c
commit e8525df576
+38 -98
View File
@@ -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;