From bc659b1e915df683e2cbc93e08f438b1fa7999bc Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Tue, 14 Mar 2023 20:25:08 -0500 Subject: [PATCH] added: `alloc.gc.untrack` to untrack a GC'd allocation --- core/alloc/gc.onyx | 30 ++++++++++++++++++++++++++---- core/alloc/heap.onyx | 14 +++++++++++--- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/core/alloc/gc.onyx b/core/alloc/gc.onyx index bd3291c3..8ff2ebbf 100644 --- a/core/alloc/gc.onyx +++ b/core/alloc/gc.onyx @@ -21,7 +21,6 @@ GCState :: struct { first: &GCLink; } -#local GCLink :: struct { prev: &GCLink; next: &GCLink; @@ -37,7 +36,12 @@ make :: (backing := context.allocator) -> GCState { clear :: (hs: &GCState) { while l := hs.first; l != null { n := l.next; - raw_free(hs.backing_allocator, l); + + if l.magic_number == GC_Link_Magic_Number { + l.magic_number = 0; + raw_free(hs.backing_allocator, l); + } + l = n; } @@ -76,8 +80,10 @@ auto :: #match { } -#local -GC_Link_Magic_Number :: 0x1337face + +GC_Manually_Free_Magic_Number :: 0xface1337 + +#local GC_Link_Magic_Number :: 0x1337face #local gc_alloc_proc :: (data: &GCState, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr { @@ -108,6 +114,10 @@ GC_Link_Magic_Number :: 0x1337face } } + // \/ + // HEAP DATA | GCLINK | Your actual allocation + // POINTERS MAGIC NUMBERS | prev, next, magic_number | bytes of data... + newptr: &GCLink = data.backing_allocator.func( data.backing_allocator.data, aa, size + sizeof GCLink, align, old); @@ -128,3 +138,15 @@ GC_Link_Magic_Number :: 0x1337face return newptr + 1; } + +untrack :: (ptr: rawptr) -> bool { + link := (cast(&GCLink) ptr) - 1; + + if link.magic_number != GC_Link_Magic_Number { + return false; + } + + link.magic_number = GC_Manually_Free_Magic_Number; + return true; +} + diff --git a/core/alloc/heap.onyx b/core/alloc/heap.onyx index 6848c14d..79f90c8d 100644 --- a/core/alloc/heap.onyx +++ b/core/alloc/heap.onyx @@ -178,12 +178,20 @@ get_freed_size :: () => { heap_free :: (ptr: rawptr) { #if Enable_Debug do assert(ptr != null, "Trying to free a null pointer."); + + hb_ptr := cast(&heap_freed_block) (cast(uintptr) ptr - sizeof heap_allocated_block); + + // + // If this block was originally allocated from the GC space, + // and then marked an "manually managed", we can free the block + // as normal here, but we have to go back some more bytes. + if hb_ptr.magic_number == core.alloc.gc.GC_Manually_Free_Magic_Number { + hb_ptr = ~~(cast(uintptr) (cast(&core.alloc.gc.GCLink, ptr) - 1) - sizeof heap_allocated_block); + } + #if runtime.Multi_Threading_Enabled do sync.scoped_mutex(&heap_mutex); - hb_ptr := cast(&heap_freed_block) (cast(uintptr) ptr - sizeof heap_allocated_block); #if Enable_Debug { - // assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on free. This could be due to a double free, or using memory past were you allocated it."); - if cast(uintptr) hb_ptr < cast(uintptr) __heap_start { log(.Error, "Core", "FREEING STATIC DATA"); return; -- 2.25.1