From 3c9fafb11afb507c476e037f6bf827a54113f524 Mon Sep 17 00:00:00 2001 From: Andre Wagner Date: Tue, 12 May 2026 20:09:40 -0500 Subject: [PATCH] . --- Makefile | 2 +- lib/heap.c | 51 +++++++++++++++++++++++++++++++++------------------ test/tests.c | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 66 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index c567b36..0a99dcd 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ endif # debug and release flags -DEBUG_CFLAGS=-Og -ggdb3 ${WARNINGS} -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined \ +DEBUG_CFLAGS=-O0 -ggdb3 ${WARNINGS} -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined \ -fno-sanitize-recover=all -fstack-protector-strong -fstack-clash-protection -fno-common ${ADD_DBG_FLAGS} \ -DCHECK_TYCHE_BUGS=1 DEBUG_LDFLAGS=-fsanitize=address -fsanitize=undefined diff --git a/lib/heap.c b/lib/heap.c index 5b7f137..ffba83d 100644 --- a/lib/heap.c +++ b/lib/heap.c @@ -2,6 +2,7 @@ #include #include +#include #include "khash.h" @@ -18,7 +19,7 @@ typedef struct { // TODO - array and table } value; } HeapValue; -KHASH_MAP_INIT_INT(HEAP, HeapValue) +KHASH_MAP_INIT_INT64(HEAP, HeapValue) typedef struct { khash_t(HEAP) *items; @@ -29,20 +30,27 @@ static void heap_init(Heap* h) h->items = kh_init(HEAP); } +static void heap_free_item(HeapValue value) +{ + switch (value.type) { + case TH_STRING: + free(value.value.str); + break; + case TH_ARRAY: + abort(); // not implemented yet + break; + case TH_TABLE: + abort(); // not implemented yet + break; + } +} + static void heap_finalize(Heap* h) { for (khiter_t k = kh_begin(h->items); k != kh_end(h->items); ++k) { - HeapValue value = kh_value(h->items, k); - switch (value.type) { - case TH_STRING: - free(value.value.str); - break; - case TH_ARRAY: - abort(); // not implemented yet - break; - case TH_TABLE: - abort(); // not implemented yet - break; + if (kh_exist(h->items, k)) { + HeapValue value = kh_value(h->items, k); + heap_free_item(value); } } kh_destroy(HEAP, h->items); @@ -88,7 +96,8 @@ static size_t heap_size(Heap* h) // GC // -KHASH_MAP_INIT_INT(MARK, bool) +KHASH_MAP_INIT_INT64(MARK, bool) + static void heap_gc(Heap* h, VALUE const* roots, size_t n_roots) { // @@ -100,7 +109,8 @@ static void heap_gc(Heap* h, VALUE const* roots, size_t n_roots) for (size_t i = 0; i < n_roots; ++i) { if (value_type(roots[i]) == TT_STRING) { int ret; - khiter_t k = kh_put(MARK, marked, value_idx(roots[i]), &ret); + uint32_t key = value_idx(roots[i]); + khiter_t k = kh_put(MARK, marked, key, &ret); kh_value(marked, k) = true; } } @@ -109,10 +119,15 @@ static void heap_gc(Heap* h, VALUE const* roots, size_t n_roots) // sweep // - for (khiter_t k = kh_begin(marked); k != kh_end(marked); ++k) { - HEAP_KEY key = kh_value(marked, k); - khiter_t item = kh_get(HEAP, h->items, key); - kh_del(HEAP, h->items, item); + for (khiter_t k = kh_begin(h->items); k != kh_end(h->items); ++k) { + if (kh_exist(h->items, k)) { + HEAP_KEY key = kh_key(h->items, k); + if (kh_get(MARK, marked, key) == kh_end(marked)) { + khiter_t kk = kh_get(HEAP, h->items, key); + heap_free_item(kh_value(h->items, kk)); + kh_del(HEAP, h->items, kk); + } + } } kh_destroy(MARK, marked); diff --git a/test/tests.c b/test/tests.c index 2c11110..b12e7a0 100644 --- a/test/tests.c +++ b/test/tests.c @@ -93,7 +93,7 @@ int main() } { - printf("### Heap\n"); + printf("### Heap - strings\n"); Heap h; heap_init(&h); @@ -108,4 +108,35 @@ int main() heap_finalize(&h); } + + { + printf("### Heap - string GC\n"); + + Stack s; + stack_init(&s); + + Heap h; + heap_init(&h); + + stack_push(&s, create_value_idx(TT_STRING, heap_add_string(&h, "item1"))); + stack_push(&s, create_value_idx(TT_STRING, heap_add_string(&h, "item2"))); + stack_push(&s, create_value_idx(TT_STRING, heap_add_string(&h, "item3"))); + + assert(heap_size(&h) == 3); + heap_gc(&h, s.stack, s.stack_n); + assert(heap_size(&h) == 3); + + stack_pop(&s, NULL); + + assert(heap_size(&h) == 3); + heap_gc(&h, s.stack, s.stack_n); + assert(heap_size(&h) == 2); + + stack_pop(&s, NULL); + heap_gc(&h, s.stack, s.stack_n); + assert(heap_size(&h) == 1); + + heap_finalize(&h); + stack_finalize(&s); + } } \ No newline at end of file