From 38b9a25e83d2c71139e9cb07659dd9205da98fb4 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 26 Jun 2023 23:56:45 +0900 Subject: [PATCH] gc.c (mrb_obj_alloc): remove free_next,free_prev from heap pages It used to be maintain heap pages with allocatable objects (free_heaps) but we can save two words (16 bytes) per page by scanning live heap pages. --- include/mruby/gc.h | 3 --- src/gc.c | 48 ++++++++++------------------------------------ 2 files changed, 10 insertions(+), 41 deletions(-) diff --git a/include/mruby/gc.h b/include/mruby/gc.h index f7876e9a0..17280a19f 100644 --- a/include/mruby/gc.h +++ b/include/mruby/gc.h @@ -45,8 +45,6 @@ typedef struct mrb_heap_page { struct RBasic *freelist; struct mrb_heap_page *prev; struct mrb_heap_page *next; - struct mrb_heap_page *free_next; - struct mrb_heap_page *free_prev; mrb_bool old:1; /* Flexible array members area a C99 feature, not C++ compatible */ /* void* objects[]; */ @@ -59,7 +57,6 @@ typedef struct mrb_heap_page { typedef struct mrb_gc { mrb_heap_page *heaps; /* heaps for GC */ mrb_heap_page *sweeps; /* page where sweep starts */ - mrb_heap_page *free_heaps; struct RBasic *gray_list; /* list of gray objects to be traversed incrementally */ struct RBasic *atomic_gray_list; /* list of objects to be traversed atomically */ size_t live; /* count of live objects */ diff --git a/src/gc.c b/src/gc.c index 191f2f0ea..f84ddb641 100644 --- a/src/gc.c +++ b/src/gc.c @@ -309,29 +309,6 @@ unlink_heap_page(mrb_gc *gc, mrb_heap_page *page) page->next = NULL; } -static void -link_free_heap_page(mrb_gc *gc, mrb_heap_page *page) -{ - page->free_next = gc->free_heaps; - if (gc->free_heaps) { - gc->free_heaps->free_prev = page; - } - gc->free_heaps = page; -} - -static void -unlink_free_heap_page(mrb_gc *gc, mrb_heap_page *page) -{ - if (page->free_prev) - page->free_prev->free_next = page->free_next; - if (page->free_next) - page->free_next->free_prev = page->free_prev; - if (gc->free_heaps == page) - gc->free_heaps = page->free_next; - page->free_prev = NULL; - page->free_next = NULL; -} - static void add_heap(mrb_state *mrb, mrb_gc *gc) { @@ -347,7 +324,6 @@ add_heap(mrb_state *mrb, mrb_gc *gc) page->freelist = prev; link_heap_page(gc, page); - link_free_heap_page(gc, page); } #define DEFAULT_GC_INTERVAL_RATIO 200 @@ -368,7 +344,6 @@ mrb_gc_init(mrb_state *mrb, mrb_gc *gc) gc->current_white_part = GC_WHITE_A; gc->heaps = NULL; - gc->free_heaps = NULL; add_heap(mrb, gc); gc->interval_ratio = DEFAULT_GC_INTERVAL_RATIO; gc->step_ratio = DEFAULT_GC_STEP_RATIO; @@ -497,7 +472,6 @@ mrb_gc_unregister(mrb_state *mrb, mrb_value obj) MRB_API struct RBasic* mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) { - struct RBasic *p; static const RVALUE RVALUE_zero = { { { NULL, NULL, MRB_TT_FALSE } } }; mrb_gc *gc = &mrb->gc; @@ -534,15 +508,18 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) if (gc->threshold < gc->live) { mrb_incremental_gc(mrb); } - if (gc->free_heaps == NULL) { - add_heap(mrb, gc); - } - p = gc->free_heaps->freelist; - gc->free_heaps->freelist = ((struct free_obj*)p)->next; - if (gc->free_heaps->freelist == NULL) { - unlink_free_heap_page(gc, gc->free_heaps); + mrb_heap_page *page = gc->heaps; + struct RBasic *p = NULL; + while (page->freelist == NULL) { + page = page->next; + if (page == NULL) { + add_heap(mrb, gc); + page = gc->heaps; + } } + p = page->freelist; + page->freelist = ((struct free_obj*)p)->next; gc->live++; gc_protect(mrb, gc, p); @@ -1109,7 +1086,6 @@ incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) RVALUE *e = p + MRB_HEAP_PAGE_SIZE; size_t freed = 0; mrb_bool dead_slot = TRUE; - mrb_bool full = (page->freelist == NULL); if (is_minor_gc(gc) && page->old) { /* skip a slot which doesn't contain any young object */ @@ -1143,14 +1119,10 @@ incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) mrb_heap_page *next = page->next; unlink_heap_page(gc, page); - unlink_free_heap_page(gc, page); mrb_free(mrb, page); page = next; } else { - if (full && freed > 0) { - link_free_heap_page(gc, page); - } if (page->freelist == NULL && is_minor_gc(gc)) page->old = TRUE; else