From c2f4686bc4eb26da42975494d770e3e1dcdc6398 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sun, 30 Nov 2025 19:54:46 +0100 Subject: [PATCH] BlockArena, a bit of allocator rework --- build.bat | 2 + src/backup/todo.txt | 3 +- src/basic/basic_alloc.cpp | 311 ++++++++++++++++--------- src/basic/basic_alloc.h | 126 +++++----- src/basic/basic_array.h | 7 +- src/basic/basic_os.cpp | 6 +- src/basic/basic_table.h | 9 +- src/metaprogram/metaprogram.cpp | 2 - src/render/opengl.cpp | 12 +- src/text_editor/buffer.cpp | 39 ++-- src/text_editor/commands_clipboard.cpp | 9 +- src/text_editor/intern_table.cpp | 11 +- src/text_editor/management.cpp | 14 +- src/text_editor/text_editor.cpp | 8 +- src/text_editor/text_editor.h | 2 +- 15 files changed, 337 insertions(+), 224 deletions(-) diff --git a/build.bat b/build.bat index fba6894..06ae82f 100644 --- a/build.bat +++ b/build.bat @@ -14,3 +14,5 @@ cl %flags% ../src/text_editor/text_editor.cpp -Fe:te.exe -I../src/external/SDL/i copy te.exe ..\data\te.exe copy te.pdb ..\data\te.pdb echo written ..\data\te.exe +cd .. +rem /fsanitize=address \ No newline at end of file diff --git a/src/backup/todo.txt b/src/backup/todo.txt index fda7893..8446628 100644 --- a/src/backup/todo.txt +++ b/src/backup/todo.txt @@ -21,7 +21,8 @@ Things I like: - Lua config files work pretty well Splits: -- Buffer16.cpp / h +- Buffer16.cpp / h vs Buffer ? +- Move font params to MainFont, allow for more fonts - Block arena and refactor alloc diff --git a/src/basic/basic_alloc.cpp b/src/basic/basic_alloc.cpp index 079467a..9006773 100644 --- a/src/basic/basic_alloc.cpp +++ b/src/basic/basic_alloc.cpp @@ -10,6 +10,7 @@ #define MA_ASAN_UNPOISON_MEMORY_REGION(addr, size) ASAN_UNPOISON_MEMORY_REGION(addr, size) #endif +#include #if OS_WINDOWS #ifndef NOMINMAX @@ -20,44 +21,44 @@ #endif #include -void *VReserve(size_t size) { +API void *VReserve(size_t size) { void *result = (uint8_t *)VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); return result; } -bool VCommit(void *p, size_t size) { +API bool VCommit(void *p, size_t size) { void *result = VirtualAlloc(p, size, MEM_COMMIT, PAGE_READWRITE); return result ? true : false; } -bool VRelease(void *p, size_t size) { +API bool VRelease(void *p, size_t size) { BOOL result = VirtualFree(p, 0, MEM_RELEASE); return result ? true : false; } -bool VDecommit(void *p, size_t size) { +API bool VDecommit(void *p, size_t size) { BOOL result = VirtualFree(p, size, MEM_DECOMMIT); return result ? true : false; } #elif OS_LINUX || OS_MAC -void *VReserve(size_t size) { +API void *VReserve(size_t size) { void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t)0); return result == (void *)-1 ? 0 : result; } -bool VCommit(void *p, size_t size) { +API bool VCommit(void *p, size_t size) { int result = mprotect(p, size, PROT_READ | PROT_WRITE); return result == 0; } -bool VRelease(void *p, size_t size) { +API bool VRelease(void *p, size_t size) { int result = munmap(p, size); return result == 0; } -bool VDecommit(void *p, size_t size) { +API bool VDecommit(void *p, size_t size) { mprotect(p, size, PROT_NONE); madvise(p, size, MADV_DONTNEED); return true; @@ -65,29 +66,102 @@ bool VDecommit(void *p, size_t size) { #else -void *VReserve(size_t size) { +API void *VReserve(size_t size) { InvalidCodepath(); return NULL; } -bool VCommit(void *p, size_t size) { +API bool VCommit(void *p, size_t size) { InvalidCodepath(); return false; } -bool VRelease(void *p, size_t size) { +API bool VRelease(void *p, size_t size) { InvalidCodepath(); return false; } -bool VDecommit(void *p, size_t size) { +API bool VDecommit(void *p, size_t size) { InvalidCodepath(); return false; } #endif -void InitArena(Arena *arena, size_t reserve) { +API void *SystemAllocatorProc(void *object, int kind, void *p, size_t size) { + void *result = NULL; + if (kind == AllocatorKind_Allocate) { + result = malloc(size); + Assert(result); + } else if (kind == AllocatorKind_Deallocate) { + free(p); + } else { + InvalidCodepath(); + } + return result; +} + +API Allocator GetSystemAllocator() { + Allocator result = {SystemAllocatorProc}; + return result; +} + +API void *_AllocSize_(Allocator alo, size_t size) { + void *result = alo.proc(alo.object, AllocatorKind_Allocate, NULL, size); + memset(result, 0, size); + return result; +} + +struct MemoryRecord { + size_t size; + void *addr; + char *file; + int line; +}; +thread_local Array MemoryTrackingRecord; + + +API void *TrackingAllocatorProc(void *object, int kind, void *p, size_t size) { + void *result = NULL; + + if (kind == AllocatorKind_Allocate) { + result = malloc(size); + Add(&MemoryTrackingRecord, {size, result, LocationTraceO.file, LocationTraceO.line}); + Assert(result); + } else if (kind == AllocatorKind_Deallocate) { + free(p); + + bool found = false; + For(IterateInReverse(&MemoryTrackingRecord)) { + if (it.addr == p) { + found = true; + UnorderedRemove(&MemoryTrackingRecord, it); + break; + } + } + Assert(found); + } else { + InvalidCodepath(); + } + return result; +} + +API void TrackingAllocatorCheck() { + // For (MemoryTrackingRecord) { + // ReportConsolef("%s(%d): error: memory leak"); + // } + Assert(MemoryTrackingRecord.len == 0); +} + +API Allocator GetTrackingAllocator() { + Allocator result = {TrackingAllocatorProc}; + return result; +} + +/////////////////////////////// +// Virtual Arena + +API void InitArena(VirtualArena *arena, size_t reserve) { reserve = AlignUp(reserve, PAGE_SIZE); arena->align = DEFAULT_ALIGNMENT; arena->data = (uint8_t *)VReserve(reserve); @@ -96,8 +170,8 @@ void InitArena(Arena *arena, size_t reserve) { } } -Arena *AllocArena(Allocator allocator, size_t size) { - Arena *result = AllocType(allocator, Arena); +API VirtualArena *AllocArena(Allocator allocator, size_t size) { + VirtualArena *result = AllocType(allocator, VirtualArena); result->data = (uint8_t *)AllocSize(allocator, size); result->reserve = size; result->commit = size; @@ -105,8 +179,8 @@ Arena *AllocArena(Allocator allocator, size_t size) { return result; } -Arena *AllocArena(size_t reserve) { - Arena *result = NULL; +API VirtualArena *AllocArena(size_t reserve) { + VirtualArena *result = NULL; void *data = VReserve(reserve); if (!data) return result; @@ -117,16 +191,16 @@ Arena *AllocArena(size_t reserve) { return result; } - result = (Arena *)data; + result = (VirtualArena *)data; result->data = (uint8_t *)data; result->reserve = reserve; result->commit = PAGE_SIZE; - result->len = result->base_len = sizeof(Arena); + result->len = result->base_len = sizeof(VirtualArena); result->align = DEFAULT_ALIGNMENT; return result; } -void *PushSize(Arena *arena, size_t size) { +API void *PushSize(VirtualArena *arena, size_t size) { // base_len is used for bootstraping arenas, it denotes the // space occupied by the arena. If len is smaller then base_len then // we start to overwrite the arena itself - pure barbarism. @@ -145,7 +219,7 @@ void *PushSize(Arena *arena, size_t size) { if (to_commit_clamped > 0) { bool success = VCommit(arena->data + arena->commit, to_commit_clamped); if (success) { - MA_ASAN_UNPOISON_MEMORY_REGION(arena->data + arena->commit, to_commit_clamped); + MA_ASAN_POISON_MEMORY_REGION(arena->data + arena->commit, to_commit_clamped); arena->commit += to_commit_clamped; } } @@ -159,14 +233,14 @@ void *PushSize(Arena *arena, size_t size) { return (void *)result; } -void Release(Arena *arena) { +API void Release(VirtualArena *arena) { if (arena == NULL || arena->data == NULL) return; bool zero_memory = (uint8_t *)arena != arena->data; VRelease(arena->data, arena->reserve); - if (zero_memory) MemoryZero(arena, sizeof(Arena)); + if (zero_memory) MemoryZero(arena, sizeof(VirtualArena)); } -void PopToPos(Arena *arena, size_t pos) { +API void PopToPos(VirtualArena *arena, size_t pos) { // base_len is used for bootstraping arenas, it denotes the // space occupied by the arena. If len is smaller then base_len then // we start to overwrite the arena itself - pure barbarism. @@ -178,9 +252,9 @@ void PopToPos(Arena *arena, size_t pos) { MA_ASAN_POISON_MEMORY_REGION(arena->data + arena->len, size); } -void *ArenaAllocatorProc(void *object, int kind, void *p, size_t size) { +API void *ArenaAllocatorProc(void *object, int kind, void *p, size_t size) { if (kind == AllocatorKind_Allocate) { - return PushSize((Arena *)object, size); + return PushSize((VirtualArena *)object, size); } else if (AllocatorKind_Deallocate) { } else { Assert(!"invalid codepath"); @@ -188,106 +262,123 @@ void *ArenaAllocatorProc(void *object, int kind, void *p, size_t size) { return NULL; } -thread_local Arena *ScratchArenaPool[4]; +/////////////////////////////// +// Block Arena -#if OS_WASM -void InitScratch() { - Allocator sys_allocator = GetSystemAllocator(); - ScratchArenaPool[0] = AllocArena(sys_allocator, MiB(16)); - ScratchArenaPool[1] = AllocArena(sys_allocator, MiB(8)); - ScratchArenaPool[3] = AllocArena(sys_allocator, MiB(2)); - ScratchArenaPool[3] = AllocArena(sys_allocator, MiB(1)); -} -#else -void InitScratch() { - for (int i = 0; i < Lengthof(ScratchArenaPool); i += 1) { - ScratchArenaPool[i] = AllocArena(); - } -} -#endif - -TempArena GetScratchEx(Arena **conflicts, int conflict_count) { - Arena *unoccupied = 0; - for (int i = 0; i < Lengthof(ScratchArenaPool); i += 1) { - Arena *from_pool = ScratchArenaPool[i]; - unoccupied = from_pool; - for (int conflict_i = 0; conflict_i < conflict_count; conflict_i += 1) { - Arena *from_conflict = conflicts[conflict_i]; - if (from_pool == from_conflict) { - unoccupied = 0; - break; - } +API void *PushSize(BlockArena *arena, size_t size) { + if (size > (size_t)(arena->end - arena->start)) { + size_t block_size = MiB(1); + if (size > block_size) { + block_size = size; } + if (arena->allocator.proc == NULL) { + arena->allocator = GetSystemAllocator(); + } + BlockArenaNode *new_block = (BlockArenaNode *)AllocSize(arena->allocator, block_size + sizeof(BlockArenaNode)); + Assert(GetAlignOffset((size_t)new_block->start, DEFAULT_ALIGNMENT) == 0); + arena->start = new_block->start; + new_block->end = arena->end = new_block->start + block_size; + SLL_STACK_ADD(arena->blocks, new_block); + } + U8 *result = arena->start; + Assert(GetAlignOffset((size_t)result, DEFAULT_ALIGNMENT) == 0); + arena->start = (U8 *)AlignUp((size_t)(arena->start + size), DEFAULT_ALIGNMENT); + return result; +} - if (unoccupied) { +API void Release(BlockArena *arena) { + for (BlockArenaNode *it = arena->blocks, *next = NULL; it; it = next) { + next = it->next; + Dealloc(arena->allocator, it); + } + MemoryZero(arena, sizeof(BlockArena)); +} + +API void Unwind(BlockArena *arena, U8 *pos) { + bool contains = false; + for (BlockArenaNode *it = arena->blocks, *next = NULL; it; it = next) { + next = it->next; + if ((pos >= it->start) && (pos < it->end)) { + contains = true; break; + } else { + arena->blocks = arena->blocks->next; + Dealloc(arena->allocator, it); } } - - // Failed to get free scratch memory, this is a fatal error, this shouldnt happen - Assert(unoccupied); - TempArena result = BeginTemp(unoccupied); - return result; + Assert(contains || pos == NULL); + arena->start = pos; } - #include -void *SystemAllocator_Alloc(void *object, int kind, void *p, size_t size) { - void *result = NULL; +API void *BlockArenaAllocatorProc(void *object, int kind, void *p, size_t size) { + BlockArena *arena = (BlockArena *)object; if (kind == AllocatorKind_Allocate) { - result = malloc(size); - Assert(result); - } else if (kind == AllocatorKind_Deallocate) { - free(p); + return PushSize(arena, size); + } else if (AllocatorKind_Deallocate) { } else { - InvalidCodepath(); + Assert(!"invalid codepath"); } - return result; + return NULL; } -Allocator GetSystemAllocator() { - Allocator result = {SystemAllocator_Alloc}; - return result; -} - -struct MemoryRecord { - size_t size; - void *addr; - bool deallocated; -}; -Array MemoryTrackingRecord; - - -void *TrackingAllocatorProc(void *object, int kind, void *p, size_t size) { - void *result = NULL; - - if (kind == AllocatorKind_Allocate) { - result = malloc(size); - Add(&MemoryTrackingRecord, {size, result}); - Assert(result); - } else if (kind == AllocatorKind_Deallocate) { - free(p); - - bool found = false; - For(MemoryTrackingRecord){ - if (it.addr == p) { - it.deallocated = true; - found = true; +void TestArena() { + Allocator memory_tracking_allocator = GetTrackingAllocator(); + { + BlockArena arena = {}; + arena.allocator = memory_tracking_allocator; + for (int i = 0; i < 10000; i += 1) { + int *vals = (int *)PushSize(&arena, sizeof(int)*i); + for (int j = 0; j < i; j += 1) { + vals[j] = j; } } - Assert(found); - } else { - InvalidCodepath(); + Release(&arena); + TrackingAllocatorCheck(); } - return result; -} -void TrackingAllocatorCheck() { - For (MemoryTrackingRecord) { - Assert(it.deallocated); + { + BlockArena arena = {}; + U8 *start = arena.start; + arena.allocator = memory_tracking_allocator; + int *vals = (int *)PushSize(&arena, sizeof(int) * 32); + for (int i = 0; i < 32; i += 1) vals[i] = i; + Unwind(&arena, (U8 *)vals); + Assert(arena.blocks); + Assert(arena.blocks->next == NULL); + Assert(arena.start == (U8 *)vals); + Assert(arena.blocks[0].start == (U8 *)vals); + Unwind(&arena, NULL); + Dealloc(arena.allocator, arena.blocks); + TrackingAllocatorCheck(); + } + + { + BlockArena arena = {}; + arena.allocator = memory_tracking_allocator; + int *vals = (int *)PushSize(&arena, sizeof(int) * 32); + for (int i = 0; i < 32; i += 1) vals[i] = i; + + U8 *p = arena.start; + U8 *a = (U8 *)PushSize(&arena, KiB(32)); + U8 *b = (U8 *)PushSize(&arena, KiB(1000)); + Assert(arena.blocks); + Assert(arena.blocks->next); + Assert(arena.blocks->next->next == NULL); + Unwind(&arena, a); + Assert(arena.blocks); + Assert(arena.blocks->next == NULL); + Assert(arena.start == p); + + Release(&arena); + TrackingAllocatorCheck(); + } + + { + BlockArena arena = {}; + arena.allocator = memory_tracking_allocator; + U8 *a = (U8 *)PushSize(&arena, KiB(2000)); + Assert((size_t)(arena.blocks[0].end - arena.blocks[0].start) == KiB(2000)); + Release(&arena); + TrackingAllocatorCheck(); } } - -Allocator GetTrackingAllocator() { - Allocator result = {TrackingAllocatorProc}; - return result; -} \ No newline at end of file diff --git a/src/basic/basic_alloc.h b/src/basic/basic_alloc.h index 0ba11eb..4d97cf0 100644 --- a/src/basic/basic_alloc.h +++ b/src/basic/basic_alloc.h @@ -1,5 +1,17 @@ #pragma once +struct LocationTrace { + char *file; + int line; +}; + +#if DEBUG_BUILD +thread_local LocationTrace LocationTraceO; +#define LOCATION_TRACE (LocationTraceO.file = __FILE__, LocationTraceO.line = __LINE__) +#else +#define LOCATION_TRACE +#endif + const int AllocatorKind_Allocate = 1; const int AllocatorKind_Deallocate = 2; @@ -10,29 +22,47 @@ struct Allocator { #define AllocType(alo, Type) (Type *)AllocSize(alo, sizeof(Type)) #define AllocArray(alo, Type, count) (Type *)AllocSize(alo, sizeof(Type) * (count)) -inline void *AllocSize(Allocator alo, size_t size) { - void *result = alo.proc(alo.object, AllocatorKind_Allocate, NULL, size); - memset(result, 0, size); - return result; -} +#define AllocSize(alo, size) (LOCATION_TRACE, _AllocSize_(alo, size)) +API void *_AllocSize_(Allocator alo, size_t size); +inline void Dealloc(Allocator alo, void *p) { if (p) (alo).proc((alo).object, AllocatorKind_Deallocate, (p), 0); } -template -void Dealloc(Allocator alo, T **p) { - if (*p == NULL) return; - alo.proc(alo.object, AllocatorKind_Deallocate, *p, 0); - *p = NULL; -} -#define DeallocEx(alo, p) (alo).proc((alo).object, AllocatorKind_Deallocate, (p), 0); +API Allocator GetSystemAllocator(); +API void TrackingAllocatorCheck(); +API Allocator GetTrackingAllocator(); -Allocator GetSystemAllocator(); #define MemoryZero(x, size) memset(x, 0, size) #define MemoryCopy(dst, src, size) memcpy(dst, src, size) #define MemoryMove(dst, src, size) memmove(dst, src, size) -const int PAGE_SIZE = 4096; -const int DEFAULT_ALIGNMENT = sizeof(void *); +/////////////////// +// Block Arena +/////////////////// +API void *BlockArenaAllocatorProc(void *object, int kind, void *p, size_t size); -struct Arena { +struct BlockArenaNode { + BlockArenaNode *next; + U8 *end; + U8 start[0]; +}; + +struct BlockArena { + U8 *start; + U8 *end; + BlockArenaNode *blocks; + Allocator allocator; + + operator Allocator() { return {BlockArenaAllocatorProc, this}; } +}; + +API void *PushSize(BlockArena *arena, size_t size); +API void Release(BlockArena *arena); +API void Unwind(BlockArena *arena, U8 *pos); + +/////////////////// +// Virtual Arena +/////////////////// + +struct VirtualArena { uint8_t *data; size_t len; size_t base_len; // to prevent self deleting the arena @@ -46,50 +76,40 @@ struct Arena { } }; -struct TempArena { - Arena *arena; - size_t len; -}; -inline void SetLen(Arena *arena, size_t len) { arena->len = Clamp(len, arena->base_len, arena->len); } -inline void Pop(Arena *arena, size_t size) { SetLen(arena, arena->len - size); } -inline TempArena BeginTemp(Arena *arena) { return {arena, arena->len}; } -inline void EndTemp(TempArena temp) { SetLen(temp.arena, temp.len); } -inline void Clear(Arena *arena) { SetLen(arena, 0); } +inline void SetLen(VirtualArena *arena, size_t len) { arena->len = Clamp(len, arena->base_len, arena->len); } +inline void Pop(VirtualArena *arena, size_t size) { SetLen(arena, arena->len - size); } +inline void Clear(VirtualArena *arena) { SetLen(arena, 0); } -void *VReserve(size_t size); -bool VCommit(void *p, size_t size); -bool VRelease(void *p, size_t size); -bool VDecommit(void *p, size_t size); +API void *VReserve(size_t size); +API bool VCommit(void *p, size_t size); +API bool VRelease(void *p, size_t size); +API bool VDecommit(void *p, size_t size); -void InitArena(Arena *arena, size_t reserve = MiB(256)); -Arena *AllocArena(size_t reserve = MiB(256)); -Arena *AllocArena(Allocator allocator, size_t size); -void *PushSize(Arena *arena, size_t size); -void Release(Arena *arena); -void InitScratch(); -TempArena GetScratchEx(Arena **conflicts, int conflict_count); +API void InitArena(VirtualArena *arena, size_t reserve = MiB(256)); +API VirtualArena *AllocArena(size_t reserve = MiB(256)); +API VirtualArena *AllocArena(Allocator allocator, size_t size); +API void *PushSize(VirtualArena *arena, size_t size); +API void Release(VirtualArena *arena); -inline TempArena GetScratch(Arena *c1 = NULL, Arena *c2 = NULL) { - int count = c1 ? 1 : 0; - count += c2 ? 1 : 0; - Arena *conflicts[] = {c1, c2}; - return GetScratchEx(conflicts, count); -} +/////////////////////////////// +// Scratch struct Scratch { - TempArena checkpoint; - Scratch() { this->checkpoint = GetScratch(); } - - Scratch(Arena *conflict) { this->checkpoint = GetScratch(conflict); } - Scratch(Arena *c1, Arena *c2) { this->checkpoint = GetScratch(c1, c2); } - Scratch(Allocator conflict) { this->checkpoint = GetScratch((Arena *)conflict.object); } - Scratch(Allocator c1, Allocator c2) { this->checkpoint = GetScratch((Arena *)c1.object, (Arena *)c2.object); } - ~Scratch() { EndTemp(checkpoint); } - operator Arena *() { return checkpoint.arena; } - operator Allocator() { return *checkpoint.arena; } + BlockArena arena = {}; + Scratch() {} + Scratch(BlockArena *conflict) {} + Scratch(BlockArena *c1, BlockArena *c2) {} + Scratch(Allocator conflict) {} + Scratch(Allocator c1, Allocator c2) {} + ~Scratch() { Release(&arena); } + operator BlockArena *() { return &arena; } + operator Allocator() { return arena; } private: // @Note: Disable copy constructors, cause its error prone Scratch(Scratch &arena); Scratch(Scratch &arena, Scratch &a2); -}; \ No newline at end of file +}; + +const int PAGE_SIZE = 4096; +const int DEFAULT_ALIGNMENT = sizeof(void *); \ No newline at end of file diff --git a/src/basic/basic_array.h b/src/basic/basic_array.h index 5842d05..f07e5c0 100644 --- a/src/basic/basic_array.h +++ b/src/basic/basic_array.h @@ -214,7 +214,7 @@ void Reserve(Array *arr, int64_t size) { T *new_data = AllocArray(arr->allocator, T, size); Assert(new_data); memcpy(new_data, arr->data, arr->len * sizeof(T)); - Dealloc(arr->allocator, &arr->data); + Dealloc(arr->allocator, arr->data); arr->data = new_data; arr->cap = size; @@ -393,7 +393,10 @@ T Get(Array &arr, int64_t i, T default_value = {}) { template void Dealloc(Array *arr) { - if (arr->data) Dealloc(arr->allocator, &arr->data); + if (arr->data) { + Dealloc(arr->allocator, arr->data); + arr->data = NULL; + } arr->len = arr->cap = 0; } diff --git a/src/basic/basic_os.cpp b/src/basic/basic_os.cpp index 8e1c930..1b81a7c 100644 --- a/src/basic/basic_os.cpp +++ b/src/basic/basic_os.cpp @@ -442,7 +442,7 @@ API String ReadFile(Allocator arena, String path) { } if (!success) { - Dealloc(arena, &result.data); + Dealloc(arena, result.data); result = {}; } @@ -566,7 +566,7 @@ API String GetExePath(Allocator allocator) { } API String GetExeDir(Allocator allocator) { - Scratch scratch((Arena *)allocator.object); + Scratch scratch(allocator); String path = GetExePath(scratch); path = ChopLastSlash(path); path = Copy(allocator, path); @@ -852,7 +852,7 @@ API String PollStdout(Allocator allocator, Process *process, bool force_read) { bool read_error = ReadFile(p->child_stdout_read, buffer, (DWORD)buffer_size, &bytes_read, 0) == 0; if (read_error) { Win32ReportError("Failed to read the stdout of child process", "ReadFile"); - Dealloc(allocator, &buffer); + Dealloc(allocator, buffer); Win32CloseProcess(process); return {}; } diff --git a/src/basic/basic_table.h b/src/basic/basic_table.h index 4bea136..2ceb158 100644 --- a/src/basic/basic_table.h +++ b/src/basic/basic_table.h @@ -51,7 +51,9 @@ struct HashTable { Assert(!(old_values == 0 && len != 0)); if (len == 0) { - if (old_values) Dealloc(allocator, &old_values); + if (old_values) { + Dealloc(allocator, old_values); + } return; } @@ -62,7 +64,7 @@ struct HashTable { insert(it->key, it->value); } } - Dealloc(allocator, &old_values); + Dealloc(allocator, old_values); } Entry *get_table_entry(uint64_t key) { @@ -177,7 +179,8 @@ struct HashTable { } void dealloc() { - Dealloc(allocator, &values); + Dealloc(allocator, values); + values = NULL; len = 0; cap = 0; } diff --git a/src/metaprogram/metaprogram.cpp b/src/metaprogram/metaprogram.cpp index 064af49..8a23eee 100644 --- a/src/metaprogram/metaprogram.cpp +++ b/src/metaprogram/metaprogram.cpp @@ -38,8 +38,6 @@ void Test() { } int main() { - InitScratch(); - Scratch scratch; String data = ReadFile(scratch, "../data/init.lua"); Array array = {scratch}; diff --git a/src/render/opengl.cpp b/src/render/opengl.cpp index 49b6f38..c5ca191 100644 --- a/src/render/opengl.cpp +++ b/src/render/opengl.cpp @@ -27,7 +27,7 @@ int64_t TotalVertexCount; unsigned VBO, VAO; Shader Shader2D; -Arena RenderArena; +BlockArena RenderArena; Rect2 CurrentScissor; Font MainFont; @@ -139,12 +139,6 @@ Shader CreateShaderES3(const char *vsrc, const char *fsrc) { // ---------- InitRender for ES3 ---------- void InitRender() { -#if OS_WASM - RenderArena = *AllocArena(GetSystemAllocator(), MiB(64)); -#else - InitArena(&RenderArena); -#endif - #if !OS_WASM glDebugMessageCallback(&GLDebugCallback, NULL); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); @@ -184,7 +178,7 @@ void InitRender() { } void BeginFrameRender(float wx, float wy) { - Clear(&RenderArena); + Release(&RenderArena); TotalVertexCount = 0; Vertices.first = NULL; Vertices.last = NULL; @@ -392,8 +386,6 @@ void DrawCircle(Vec2 pos, float radius, Color color) { } } - -// ---------- ReloadFont - replace DSA texture calls ---------- void ReloadFont() { Int size = StyleFontSize; size = ClampBottom((Int)2, size); diff --git a/src/text_editor/buffer.cpp b/src/text_editor/buffer.cpp index a12b106..161fb17 100644 --- a/src/text_editor/buffer.cpp +++ b/src/text_editor/buffer.cpp @@ -628,7 +628,7 @@ void RawGrow(Buffer *buffer, Int change_size) { Int new_cap = (buffer->cap + outside) * 2; U16 *new_array = AllocArray(alo, U16, new_cap); MemoryCopy(new_array, buffer->data, buffer->len * sizeof(U16)); - Dealloc(alo, &buffer->data); + Dealloc(alo, buffer->data); buffer->cap = new_cap; buffer->data = new_array; } @@ -884,12 +884,10 @@ API void ApplyEditsMultiCursor(Buffer *buffer, Array edits) { #endif // We need to sort from lowest to highest based on range.min - { - Scratch scratch((Arena *)buffer->line_starts.allocator.object); - Array edits_copy = TightCopy(scratch, edits); - if (edits.len > 1) MergeSort(edits.len, edits_copy.data, edits.data); - edits = edits_copy; - } + Scratch scratch(buffer->line_starts.allocator); + Array edits_copy = TightCopy(scratch, edits); + if (edits.len > 1) MergeSort(edits.len, edits_copy.data, edits.data); + edits = edits_copy; #if BUFFER_DEBUG for (int64_t i = 0; i < edits.len - 1; i += 1) { @@ -973,7 +971,7 @@ API void RedoEdit(Buffer *buffer, Array *carets) { *carets = entry.carets; Allocator sys_allocator = GetSystemAllocator(); - For(entry.edits) Dealloc(sys_allocator, &it.string.data); + For(entry.edits) Dealloc(sys_allocator, it.string.data); Dealloc(&entry.edits); } @@ -992,14 +990,14 @@ API void UndoEdit(Buffer *buffer, Array *carets) { *carets = entry.carets; Allocator sys_allocator = GetSystemAllocator(); - For(entry.edits) Dealloc(sys_allocator, &it.string.data); + For(entry.edits) Dealloc(sys_allocator, it.string.data); Dealloc(&entry.edits); } API void DeallocHistoryEntries(Array *entries) { For(*entries) { Dealloc(&it.carets); - ForItem(edit, it.edits) Dealloc(it.edits.allocator, &edit.string.data); + ForItem(edit, it.edits) Dealloc(it.edits.allocator, edit.string.data); Dealloc(&it.edits); } entries->len = 0; @@ -1175,15 +1173,23 @@ API void DeinitBuffer(Buffer *buffer) { Assert(buffer->next == NULL); Assert(buffer->prev == NULL); Allocator allocator = buffer->line_starts.allocator; - Dealloc(allocator, &buffer->data); + Dealloc(allocator, buffer->data); Dealloc(&buffer->line_starts); DeallocHistoryArray(&buffer->undo_stack); DeallocHistoryArray(&buffer->redo_stack); } +API Buffer *CreateTempBuffer(Allocator allocator, Int size = 4096) { + Buffer *result = AllocType(allocator, Buffer); + result->no_history = true; + result->no_line_starts = true; + InitBuffer(allocator, result, {}, "*temp*", size); + return result; +} + void TestBuffer() { - Scratch scratch; { + Scratch scratch; Buffer buffer = {}; InitBuffer(scratch, &buffer); Assert(buffer.line_starts.len == 1); @@ -1259,6 +1265,7 @@ void TestBuffer() { } { + Scratch scratch; Buffer buffer = {}; InitBuffer(scratch, &buffer); RawReplaceText(&buffer, {}, u"Thing\nmeme"); @@ -1272,7 +1279,9 @@ void TestBuffer() { RawValidateLineStarts(&buffer); } + // Make sure all the line starts are properly created { + Scratch scratch; Buffer buffer = {}; InitBuffer(scratch, &buffer); RawReplaceText(&buffer, {}, u"Thing\nmeme"); @@ -1293,7 +1302,9 @@ void TestBuffer() { RawValidateLineStarts(&buffer); } + // Basic case make sure no leaks { + Scratch scratch; Buffer buffer = {}; InitBuffer(GetTrackingAllocator(), &buffer); RawReplaceText(&buffer, {}, u"Thing\nmeme"); @@ -1302,8 +1313,9 @@ void TestBuffer() { TrackingAllocatorCheck(); } - // + // Testing Edit API and making sure no leaks { + Scratch scratch; Buffer buffer = {}; InitBuffer(GetTrackingAllocator(), &buffer); RawReplaceText(&buffer, {}, u"Testing\nthings"); @@ -1325,6 +1337,7 @@ void TestBuffer() { // Make sure no_history and no line_starts properly makes sure of these { + Scratch scratch; Buffer buffer = {}; buffer.no_history = true; buffer.no_line_starts = true; diff --git a/src/text_editor/commands_clipboard.cpp b/src/text_editor/commands_clipboard.cpp index 22da574..1caf245 100644 --- a/src/text_editor/commands_clipboard.cpp +++ b/src/text_editor/commands_clipboard.cpp @@ -21,14 +21,15 @@ EM_ASYNC_JS(const char *, GetClipboardText, (), { void SetClipboardText(String16 string16) { String string = ToString(SysAllocator, string16); - defer { Dealloc(SysAllocator, &string.data); }; + defer { Dealloc(SysAllocator, string.data); }; _SetClipboardText(string.data); } void FreeClipboardGlobals() { - For(SavedClipboardCarets) Dealloc(SysAllocator, &it.data); + For(SavedClipboardCarets) Dealloc(SysAllocator, it.data); SavedClipboardCarets.len = 0; - Dealloc(SysAllocator, &SavedClipboardString.data); + Dealloc(SysAllocator, SavedClipboardString.data); + SavedClipboardString = {}; } void SaveStringInClipboard(String16 string) { @@ -69,7 +70,7 @@ void Command_Paste(View *view) { defer { FreeClipboardText((void *)text); }; String16 string = ToUnixString16(SysAllocator, text); - defer { Dealloc(SysAllocator, &string.data); }; + defer { Dealloc(SysAllocator, string.data); }; // Regular paste if (string != SavedClipboardString || SavedClipboardCarets.len != view->carets.len) { diff --git a/src/text_editor/intern_table.cpp b/src/text_editor/intern_table.cpp index c6a921c..5f68f03 100644 --- a/src/text_editor/intern_table.cpp +++ b/src/text_editor/intern_table.cpp @@ -1,17 +1,12 @@ struct InternTable { - HashTable strings; - Arena *arena; + HashTable strings; // general allocator + BlockArena arena; }; String Intern(InternTable *table, String string) { - Allocator sys_allocator = GetSystemAllocator(); - if (table->arena == NULL) { - table->arena = AllocArena(sys_allocator, MiB(8)); - table->strings.allocator = *table->arena; - } String *value = table->strings.get(string); if (!value) { - String copy = Copy(*table->arena, string); + String copy = Copy(table->arena, string); table->strings.put(copy, copy); return copy; } diff --git a/src/text_editor/management.cpp b/src/text_editor/management.cpp index 1e464cf..feab51e 100644 --- a/src/text_editor/management.cpp +++ b/src/text_editor/management.cpp @@ -160,8 +160,8 @@ void DeallocBuffer(Buffer *buffer) { Dealloc(&buffer->line_starts); DeallocHistoryArray(&buffer->undo_stack); DeallocHistoryArray(&buffer->redo_stack); - DeallocEx(buffer->line_starts.allocator, buffer->data); - DeallocEx(buffer->line_starts.allocator, buffer); + Dealloc(buffer->line_starts.allocator, buffer->data); + Dealloc(buffer->line_starts.allocator, buffer); } Buffer *CreateBuffer(Allocator allocator, String name, Int size) { @@ -172,14 +172,6 @@ Buffer *CreateBuffer(Allocator allocator, String name, Int size) { return result; } -Buffer *CreateTempBuffer(Allocator allocator, Int size = 4096) { - Buffer *result = AllocType(allocator, Buffer); - result->no_history = true; - result->no_line_starts = true; - InitBuffer(allocator, result, "*temp*", size); - return result; -} - Window *CreateWind(bool create_command_buffer = true) { Window *w = AllocType(SysAllocator, Window); w->visible = true; @@ -540,7 +532,7 @@ void GarbageCollect() { } Dealloc(&it->carets); - DeallocEx(sys_allocator, it); + Dealloc(sys_allocator, it); DLL_QUEUE_REMOVE(FirstView, LastView, it); } diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index 4289c17..060a138 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -376,6 +376,7 @@ void MainLoop() { SDL_GL_SwapWindow(SDLWindow); } + #if _WIN32 int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) #else @@ -386,14 +387,15 @@ int main(int argc, char **argv) #if _WIN32 int argc = __argc; char **argv = __argv; + AttachConsole(ATTACH_PARENT_PROCESS); #endif BeginProfiler(); - InitScratch(); if (1) { + TestArena(); TestBuffer(); - ReportErrorf("Testing DONE\n"); - return 0; + // ReportErrorf("Testing DONE\n"); + // return 0; } #if !OS_WINDOWS diff --git a/src/text_editor/text_editor.h b/src/text_editor/text_editor.h index 8acd828..8fffd4c 100644 --- a/src/text_editor/text_editor.h +++ b/src/text_editor/text_editor.h @@ -101,7 +101,7 @@ struct BSet { // Dont use it Int FrameID; -Allocator SysAllocator = {SystemAllocator_Alloc}; +Allocator SysAllocator = {SystemAllocatorProc}; String ConfigDir; float DPIScale = 1.0f;