aboutsummaryrefslogtreecommitdiff
path: root/runtime/src/shed/gc.c
blob: dd31318d380e6c3ee8688a26d80cbdf881300d13 (plain)
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
#include <stdbool.h>

#include "./gc.h"
#include "./primitives.h"
#include "./std/unistd.h"

// == GC objects ==

bool shed__runtime__gc_is_gc_object(ShedObject object) {
    // Check that the object is not one of:
    // * unit (0)
    // * false (0)
    // * true (1)
    return !(object == 0 || object == 1);
}

// == Roots ==

ShedGcRootIndex shed__runtime__gc_root_stack_index = 0;

enum {
    GC_ROOT_STACK_SIZE = 16384,
};

struct ShedGcObjectHeader* shed__runtime__gc_root_stack[GC_ROOT_STACK_SIZE];

ShedGcRootIndex shed__runtime__gc_get_root_stack_index() {
    return shed__runtime__gc_root_stack_index;
}

void shed__runtime__gc_set_root_stack_index(ShedGcRootIndex new_shed__runtime__gc_root_stack_index) {
    shed__runtime__gc_root_stack_index = new_shed__runtime__gc_root_stack_index;
}

void shed__runtime__gc_push_root_gc_object(struct ShedGcObjectHeader* gc_root) {
    shed__runtime__gc_root_stack[shed__runtime__gc_root_stack_index] = gc_root;
    shed__runtime__gc_root_stack_index++;
}

void shed__runtime__gc_push_root(ShedObject gc_root) {
    if (!shed__runtime__gc_is_gc_object(gc_root)) {
        return;
    }

    shed__runtime__gc_push_root_gc_object((struct ShedGcObjectHeader*) gc_root);
}

// == Clearing ==

void shed__runtime__gc_clear_roots(void) {
    // Clearing all roots allows valgrind to detect leaks.
    for (size_t gc_root_index = 0; gc_root_index < GC_ROOT_STACK_SIZE; gc_root_index++) {
        shed__runtime__gc_root_stack[gc_root_index] = NULL;
    }
}