From a83c08aed74756b45a63aceb3d1a783116b02adb Mon Sep 17 00:00:00 2001 From: Ludovic 'Archivist' Lagouardette Date: Wed, 1 Oct 2025 00:43:49 +0200 Subject: [PATCH] Fixed garbage collection mistakes --- lib.c | 15 +++++++++------ test/garbage_shenanigans.c | 39 +++++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/lib.c b/lib.c index 5e211e3..acaafee 100644 --- a/lib.c +++ b/lib.c @@ -324,7 +324,7 @@ int ink_destroy(struct context* ctx) { for (i = 0; i < ctx->types_top; ++i) { struct ink_type* t = ctx->types + i; if (t->element_size > 0 && t->elements_top > 0) { - for (j = 0; i < t->element_size; ++j) { + for (j = 0; j < t->elements_top; ++j) { if (t->elements[j].in_use) { t->collect(ctx, t->elements[j].data); ctx->free(ctx, t->elements[j].data); @@ -343,8 +343,8 @@ int ink_destroy(struct context* ctx) { ctx->inner_free(ctx, ctx->native_words[i].name); } for (i = 0; i < ctx->routines_top; ++i) { - ctx->free(ctx, ctx->routines[i].function_stack); - ctx->free(ctx, ctx->routines[i].stack); + if(ctx->routines[i].function_stack) ctx->free(ctx, ctx->routines[i].function_stack); + if(ctx->routines[i].stack) ctx->free(ctx, ctx->routines[i].stack); } for (i = 0; i < ctx->lex_reserved_words_top; ++i) { ctx->free(ctx, ctx->lex_reserved_words[i]); @@ -454,7 +454,7 @@ static void ink_free(struct context* _, void* ptr) { free(ptr); } static int ink_putchar(struct context* _, int c) { - _=_; + (void)(_); return putchar(c); } @@ -1458,7 +1458,11 @@ void ink_gc(struct context* ctx) { for (i = 0; i < ctx->types_top; ++i) { for (j = 0; j < ctx->types[i].elements_top; ++j) { /* Only mark from things that are active and detected as in use */ - if (ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].is_protected && ctx->types[i].elements[j].uses) { + if(ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].is_protected && !ctx->types[i].elements[j].uses) { + ctx->types[i].elements[j].uses = 1; + marked = 1; + } + if (ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].uses) { struct ink_collection_list c; c = ctx->types[i].gc(ctx, ctx->types[i].elements[j].data); for (k = 0; k < c.count; ++k) { @@ -2087,7 +2091,6 @@ static void dump_stack(struct context* ctx) { if(idx != NULL) ctx->free(ctx, idx); value = type = idx = NULL; } - return; } static void collect_noop(struct context* ctx, void* array) { diff --git a/test/garbage_shenanigans.c b/test/garbage_shenanigans.c index 5d9bf9d..9aa51cf 100644 --- a/test/garbage_shenanigans.c +++ b/test/garbage_shenanigans.c @@ -1,9 +1,41 @@ #include "ink.h" +#include +#include +#include +#include + +size_t allocated = 0; +size_t deallocated = 0; + +static void* ink_malloc(struct context* _, size_t sz) { + (void)(_); + allocated+=sz; + void* ptr = malloc(sz + sizeof(size_t)); + *(size_t*)ptr = sz; + return (size_t*)ptr + 1; +} +static void ink_free(struct context* _, void* ptr) { + (void)(_); + deallocated += *((size_t*)ptr-1); + free(((size_t*)ptr)-1); +} +static void* ink_realloc(struct context* _, void* ptr, size_t sz) { + (void)(_); + char* new_ptr = ink_malloc(_, sz); + size_t old_sz = *(-1 + (size_t*)ptr); + memcpy(new_ptr, ptr, old_sz); + ink_free(_, ptr); + return new_ptr; +} +static int ink_putchar(struct context* _, int c) { + (void)(_); + return putchar(c); +} int main(int argc, char** argv) { struct context* ctx; - ctx = ink_make_default_context(); - + ctx = ink_make_context(ink_malloc, ink_realloc, ink_free, ink_putchar); + ink_std_library(ctx); ink_compile( ctx, "fn encrypt do\n" @@ -118,6 +150,7 @@ int main(int argc, char** argv) { counter += increment; } } - + ink_destroy(ctx); + assert(allocated == deallocated); //return ctx->routines[coro].panic != INK_ROUTINE_SUCCESS && ctx->routines[coro].panic != INK_ROUTINE_CAN_REUSE; } \ No newline at end of file