gc: Add some optional debugging features

This commit is contained in:
Laria 2022-07-15 21:56:30 +02:00
parent 7e592cdb96
commit 55fb3c6345

View file

@ -1,5 +1,6 @@
#include <assert.h>
#include <stdio.h>
#include <string.h>
#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;
}