MemoryArena updates using Gemini. Add some debug tag so we can debug memory allocations
This commit is contained in:
@@ -12,11 +12,27 @@ namespace Juliet
|
||||
uint8* Data;
|
||||
size_t Size;
|
||||
size_t Offset;
|
||||
#if JULIET_DEBUG
|
||||
struct AllocationInfo
|
||||
{
|
||||
size_t Offset;
|
||||
size_t Size;
|
||||
const char* Tag;
|
||||
};
|
||||
// Use a simple array for now to avoid std::vector dependency in the header or complex management
|
||||
// Ideally this should be a linked list or similar
|
||||
static constexpr size_t kMaxAllocations = 4096;
|
||||
AllocationInfo Allocations[kMaxAllocations];
|
||||
size_t AllocationCount = 0;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
JULIET_API void MemoryArenaCreate(MemoryArena* arena, void* backingMemory, size_t size);
|
||||
JULIET_API void* ArenaPush(MemoryArena* arena, size_t size, size_t alignment = 16);
|
||||
JULIET_API void* ArenaRealloc(MemoryArena* arena, void* oldPtr, size_t oldSize, size_t newSize, size_t alignment = 16);
|
||||
JULIET_API void* ArenaPush(MemoryArena* arena, size_t size, size_t alignment = 16, const char* tag = nullptr);
|
||||
|
||||
JULIET_API void* ArenaRealloc(MemoryArena* arena, void* oldPtr, size_t oldSize, size_t newSize, size_t alignment = 16, const char* tag = nullptr);
|
||||
|
||||
JULIET_API void ArenaReset(MemoryArena* arena);
|
||||
JULIET_API size_t ArenaGetMarker(MemoryArena* arena);
|
||||
JULIET_API void ArenaResetToMarker(MemoryArena* arena, size_t marker);
|
||||
@@ -39,9 +55,10 @@ namespace Juliet
|
||||
void MemoryArenasShutdown();
|
||||
|
||||
template <typename T>
|
||||
inline T* ArenaPushType(MemoryArena* arena)
|
||||
inline T* ArenaPushType(MemoryArena* arena, const char* tag = nullptr)
|
||||
{
|
||||
T* result = static_cast<T*>(ArenaPush(arena, sizeof(T), alignof(T)));
|
||||
T* result = static_cast<T*>(ArenaPush(arena, sizeof(T), alignof(T), tag));
|
||||
|
||||
if (result)
|
||||
{
|
||||
MemSet(result, 0, sizeof(T));
|
||||
@@ -50,9 +67,10 @@ namespace Juliet
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T* ArenaPushArray(MemoryArena* arena, size_t count)
|
||||
inline T* ArenaPushArray(MemoryArena* arena, size_t count, const char* tag = nullptr)
|
||||
{
|
||||
T* result = static_cast<T*>(ArenaPush(arena, sizeof(T) * count, alignof(T)));
|
||||
T* result = static_cast<T*>(ArenaPush(arena, sizeof(T) * count, alignof(T), tag));
|
||||
|
||||
if (result)
|
||||
{
|
||||
MemSet(result, 0, sizeof(T) * count);
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
namespace UnitTest
|
||||
{
|
||||
extern void TestMemoryArena();
|
||||
}
|
||||
|
||||
void MemoryArenaCreate(MemoryArena* arena, void* backingMemory, size_t size)
|
||||
{
|
||||
Assert(arena);
|
||||
@@ -13,10 +18,14 @@ namespace Juliet
|
||||
arena->Data = static_cast<uint8*>(backingMemory);
|
||||
arena->Size = size;
|
||||
arena->Offset = 0;
|
||||
#if JULIET_DEBUG
|
||||
arena->AllocationCount = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void* ArenaPush(MemoryArena* arena, size_t size, size_t alignment)
|
||||
void* ArenaPush(MemoryArena* arena, size_t size, size_t alignment, const char* tag)
|
||||
{
|
||||
(void)tag; // TODO: Use tag for allocation tracking in Debug builds
|
||||
Assert(arena);
|
||||
|
||||
// Alignment must be power of 2
|
||||
@@ -35,10 +44,19 @@ namespace Juliet
|
||||
void* result = arena->Data + (offset - reinterpret_cast<size_t>(arena->Data));
|
||||
arena->Offset = newOffset;
|
||||
|
||||
#if JULIET_DEBUG
|
||||
if (arena->AllocationCount < MemoryArena::kMaxAllocations)
|
||||
{
|
||||
arena->Allocations[arena->AllocationCount] = { offset - reinterpret_cast<size_t>(arena->Data), size, tag ? tag : "Unknown" };
|
||||
arena->AllocationCount++;
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void* ArenaRealloc(MemoryArena* arena, void* oldPtr, size_t oldSize, size_t newSize, size_t alignment)
|
||||
void* ArenaRealloc(MemoryArena* arena, void* oldPtr, size_t oldSize, size_t newSize, size_t alignment, const char* tag)
|
||||
|
||||
{
|
||||
Assert(arena);
|
||||
// Alignment must be power of 2
|
||||
@@ -46,7 +64,7 @@ namespace Juliet
|
||||
|
||||
if (oldPtr == nullptr)
|
||||
{
|
||||
return ArenaPush(arena, newSize, alignment);
|
||||
return ArenaPush(arena, newSize, alignment, tag);
|
||||
}
|
||||
|
||||
if (newSize == 0)
|
||||
@@ -84,12 +102,20 @@ namespace Juliet
|
||||
{
|
||||
// In-place Resize success
|
||||
arena->Offset = newOffset;
|
||||
#if JULIET_DEBUG
|
||||
// Update the last allocation size
|
||||
if (arena->AllocationCount > 0)
|
||||
{
|
||||
arena->Allocations[arena->AllocationCount - 1].Size = newSize;
|
||||
}
|
||||
#endif
|
||||
return oldPtr;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: Alloc + Copy
|
||||
void* newPtr = ArenaPush(arena, newSize, alignment);
|
||||
void* newPtr = ArenaPush(arena, newSize, alignment, tag);
|
||||
|
||||
if (newPtr)
|
||||
{
|
||||
size_t copySize = oldSize < newSize ? oldSize : newSize;
|
||||
@@ -102,6 +128,9 @@ namespace Juliet
|
||||
{
|
||||
Assert(arena);
|
||||
arena->Offset = 0;
|
||||
#if JULIET_DEBUG
|
||||
arena->AllocationCount = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t ArenaGetMarker(MemoryArena* arena)
|
||||
@@ -115,6 +144,20 @@ namespace Juliet
|
||||
Assert(arena);
|
||||
Assert(marker <= arena->Offset);
|
||||
arena->Offset = marker;
|
||||
|
||||
#if JULIET_DEBUG
|
||||
while (arena->AllocationCount > 0)
|
||||
{
|
||||
if (arena->Allocations[arena->AllocationCount - 1].Offset >= marker)
|
||||
{
|
||||
arena->AllocationCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// --- Global Arenas & Management ---
|
||||
@@ -167,6 +210,10 @@ namespace Juliet
|
||||
MemoryArenaCreate(&g_ScratchArena, g_ScratchBacking, kScratchSize);
|
||||
MemoryArenaCreate(&g_EngineArena, g_EngineBacking, kEngineSize);
|
||||
MemoryArenaCreate(&g_GameArena, g_GameBacking, kGameSize);
|
||||
|
||||
#if JULIET_DEBUG
|
||||
UnitTest::TestMemoryArena();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MemoryArenasShutdown()
|
||||
|
||||
Reference in New Issue
Block a user