~brenns10/funlisp

ref: 7347d0eca6d0a50799d3048c21f376277e827224 funlisp/src/gc.c -rw-r--r-- 1.2 KiB
7347d0ecStephen Brennan Updates for readthedocs 3 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
 * gc.c: mark and sweep garbage collection for funlisp
 *
 * Stephen Brennan <stephen@brennan.io>
 */
#include <assert.h>

#include "funlisp_internal.h"

void lisp_init(lisp_runtime *rt)
{
	rt->nil = type_list->new();
	rt->nil->mark = 0;
	rt->nil->type = type_list;
	rt->nil->next = NULL;
	rt->head = rt->nil;
	rt->tail = rt->nil;
	rb_init(&rt->rb, sizeof(lisp_value*), 16);
}

void lisp_destroy(lisp_runtime *rt)
{
	lisp_sweep(rt);
	rb_destroy(&rt->rb);
	lisp_free(rt->nil);
}

void lisp_mark(lisp_runtime *rt, lisp_value *v)
{
	rb_push_back(&rt->rb, &v);

	while (rt->rb.count > 0) {
		rb_pop_front(&rt->rb, &v);
		v->mark = GC_MARKED;
		struct iterator it = v->type->expand(v);
		while (it.has_next(&it)) {
			v = it.next(&it);
			if (v->mark == GC_NOMARK) {
				v->mark = GC_QUEUED;
				rb_push_back(&rt->rb, &v);
			}
		}
		it.close(&it);
	}
}

void lisp_sweep(lisp_runtime *rt)
{
	lisp_value *curr = rt->head;

	while (curr->next) {
		if (curr->next->mark != GC_MARKED) {
			lisp_value *tmp = curr->next->next;
			lisp_free(curr->next);
			curr->next = tmp;
		} else {
			curr->mark = GC_NOMARK;
			curr = curr->next;
		}
	}

	curr->mark = GC_NOMARK;
	rt->tail = curr;
}