From e8525df576ac7acf6cc85bf2af1c4bcc0f8fb871 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 14 Mar 2024 11:44:06 +0900 Subject: [PATCH] gc.c (gc_gray_counts): unify the function with gc_mark_children Avoid traversing object repeatedly. --- src/gc.c | 136 ++++++++++++++++--------------------------------------- 1 file changed, 38 insertions(+), 98 deletions(-) diff --git a/src/gc.c b/src/gc.c index 5f8da87bb..5434bd0d0 100644 --- a/src/gc.c +++ b/src/gc.c @@ -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; istack[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; imesg) { 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;