|
@@ -1,7 +1,14 @@
|
|
|
#include <stdio.h>
|
|
|
+#include <stdbool.h>
|
|
|
+#include <string.h>
|
|
|
#include "./heap.h"
|
|
|
|
|
|
uintptr_t heap[HEAP_CAP_WORDS] = {0};
|
|
|
+const uintptr_t *stack_base = 0;
|
|
|
+
|
|
|
+bool reachable_chunks[CHUNK_LIST_CAP] = {0};
|
|
|
+void *to_free[CHUNK_LIST_CAP] = {0};
|
|
|
+size_t to_free_count = 0;
|
|
|
|
|
|
Chunk_List alloced_chunks = {0};
|
|
|
Chunk_List freed_chunks = {
|
|
@@ -50,9 +57,9 @@ void chunk_list_merge(Chunk_List *dst, const Chunk_List *src)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void chunk_list_dump(const Chunk_List *list)
|
|
|
+void chunk_list_dump(const Chunk_List *list, const char *name)
|
|
|
{
|
|
|
- printf("Chunks (%zu):\n", list->count);
|
|
|
+ printf("%s Chunks (%zu):\n", name, list->count);
|
|
|
for (size_t i = 0; i < list->count; ++i) {
|
|
|
printf(" start: %p, size: %zu\n",
|
|
|
(void*) list->chunks[i].start,
|
|
@@ -121,7 +128,37 @@ void heap_free(void *ptr)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void mark_region(const uintptr_t *start, const uintptr_t *end)
|
|
|
+{
|
|
|
+ for (; start < end; start += 1) {
|
|
|
+ const uintptr_t *p = (const uintptr_t *) *start;
|
|
|
+ for (size_t i = 0; i < alloced_chunks.count; ++i) {
|
|
|
+ Chunk chunk = alloced_chunks.chunks[i];
|
|
|
+ if (chunk.start <= p && p < chunk.start + chunk.size) {
|
|
|
+ if (!reachable_chunks[i]) {
|
|
|
+ reachable_chunks[i] = true;
|
|
|
+ mark_region(chunk.start, chunk.start + chunk.size);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void heap_collect()
|
|
|
{
|
|
|
- UNIMPLEMENTED;
|
|
|
+ const uintptr_t *stack_start = (const uintptr_t*)__builtin_frame_address(0);
|
|
|
+ memset(reachable_chunks, 0, sizeof(reachable_chunks));
|
|
|
+ mark_region(stack_start, stack_base + 1);
|
|
|
+
|
|
|
+ to_free_count = 0;
|
|
|
+ for (size_t i = 0; i < alloced_chunks.count; ++i) {
|
|
|
+ if (!reachable_chunks[i]) {
|
|
|
+ assert(to_free_count < CHUNK_LIST_CAP);
|
|
|
+ to_free[to_free_count++] = alloced_chunks.chunks[i].start;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (size_t i = 0; i < to_free_count; ++i) {
|
|
|
+ heap_free(to_free[i]);
|
|
|
+ }
|
|
|
}
|