From 78eb351e10de416be371ecd4377ac3fd7c67c2cb Mon Sep 17 00:00:00 2001 From: dzaima Date: Sun, 26 Feb 2023 18:37:07 +0200 Subject: [PATCH] allow top-level GC to collect all garbage in GC_VISIT_V2 --- src/h.h | 2 +- src/main.c | 18 ++++++++++++------ src/opt/gc.c | 39 ++++++++++++++++++++++---------------- src/opt/mm_buddyTemplate.c | 2 +- 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/h.h b/src/h.h index c666e504..8dc3eca3 100644 --- a/src/h.h +++ b/src/h.h @@ -356,7 +356,7 @@ void gc_add(B x); // add permanent root object void gc_addFn(vfn f); // add function that calls mm_visit/mm_visitP for dynamic roots void gc_add_ref(B* x); // add x as a root reference bool gc_maybeGC(void); // gc if that seems necessary; returns if did gc -void gc_forceGC(void); // force a gc; who knows what happens if gc is disabled (probably should error) +void gc_forceGC(bool toplevel); // force a gc; who knows what happens if gc is disabled (probably should error) // some primitive actions static const B bi_N = b((u64)0x7FF2000000000000ull); // tag(0,TAG_TAG); // make gcc happy diff --git a/src/main.c b/src/main.c index ef2745e5..d624102f 100644 --- a/src/main.c +++ b/src/main.c @@ -624,7 +624,7 @@ void cbqn_runLine0(char* ln, i64 read) { e->vars[i] = bi_noVar; dec(val); #if ENABLE_GC - if (!gc_depth) gc_forceGC(); + if (!gc_depth) gc_forceGC(true); #endif return; } @@ -665,15 +665,21 @@ void cbqn_runLine0(char* ln, i64 read) { return; } else if (isCmd(cmdS, &cmdE, "gc ")) { #if ENABLE_GC + bool toplevel = true; if (0==*cmdE) { + gc_now:; if (gc_depth!=0) { printf("GC is disabled, but forcibly GCing anyway\n"); - gc_enable(); - gc_forceGC(); - gc_disable(); + u64 stored_depth = gc_depth; + gc_depth = 0; + gc_forceGC(toplevel); + gc_depth = stored_depth; } else { - gc_forceGC(); + gc_forceGC(toplevel); } + } else if (strcmp(cmdE,"nontop")==0) { + toplevel = false; + goto gc_now; } else if (strcmp(cmdE,"on")==0) { if (gc_depth==0) printf("GC already on\n"); else if (gc_depth>1) printf("GC cannot be enabled\n"); @@ -935,7 +941,7 @@ int main(int argc, char* argv[]) { #ifdef HEAP_VERIFY heapVerify(); #endif - gc_forceGC(); + gc_forceGC(true); } } if (startREPL) { diff --git a/src/opt/gc.c b/src/opt/gc.c index 1ba1e0a5..65be87c6 100644 --- a/src/opt/gc.c +++ b/src/opt/gc.c @@ -136,22 +136,29 @@ static void gc_tryFree(Value* v) { gcv2_storeRemainingEnd(x); } - static void gc_run() { - visit_mode = GC_DEC_REFC; - mm_forHeap(gcv2_visit); - - gcv2_bufS = gcv2_bufC = malloc(1<<20); - gcv2_bufE = gcv2_bufS + ((1<<20) / sizeof(Value*)); - mm_forHeap(gcv2_storeRemaining); // incl. unmark - - visit_mode = GC_INC_REFC; - mm_forHeap(gcv2_visit); + static void gc_run(bool toplevel) { + if (toplevel) { + mm_forHeap(gc_resetTag); + } else { + visit_mode = GC_DEC_REFC; + mm_forHeap(gcv2_visit); + + gcv2_bufS = gcv2_bufC = malloc(1<<20); + gcv2_bufE = gcv2_bufS + ((1<<20) / sizeof(Value*)); + mm_forHeap(gcv2_storeRemaining); // incl. unmark + + visit_mode = GC_INC_REFC; + mm_forHeap(gcv2_visit); + } visit_mode = GC_MARK; gc_visitRoots(); - Value** c = gcv2_bufS; - while (c < gcv2_bufC) mm_visitP(*(c++)); - free(gcv2_bufS); + + if (!toplevel) { + Value** c = gcv2_bufS; + while (c < gcv2_bufC) mm_visitP(*(c++)); + free(gcv2_bufS); + } mm_forHeap(gc_tryFree); mm_forHeap(gc_freeFreed); @@ -166,7 +173,7 @@ static void gc_tryFree(Value* v) { #endif u64 gc_lastAlloc; -void gc_forceGC() { +void gc_forceGC(bool toplevel) { #if ENABLE_GC #ifdef LOG_GC u64 start = nsTime(); @@ -175,7 +182,7 @@ void gc_forceGC() { gc_unkRefsBytes = 0; gc_unkRefsCount = 0; u64 startSize = mm_heapUsed(); #endif - gc_run(); + gc_run(toplevel); u64 endSize = mm_heapUsed(); #ifdef LOG_GC fprintf(stderr, "GC kept "N64d"B/"N64d" objs, freed "N64d"B, incl. directly "N64d"B/"N64d" objs", gc_visitBytes, gc_visitCount, startSize-endSize, gc_freedBytes, gc_freedCount); @@ -193,7 +200,7 @@ bool gc_maybeGC() { if (gc_depth) return false; u64 used = mm_heapUsed(); if (used > gc_lastAlloc*2) { - gc_forceGC(); + gc_forceGC(false); return true; } return false; diff --git a/src/opt/mm_buddyTemplate.c b/src/opt/mm_buddyTemplate.c index 7f0a2d3d..e34b610f 100644 --- a/src/opt/mm_buddyTemplate.c +++ b/src/opt/mm_buddyTemplate.c @@ -51,7 +51,7 @@ static NOINLINE void* BN(allocateMore)(i64 bucket, u8 type, i64 from, i64 to) { if (mm_heapAlloc+sz >= mm_heapMax) { #if GC_VISIT_V2 if (!BN(allocMore_rec)) { - gc_forceGC(); + gc_forceGC(false); BN(allocMore_rec) = true; alloc_rec:; void* r = BN(allocL)(bucket, type);