summaryrefslogtreecommitdiff
path: root/pit/src/runtime/gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'pit/src/runtime/gc.c')
-rw-r--r--pit/src/runtime/gc.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/pit/src/runtime/gc.c b/pit/src/runtime/gc.c
index 0880592..1cc6547 100644
--- a/pit/src/runtime/gc.c
+++ b/pit/src/runtime/gc.c
@@ -37,6 +37,17 @@ void pit_gc(pit_runtime *rt) {
pit_arena_reset(tospace);
pit_hashtable_reset(pit_ref, pit_annotation)(tospace_ann);
/* populate tospace with immediately reachable values */
+ /* any values saved directly to the runtime are reachable */
+ rt->msg_out_of_memory = gc_copy_value(rt, rt->msg_out_of_memory);
+ /* everything on the call stack is reachable */
+ for (i64 i = 0; i < rt->callstack->next; ++i) {
+ pit_callstack_entry *ent = pit_vec_get(pit_callstack_entry)(rt->callstack, i);
+ if (ent == NULL) continue; /* TODO warn on failure here? */
+ ent->tag = gc_copy_value(rt, ent->tag);
+ ent->bound = gc_copy_value(rt, ent->bound);
+ ent->code = gc_copy_value(rt, ent->code);
+ }
+ /* the symbol table is reachable */
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? */
@@ -44,10 +55,12 @@ void pit_gc(pit_runtime *rt) {
ent->value = gc_copy_value(rt, ent->value);
ent->function = gc_copy_value(rt, ent->function);
}
+ /* all saved bindings are reachable */
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? */
}
+ /* recursively populate all reachable values from that initial set */
for (i64 scan = 0; scan < tospace->next; ++scan) {
pit_value_heavy *h = pit_arena_get(tospace, scan);
switch (h->hsort) {