diff --git a/src/kuroko/memory.h b/src/kuroko/memory.h index 0efecce..48a6f4f 100644 --- a/src/kuroko/memory.h +++ b/src/kuroko/memory.h @@ -78,3 +78,15 @@ extern void krk_markObject(KrkObj * object); */ extern void krk_markTable(KrkTable * table); +/** + * @brief Assume ownership of @p size bytes at @p ptr + * + * Future memory allocation operations with this ptr must be + * through @c krk_reallocate - @p size will be added to the + * VM allocation count, and if extensively memory debugging + * is enabled then the pointer will be marked as owned. + * + * @param ptr Pointer to take ownership of + * @param size Size of data at @p ptr + */ +extern void krk_gcTakeBytes(const void * ptr, size_t size); diff --git a/src/memory.c b/src/memory.c index 4884154..cda7259 100644 --- a/src/memory.c +++ b/src/memory.c @@ -5,7 +5,26 @@ #include #include +#if defined(KRK_EXTENSIVE_MEMORY_DEBUGGING) +/** + * Extensive memory debugging tracks every allocation + * in a table, but we don't want to use our table... + */ +#include "../../toaruos/lib/list.c" +#include "../../toaruos/lib/hashmap.c" +static hashmap_t * _debug_hash = NULL; +#endif + +void krk_gcTakeBytes(const void * ptr, size_t size) { +#if defined(KRK_EXTENSIVE_MEMORY_DEBUGGING) + hashmap_set(_debug_hash, (void*)ptr, (void*)(uintptr_t)(size)); +#endif + + vm.bytesAllocated += size; +} + void * krk_reallocate(void * ptr, size_t old, size_t new) { + vm.bytesAllocated -= old; vm.bytesAllocated += new; @@ -20,12 +39,40 @@ void * krk_reallocate(void * ptr, size_t old, size_t new) { } } + void * out; if (new == 0) { free(ptr); - return NULL; + out = NULL; + } else { + out = realloc(ptr, new); } - return realloc(ptr, new); +#if defined(KRK_EXTENSIVE_MEMORY_DEBUGGING) + if (!_debug_hash) { + _debug_hash = hashmap_create_int(1000); + } + if (ptr != NULL) { + if (!hashmap_has(_debug_hash, ptr)) { + fprintf(stderr, "Invalid reallocation of %p from %zu to %zu\n", ptr, old, new); + abort(); + } + + uintptr_t t = (uintptr_t)hashmap_get(_debug_hash, ptr); + if (t != old) { + fprintf(stderr, "Invalid reallocation of %p from %zu - should be %zu - to %zu\n", ptr, old, t, new); + abort(); + } + } + + if (ptr) { + hashmap_remove(_debug_hash, ptr); + } + if (out) { + hashmap_set(_debug_hash, out, (void*)(uintptr_t)new); + } +#endif + + return out; } static void freeObject(KrkObj * object) { diff --git a/src/object.c b/src/object.c index 8708b4b..bf31fab 100644 --- a/src/object.c +++ b/src/object.c @@ -212,7 +212,7 @@ KrkString * krk_takeString(char * chars, size_t length) { } /* Part of taking ownership of this string is that we track its memory usage */ - vm.bytesAllocated += length + 1; + krk_gcTakeBytes(chars, length + 1); KrkString * result = allocateString(chars, length, hash); return result; }