gc: Add some optional debugging features
This commit is contained in:
parent
7e592cdb96
commit
55fb3c6345
1 changed files with 44 additions and 4 deletions
48
src/gc.c
48
src/gc.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue