aboutsummaryrefslogtreecommitdiffstats
path: root/src/bootstrap/gc.c
blob: fff420177094e8b4e3f08a4e718b6f27d74b374c (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
typedef struct GC {
    Object *obj_list;
    // Free list keeps track of the offset numbers from the obj_list
    size_t *free_list;
    size_t obj_size;
    size_t obj_cap;
    size_t fl_pos;
    size_t available_slots;
} GC;

// FIXME: small value for testing purposes
#define GC_INITIAL_HEAP 100000

static GC gc;

void
init_gc(void) {
    gc = (GC){
        .obj_cap = GC_INITIAL_HEAP,
        .available_slots = GC_INITIAL_HEAP,
    };
    gc.free_list = malloc(GC_INITIAL_HEAP * sizeof(size_t *));
    gc.obj_list = malloc(GC_INITIAL_HEAP * sizeof(Object *));

    // The free list stores the offset from the initial position for all
    // available slots.
    for (size_t i = 0; i < gc.obj_cap; i++) {
        gc.free_list[i] = i;
    }
}

Object *
alloc_object(ObjectType type) {
    if (gc.available_slots == 0) {
        // TODO: trigger garbage collection.
        if (gc.available_slots == 0) {
            // TODO: grow heap tables.
            // NOTE: When growing the tables, we might lose the pointer
            // references! Should we work with offsets all the way?  That is for
            // cdr and car? Should we have a utility function?
        }
    }
    size_t slot = gc.free_list[gc.fl_pos++];
    gc.available_slots--;
    Object *obj = gc.obj_list + slot;
    obj->type = type;
    return obj;
}