From 6ae13b1c8678284cf6672681258ad58601163816 Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Tue, 19 Aug 2025 13:30:51 -0500 Subject: [PATCH] Add reference C code that I can hand compile --- reference/Makefile | 6 ++++ reference/gc.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++ reference/gc.h | 28 +++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 reference/Makefile create mode 100644 reference/gc.c create mode 100644 reference/gc.h diff --git a/reference/Makefile b/reference/Makefile new file mode 100644 index 0000000..92b7585 --- /dev/null +++ b/reference/Makefile @@ -0,0 +1,6 @@ +CFLAGS=-g + +all: gctest + +gctest: gc.o + $(CC) $(CFLAGS) -o $@ $< diff --git a/reference/gc.c b/reference/gc.c new file mode 100644 index 0000000..3c1ef91 --- /dev/null +++ b/reference/gc.c @@ -0,0 +1,88 @@ +// 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 +} + diff --git a/reference/gc.h b/reference/gc.h new file mode 100644 index 0000000..83bfc34 --- /dev/null +++ b/reference/gc.h @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +#define SIZE 8 +#define BROKEN_HEART 1 +#define CONS 2 +#define INTEGER 3 + +typedef struct box_t { + char type; + union { + int integer; + struct cons_t* cons; + }; +} box_t; + +typedef struct cons_t { + box_t car; + box_t cdr; +} cons_t; + +void init(); +cons_t *alloc(); +void gc_run(); +void gc_loop(); +void relocate(cons_t*);