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.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/pit/src/runtime/gc.c b/pit/src/runtime/gc.c
index 7fd42fa..e7b9e8d 100644
--- a/pit/src/runtime/gc.c
+++ b/pit/src/runtime/gc.c
@@ -1,6 +1,7 @@
#include <lcq/pit/arena.h>
#include <lcq/pit/runtime/gc.h>
+/* copy a heavy value from fromspace to tospace, returning its new index */
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;
@@ -13,6 +14,8 @@ static i64 gc_copy(pit_runtime *rt, pit_value_heavy *h) {
return ret;
}
}
+/* copy some lisp value from fromspace to tospace, returning the new value */
+/* (this only changes heavy values, since they live on the heap) */
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);
@@ -29,6 +32,10 @@ static pit_value gc_copy_value(pit_runtime *rt, pit_value v) {
}
}
+/* collect garbage */
+/* this uses Cheney's algorithm: https://en.wikipedia.org/wiki/Cheney%27s_algorithm */
+/* note that only the symbol table, saved bindings, and VM state (code / value stacks) are roots */
+/* any pit_value saved elsewhere could be invalidated by garbage collection if it is unreachable! */
void pit_gc(pit_runtime *rt) {
rt->frozen_values = 0;
rt->frozen_symtab = 0;
@@ -115,6 +122,10 @@ void pit_gc(pit_runtime *rt) {
pit_hashtable_reset(pit_ref, pit_annotation)(rt->annotations_backbuffer);
}
+/* collect garbage if necessary. this is run between every instruction evaluation in the VM. */
+/* currently we use a simple heuristic: if the heap is using more than 80% of the available space */
+/* note that this is could be weird in a heap with very few heavy values but a lot of data (strings etc.) */
+/* TODO do research on better heuristics */
void pit_gc_if_necessary(pit_runtime *rt) {
if (pit_arena_byte_idx(rt->heap, rt->heap->next * 5) > rt->heap->back * 4) {
pit_gc(rt);