summaryrefslogtreecommitdiff
path: root/src/runtime/gc.c
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2026-06-30 14:30:19 -0400
committerLLLL Colonq <llll@colonq>2026-06-30 14:30:19 -0400
commit1c028e3a2250a56eface56ebbb1835d77e4e2579 (patch)
tree98ea5da9d75e87f44bb3eb2e153810a6a820f9b6 /src/runtime/gc.c
parent1d4447bcd888dd0bd20cf4b6dd7f9192145debf0 (diff)
Big refactorHEADmaster
Diffstat (limited to 'src/runtime/gc.c')
-rw-r--r--src/runtime/gc.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/runtime/gc.c b/src/runtime/gc.c
new file mode 100644
index 0000000..fcb5f89
--- /dev/null
+++ b/src/runtime/gc.c
@@ -0,0 +1,100 @@
+#include <lcq/pit/runtime/gc.h>
+
+static i64 gc_copy(pit_runtime *rt, pit_value_heavy *h) {
+ if (h->hsort == PIT_VALUE_HEAVY_SORT_FORWARDING_POINTER) {
+ return h->in.forwarding_pointer;
+ } else {
+ i64 ret = rt->backbuffer->next;
+ pit_value_heavy *g = pit_arena_alloc(rt->backbuffer);
+ *g = *h;
+ h->hsort = PIT_VALUE_HEAVY_SORT_FORWARDING_POINTER;
+ h->in.forwarding_pointer = ret;
+ return ret;
+ }
+}
+static pit_value gc_copy_value(pit_runtime *rt, pit_value v) {
+ if (pit_value_sort(v) == PIT_VALUE_SORT_REF) {
+ pit_ref r = pit_value_as_ref(rt, v);
+ pit_value_heavy *h = pit_value_ref_deref(rt, r);
+ i64 new = gc_copy(rt, h);
+ pit_annotated_ref *ann = pit_annotation_get(rt, r);
+ if (ann != NULL) {
+ pit_annotated_ref newann = *ann;
+ newann.ref = new;
+ if (pit_vec_push(pit_annotated_ref)(rt->backtrace, newann) < 0)
+ pit_error(rt, "annotation overflow");
+ }
+ return pit_value_ref_new(rt, new);
+ } else {
+ return v;
+ }
+}
+void pit_gc(pit_runtime *rt) {
+ rt->frozen_values = 0;
+ rt->frozen_symtab = 0;
+ pit_arena *fromspace = rt->heap;
+ pit_arena *tospace = rt->backbuffer;
+ pit_vec(pit_annotated_ref) *fromspace_ann = rt->annotations;
+ pit_vec(pit_annotated_ref) *tospace_ann = rt->backtrace;
+ pit_arena_reset(tospace);
+ pit_vec_reset(pit_annotated_ref)(tospace_ann);
+ /* populate tospace with immediately reachable values */
+ for (i64 i = 0; i < rt->symtab->next; ++i) {
+ pit_symtab_entry *ent = pit_vec_get(pit_symtab_entry)(rt->symtab, i);
+ if (ent == NULL) continue; /* TODO warn on failure here? */
+ ent->name = gc_copy_value(rt, ent->name);
+ ent->value = gc_copy_value(rt, ent->value);
+ ent->function = gc_copy_value(rt, ent->function);
+ }
+ for (i64 i = 0; i < rt->saved_bindings->next; ++i) {
+ pit_value *v = pit_vec_get(pit_value)(rt->saved_bindings, i);
+ if (v != NULL) *v = gc_copy_value(rt, *v); /* TODO warn on failure here? */
+ }
+ for (i64 scan = 0; scan < tospace->next; ++scan) {
+ pit_value_heavy *h = pit_arena_get(tospace, scan);
+ switch (h->hsort) {
+ case PIT_VALUE_HEAVY_SORT_CELL:
+ h->in.cell = gc_copy_value(rt, h->in.cell);
+ break;
+ case PIT_VALUE_HEAVY_SORT_CONS:
+ h->in.cons.car = gc_copy_value(rt, h->in.cons.car);
+ h->in.cons.cdr = gc_copy_value(rt, h->in.cons.cdr);
+ break;
+ case PIT_VALUE_HEAVY_SORT_ARRAY: {
+ i64 byte_len = 0; pit_mul(&byte_len, sizeof(pit_value), h->in.array.len);
+ pit_value *data = pit_arena_alloc_back(tospace, byte_len);
+ for (i64 i = 0; i < h->in.array.len; ++i) {
+ data[i] = gc_copy_value(rt, h->in.array.data[i]);
+ }
+ h->in.array.data = data;
+ break;
+ }
+ case PIT_VALUE_HEAVY_SORT_BYTES: {
+ u8 *data = pit_arena_alloc_back(tospace, h->in.bytes.len);
+ for (i64 i = 0; i < h->in.bytes.len; ++i) {
+ data[i] = h->in.bytes.data[i];
+ }
+ h->in.bytes.data = data;
+ break;
+ }
+ case PIT_VALUE_HEAVY_SORT_FUNC:
+ h->in.func.env = gc_copy_value(rt, h->in.func.env);
+ h->in.func.args = gc_copy_value(rt, h->in.func.args);
+ h->in.func.arg_rest_nm = gc_copy_value(rt, h->in.func.arg_rest_nm);
+ h->in.func.body = gc_copy_value(rt, h->in.func.body);
+ break;
+ case PIT_VALUE_HEAVY_SORT_NATIVEFUNC: break;
+ case PIT_VALUE_HEAVY_SORT_NATIVEDATA:
+ h->in.nativedata.tag = gc_copy_value(rt, h->in.nativedata.tag);
+ break;
+ case PIT_VALUE_HEAVY_SORT_FORWARDING_POINTER:
+ pit_error(rt, "garbage collection broken! encountered forwarding pointer in to-space");
+ break;
+ }
+ }
+ rt->heap = tospace;
+ rt->backbuffer = fromspace;
+ rt->annotations = tospace_ann;
+ rt->backtrace = fromspace_ann;
+ pit_vec_reset(pit_annotated_ref)(rt->backtrace);
+}