// Cheney style stop and copy garbage collector #include "gc.h" static cons_t *old, *new, *scanptr, *freeptr, *eom, *root; static cons_t *the_empty_list = NULL; size_t tos; void init() { old = calloc(sizeof(cons_t), SIZE); freeptr = old; eom = old + (SIZE / 2); new = eom + 1; root = alloc(); } cons_t *alloc() { if (freeptr < eom) { cons_t *retval = freeptr; freeptr++; return retval; } else { gc_run(); return alloc(); } } void gc_run() { freeptr = new; scanptr = new; // Relocate root relocate(root); // Enter the main GC loop gc_loop(); // Flip old and new; cons_t *temp = old; old = new; new = temp; } void gc_loop() { while (scanptr < freeptr) { relocate(scanptr); scanptr++; } } void move(box_t box) { if (box.type == CONS && box.cons != the_empty_list) { if (box.cons->car.type == BROKEN_HEART) { box.cons = box.cons->cdr.cons; } else { memcpy(freeptr, box.cons, sizeof(cons_t)); box.cons->car.type = BROKEN_HEART; box.cons->cdr.cons = freeptr; freeptr++; } } } void relocate(cons_t* cons) { move(cons->car); move(cons->cdr); } int main() { init(); // Simulate running linear fibonnaci root->car.type = INTEGER; root->car.integer = 1; root->cdr.type = CONS; root->cdr.cons = alloc(); root->cdr.cons->car.type = INTEGER; root->cdr.cons->car.integer = 0; root->cdr.cons->cdr.type = CONS; root->cdr.cons->cdr.cons = the_empty_list; for (size_t i = 0; i < 29; i++) { cons_t *cons = alloc(); cons->car.type = INTEGER; cons->car.integer = root->car.integer + root->cdr.cons->car.integer; cons->cdr.type = CONS; cons->cdr.cons = root; root->cdr.cons = the_empty_list; root = cons; }; printf("%d\n", root->car.integer); // 832040, and we've definitely run gc a few times }