diff --git a/src/gc.c b/src/gc.c index a2f4f75..49a2a34 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1,5 +1,6 @@ #include #include +#include #include "alloc.h" #include "bytecode.h" @@ -9,7 +10,10 @@ #include "scope.h" #include "value.h" -#define DEBUG_GC 1 +// #define GC_DEBUG_COLLECT_EVERY_ALLOCATION 1 +// #define GC_DEBUG_STATS 1 +// #define GC_DEBUG_WIPE_RECLAIMED_OBJECTS 1 +// #define GC_DEBUG_DUMP_GRAPH_ON_COLLECT 1 struct gc_object { // Unlike most other tagged unions in apfl, the union is first here. @@ -42,6 +46,12 @@ gc_allocator(void *opaque, void *oldptr, size_t oldsize, size_t newsize) { struct gc *gc = opaque; + #ifdef GC_DEBUG_COLLECT_EVERY_ALLOCATION + if (newsize != 0 && !gc->is_collecting) { + apfl_gc_full(gc); + } + #endif + void *out = ALLOCATOR_CALL(gc->base_allocator, oldptr, oldsize, newsize); if (newsize != 0 && out == NULL && !gc->is_collecting) { // We're out of memory! Try to get out of this situation by doing a full @@ -337,6 +347,11 @@ deinit_object(struct gc *gc, struct gc_object *object) static void sweep(struct gc *gc) { + #ifdef GC_DEBUG_STATS + int reclaimed_objects = 0; + int reclaimed_blocks = 0; + #endif + struct gc_block **cur = &gc->block; while (*cur != NULL) { struct gc_block *block = *cur; @@ -350,7 +365,18 @@ sweep(struct gc *gc) break; case GC_STATUS_WHITE: deinit_object(gc, object); + + #ifdef GC_DEBUG_WIPE_RECLAIMED_OBJECTS + memset(object, 0, sizeof(struct gc_object)); + object->type = 0xFF; // Some intentionally undefined type + #endif + object->status = GC_STATUS_FREE; + + #ifdef GC_DEBUG_STATS + reclaimed_objects++; + #endif + break; case GC_STATUS_GREY: assert(false /*Encountered grey object while sweeping*/); @@ -365,12 +391,26 @@ sweep(struct gc *gc) if (completely_free) { *cur = block->next; FREE_OBJ(gc->allocator, block); + + #ifdef GC_DEBUG_STATS + reclaimed_blocks++; + #endif } else { cur = &block->next; } } + + #ifdef GC_DEBUG_STATS + fprintf(stderr, "gc: reclaimed %d objects, %d blocks\n", reclaimed_objects, reclaimed_blocks); + #endif } +#ifdef GC_DEBUG_DUMP_GRAPH_ON_COLLECT +# define DUMP_ON_COLLECT() apfl_gc_debug_dump_graph(gc, stderr) +#else +# define DUMP_ON_COLLECT() +#endif + void apfl_gc_full(struct gc *gc) { @@ -378,11 +418,11 @@ apfl_gc_full(struct gc *gc) gc->is_collecting = true; mark_roots(gc); - apfl_gc_debug_dump_graph(gc, stderr); + DUMP_ON_COLLECT(); trace_while_having_grey(gc); - apfl_gc_debug_dump_graph(gc, stderr); + DUMP_ON_COLLECT(); sweep(gc); - apfl_gc_debug_dump_graph(gc, stderr); + DUMP_ON_COLLECT(); gc->is_collecting = false; }