allow top-level GC to collect all garbage in GC_VISIT_V2

This commit is contained in:
dzaima 2023-02-26 18:37:07 +02:00
parent 418a1c054f
commit 78eb351e10
4 changed files with 37 additions and 24 deletions

View File

@ -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_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 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 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 // some primitive actions
static const B bi_N = b((u64)0x7FF2000000000000ull); // tag(0,TAG_TAG); // make gcc happy static const B bi_N = b((u64)0x7FF2000000000000ull); // tag(0,TAG_TAG); // make gcc happy

View File

@ -624,7 +624,7 @@ void cbqn_runLine0(char* ln, i64 read) {
e->vars[i] = bi_noVar; e->vars[i] = bi_noVar;
dec(val); dec(val);
#if ENABLE_GC #if ENABLE_GC
if (!gc_depth) gc_forceGC(); if (!gc_depth) gc_forceGC(true);
#endif #endif
return; return;
} }
@ -665,15 +665,21 @@ void cbqn_runLine0(char* ln, i64 read) {
return; return;
} else if (isCmd(cmdS, &cmdE, "gc ")) { } else if (isCmd(cmdS, &cmdE, "gc ")) {
#if ENABLE_GC #if ENABLE_GC
bool toplevel = true;
if (0==*cmdE) { if (0==*cmdE) {
gc_now:;
if (gc_depth!=0) { if (gc_depth!=0) {
printf("GC is disabled, but forcibly GCing anyway\n"); printf("GC is disabled, but forcibly GCing anyway\n");
gc_enable(); u64 stored_depth = gc_depth;
gc_forceGC(); gc_depth = 0;
gc_disable(); gc_forceGC(toplevel);
gc_depth = stored_depth;
} else { } else {
gc_forceGC(); gc_forceGC(toplevel);
} }
} else if (strcmp(cmdE,"nontop")==0) {
toplevel = false;
goto gc_now;
} else if (strcmp(cmdE,"on")==0) { } else if (strcmp(cmdE,"on")==0) {
if (gc_depth==0) printf("GC already on\n"); if (gc_depth==0) printf("GC already on\n");
else if (gc_depth>1) printf("GC cannot be enabled\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 #ifdef HEAP_VERIFY
heapVerify(); heapVerify();
#endif #endif
gc_forceGC(); gc_forceGC(true);
} }
} }
if (startREPL) { if (startREPL) {

View File

@ -136,7 +136,10 @@ static void gc_tryFree(Value* v) {
gcv2_storeRemainingEnd(x); gcv2_storeRemainingEnd(x);
} }
static void gc_run() { static void gc_run(bool toplevel) {
if (toplevel) {
mm_forHeap(gc_resetTag);
} else {
visit_mode = GC_DEC_REFC; visit_mode = GC_DEC_REFC;
mm_forHeap(gcv2_visit); mm_forHeap(gcv2_visit);
@ -146,12 +149,16 @@ static void gc_tryFree(Value* v) {
visit_mode = GC_INC_REFC; visit_mode = GC_INC_REFC;
mm_forHeap(gcv2_visit); mm_forHeap(gcv2_visit);
}
visit_mode = GC_MARK; visit_mode = GC_MARK;
gc_visitRoots(); gc_visitRoots();
if (!toplevel) {
Value** c = gcv2_bufS; Value** c = gcv2_bufS;
while (c < gcv2_bufC) mm_visitP(*(c++)); while (c < gcv2_bufC) mm_visitP(*(c++));
free(gcv2_bufS); free(gcv2_bufS);
}
mm_forHeap(gc_tryFree); mm_forHeap(gc_tryFree);
mm_forHeap(gc_freeFreed); mm_forHeap(gc_freeFreed);
@ -166,7 +173,7 @@ static void gc_tryFree(Value* v) {
#endif #endif
u64 gc_lastAlloc; u64 gc_lastAlloc;
void gc_forceGC() { void gc_forceGC(bool toplevel) {
#if ENABLE_GC #if ENABLE_GC
#ifdef LOG_GC #ifdef LOG_GC
u64 start = nsTime(); u64 start = nsTime();
@ -175,7 +182,7 @@ void gc_forceGC() {
gc_unkRefsBytes = 0; gc_unkRefsCount = 0; gc_unkRefsBytes = 0; gc_unkRefsCount = 0;
u64 startSize = mm_heapUsed(); u64 startSize = mm_heapUsed();
#endif #endif
gc_run(); gc_run(toplevel);
u64 endSize = mm_heapUsed(); u64 endSize = mm_heapUsed();
#ifdef LOG_GC #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); 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; if (gc_depth) return false;
u64 used = mm_heapUsed(); u64 used = mm_heapUsed();
if (used > gc_lastAlloc*2) { if (used > gc_lastAlloc*2) {
gc_forceGC(); gc_forceGC(false);
return true; return true;
} }
return false; return false;

View File

@ -51,7 +51,7 @@ static NOINLINE void* BN(allocateMore)(i64 bucket, u8 type, i64 from, i64 to) {
if (mm_heapAlloc+sz >= mm_heapMax) { if (mm_heapAlloc+sz >= mm_heapMax) {
#if GC_VISIT_V2 #if GC_VISIT_V2
if (!BN(allocMore_rec)) { if (!BN(allocMore_rec)) {
gc_forceGC(); gc_forceGC(false);
BN(allocMore_rec) = true; BN(allocMore_rec) = true;
alloc_rec:; alloc_rec:;
void* r = BN(allocL)(bucket, type); void* r = BN(allocL)(bucket, type);