blob: 2bdac4ce441c9a7c5f9659df8cf86875c45da7ac [file] [log] [blame]
swissChili6d6525e2021-06-15 21:20:53 -07001#include "gc.h"
2#include "lisp.h"
swissChilie9fec8b2021-06-22 13:59:33 -07003#include "plat/plat.h"
swissChili6d6525e2021-06-15 21:20:53 -07004
swissChili9e57da42021-06-15 22:22:46 -07005value_t *gc_base;
swissChilie9fec8b2021-06-22 13:59:33 -07006THREAD_LOCAL static unsigned int gc_mark;
swissChili6d6525e2021-06-15 21:20:53 -07007
swissChili9e57da42021-06-15 22:22:46 -07008void __attribute__((noinline)) gc_set_base_here()
9{
10 // Move the current stack top address to gc_base. This works nicely because
11 // it means that when another (presumably lisp) function is called right
12 // after this, the stack top for it will be the same as for this function.
13 asm("movl %%esp, %0" : "=g"(gc_base));
14}
15
swissChilie9fec8b2021-06-22 13:59:33 -070016void _mark(value_t value, unsigned int *marked)
swissChili9e57da42021-06-15 22:22:46 -070017{
18 if (heapp(value))
19 {
swissChilie9fec8b2021-06-22 13:59:33 -070020 void *pointer = (void *)(value & ~HEAP_MASK);
21 struct alloc *alloc = pointer - sizeof(struct alloc);
swissChili9e57da42021-06-15 22:22:46 -070022
swissChilie9fec8b2021-06-22 13:59:33 -070023 fprintf(stderr, "[ GC ] Marking 0x%p\n", pointer);
24
25 // Only recursively mark if this hasn't been marked yet. i.e. prevent
26 // marking circular references twice
27 if (alloc->mark != gc_mark)
28 {
29 ++*marked;
30
31 alloc->mark = gc_mark;
32
33 // printf("[ GC ] val =");
34 // printval(alloc_to_value(alloc), 2);
35
36 switch (alloc->type_tag)
37 {
38 case CONS_TAG: {
39 struct cons_alloc *cons = (struct cons_alloc *)alloc;
40 _mark(cons->cons.car, marked);
41 _mark(cons->cons.cdr, marked);
42 break;
43 }
44 }
45 }
swissChili9e57da42021-06-15 22:22:46 -070046 }
swissChili6d6525e2021-06-15 21:20:53 -070047}
48
swissChilie9fec8b2021-06-22 13:59:33 -070049value_t alloc_to_value(struct alloc *a)
50{
51 void *val = ((void *)a) + sizeof(struct alloc);
52 return (unsigned int)val | a->type_tag;
53}
54
swissChili6d6525e2021-06-15 21:20:53 -070055void _sweep()
56{
swissChili5db22a02021-06-30 22:04:33 -070057 for (struct alloc *a = first_a; a;)
swissChilie9fec8b2021-06-22 13:59:33 -070058 {
swissChilib8fd4712021-06-23 15:32:04 -070059 if (pool_alive(a->pool) || a->mark == gc_mark)
60 {
61 // Marked or in living pool
swissChili5db22a02021-06-30 22:04:33 -070062 a = a->next;
swissChilib8fd4712021-06-23 15:32:04 -070063 }
64 else
65 {
66 printf("Freeing:\n");
67 printval(alloc_to_value(a), 2);
68
69 // Free and remove from allocation list
70 struct alloc *p = a->prev, *n = a->next;
71 free_aligned(a);
72
73 a = n;
74
75 if (p)
76 p->next = n;
77
78 if (n)
79 n->prev = p;
80 }
swissChilie9fec8b2021-06-22 13:59:33 -070081 }
swissChili6d6525e2021-06-15 21:20:53 -070082}
83
84void _do_gc(unsigned int esp, unsigned int ebp)
85{
swissChili9e57da42021-06-15 22:22:46 -070086 value_t *esp_p = (value_t *)esp,
87 *ebp_p = (value_t *)ebp;
swissChili6d6525e2021-06-15 21:20:53 -070088
swissChilie9fec8b2021-06-22 13:59:33 -070089 unsigned int num_marked = 0;
90
91 gc_mark++;
92
93 fprintf(stderr, "[ GC ] %d (esp 0x%p, ebp 0x%p)\n", gc_mark, esp_p, ebp_p);
swissChili9e57da42021-06-15 22:22:46 -070094
95 // For every stack frame until the base of the stack
96 while (esp_p < gc_base)
swissChili6d6525e2021-06-15 21:20:53 -070097 {
swissChili9e57da42021-06-15 22:22:46 -070098 // Walk up the stack until we reach either the frame pointer or the base
99 // of the stack. Basically walk to the top of this function's stack
100 // frame.
101 for (; esp_p < ebp_p && esp_p < gc_base; esp_p++)
102 {
swissChilie9fec8b2021-06-22 13:59:33 -0700103 _mark(*esp_p, &num_marked);
swissChili9e57da42021-06-15 22:22:46 -0700104 }
105
106 // Set the frame pointer to the frame pointer on the stack
107 ebp_p = (value_t *)*esp_p;
108
109 // Step up two stack slots, one for the frame pointer and one for the
110 // return address.
111 esp_p += 2;
swissChili6d6525e2021-06-15 21:20:53 -0700112 }
swissChili9e57da42021-06-15 22:22:46 -0700113
114 fprintf(stderr, "Marked %d\n", num_marked);
swissChilie9fec8b2021-06-22 13:59:33 -0700115
116 _sweep();
swissChili6d6525e2021-06-15 21:20:53 -0700117}
swissChilib8fd4712021-06-23 15:32:04 -0700118
119void free_all()
120{
121 for (struct alloc *a = first_a; a;)
122 {
123 struct alloc *next = a->next;
124 free_aligned(a);
125 a = next;
126 }
127}