diff --git a/gc.c b/gc.c new file mode 100644 index 0000000..c9bcad4 --- /dev/null +++ b/gc.c @@ -0,0 +1,45 @@ +#include + +#include "gc.h" +#include "vm.h" + +void mark(struct garbageObject *obj) { + if (obj->mark) return; + + ++obj->mark; + + if (obj->type == GARBAGE_PAIR) { + mark(obj->head); + mark(obj->tail); + } +} + +void markAll(struct virtualMachine *vm) { + for (int i = 0; i < vm->stackSize; ++i) { + mark(vm->stack[i]); + } +} + +void sweep(struct virtualMachine *vm) { + struct garbageObject **obj = &vm->head; + + while (*obj) { + if (!(*obj)->mark) { + struct garbageObject *unreachable = *obj; + *obj = unreachable->next; + free(unreachable); + vm->refCount--; + } else { + (*obj)->mark = 0; + obj = &(*obj)->next; + } + } +} + +int collect(struct virtualMachine *vm) { + int count = vm->refCount; + markAll(vm); + sweep(vm); + vm->refMax = vm->refCount * 2; + return count - vm->refCount; +} diff --git a/gc.h b/gc.h index 9a05678..f2320dc 100644 --- a/gc.h +++ b/gc.h @@ -1,6 +1,8 @@ #ifndef GC_H #define GC_H +#include "vm.h" + // Marks a single reference if it is still in use void mark(struct garbageObject *obj); @@ -11,6 +13,6 @@ void markAll(struct virtualMachine *vm); void sweep(struct virtualMachine *vm); // Marks and Sweeps all references -void collect(struct virtualMachine *vm); +int collect(struct virtualMachine *vm); #endif /* GC_H */