allow top-level GC to collect all garbage in GC_VISIT_V2
This commit is contained in:
parent
418a1c054f
commit
78eb351e10
2
src/h.h
2
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
|
||||
|
||||
18
src/main.c
18
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) {
|
||||
|
||||
39
src/opt/gc.c
39
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;
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user