Allocator logging

This commit is contained in:
Krzosa Karol
2022-05-13 20:36:42 +02:00
parent 2689aa9ba1
commit ea0b1c352d
5 changed files with 180 additions and 102 deletions

202
main.cpp
View File

@@ -151,6 +151,36 @@ wrap_around_pow2(U64 x, U64 power_of_2) {
return r;
}
function B32
string_compare(String a, String b){
if(a.len != b.len)
return false;
for(S64 i = 0; i < a.len; i++){
if(a.str[i] != b.str[i])
return false;
}
return true;
}
function U8
char_to_lower(U8 c){
if(c >= 'A' && c <= 'Z')
c += 32;
return c;
}
function U8
char_to_upper(U8 c){
if(c >= 'a' && c <= 'z')
c -= 32;
return c;
}
force_inline String
operator""_s(const char *str, size_t size){
return String{(U8 *)str, (S64)size};
}
//-----------------------------------------------------------------------------
// OS Memory
//-----------------------------------------------------------------------------
@@ -245,7 +275,7 @@ test_os_memory(){
enum Allocation_Kind{Allocation_Alloc,Allocation_Resize,Allocation_FreeAll,Allocation_Free,Allocation_Destroy};
struct Allocator;
typedef void *Allocator_Proc(Allocator*, Allocation_Kind, void *, SizeU);
struct Allocator{Allocator_Proc *proc;};
struct Allocator{Allocator_Proc *proc; String debug_name;};
//-----------------------------------------------------------------------------
// Memory arenas
@@ -259,7 +289,7 @@ struct Arena:Allocator{
SizeU len;
};
function void arena_init(Arena *arena);
function void arena_init(Arena *arena, String debug_name);
function void
arena_pop_pos(Arena *arena, SizeU pos){
@@ -282,7 +312,7 @@ arena_push_size(Arena *a, SizeU size){
SizeU generous_size = size + a->alignment;
if(a->len+generous_size>a->memory.commit){
if(a->memory.reserve == 0){
arena_init(a);
arena_init(a, "Zero initialized arena"_s);
}
B32 result = os_commit(&a->memory, generous_size+additional_commit_size);
assert(result);
@@ -305,7 +335,7 @@ arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, Size
memory_copy(result, old_pointer, size);
return result;
}
case Allocation_Free : invalid_codepath; return 0;
case Allocation_Free : return 0;
case Allocation_FreeAll: arena_clear(arena); return 0;
case Allocation_Destroy: arena_release(arena); return 0;
}
@@ -321,17 +351,18 @@ personal_arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_poin
}
function void
arena_init(Arena *a){
a->memory = os_reserve(default_reserve_size);
a->alignment = default_alignment;
arena_init(Arena *a, String debug_name){
a->memory = os_reserve(default_reserve_size);
a->alignment = default_alignment;
a->debug_name = debug_name;
if(!a->proc) a->proc = arena_allocator_proc;
}
function Arena
arena_make_personal(){
arena_make_personal(String debug_name){
Arena arena = {};
arena.proc = personal_arena_allocator_proc;
arena_init(&arena);
arena_init(&arena, debug_name);
return arena;
}
@@ -397,11 +428,25 @@ struct Thread_Ctx{
void *ctx;
U64 ctx_id;
Log_Proc *log_proc;
int line;
char *file;
};
thread_local Thread_Ctx thread_ctx;
global Arena pernament_arena;
global OS_Heap os_process_heap;
#define report_file_and_line() report__file_and_line(__FILE__, __LINE__)
#define DEBUG_TRACE(x) (report_file_and_line(), (x))
function void
report__file_and_line(const char *file, int line){
thread_ctx.file = (char *)file;
thread_ctx.line = line;
}
//-----------------------------------------------------------------------------
// Implicit scratch stack
//-----------------------------------------------------------------------------
#define Set_Scratch() Scoped_Scratch scratch_##__LINE__
#define Set_Backup_Scratch() Scoped_Scratch scratch_##__LINE__(true)
struct Scoped_Scratch{
@@ -422,6 +467,9 @@ struct Scoped_Scratch{
}
};
//-----------------------------------------------------------------------------
// Implicit allocator stack
//-----------------------------------------------------------------------------
#define Set_Allocator(a) Scoped_Allocator scoped_##__LINE__(a)
struct Scoped_Allocator{
Allocator *allocator;
@@ -442,6 +490,7 @@ thread_ctx_get_user_ctx(U64 id){
assert(thread_ctx.ctx != 0);
return thread_ctx.ctx;
}
#define Get_Ctx(T) T *ctx = (T *)thread_ctx_get_user_ctx(T##_ID)
#define Set_Ctx(ctx, id) Scoped_Ctx scoped_ctx_##__LINE__((void *)ctx, id)
struct Scoped_Ctx{
@@ -456,55 +505,80 @@ struct Scoped_Ctx{
~Scoped_Ctx(){thread_ctx.ctx = prev_ctx; thread_ctx.ctx_id = prev_id;}
};
enum Alloc_Flag{AF_None,AF_ZeroMemory};
//-----------------------------------------------------------------------------
// Explicit allocator
//-----------------------------------------------------------------------------
#define exp_alloc_array(a, T, size,...) (T *)exp_alloc(a, sizeof(T)*(size), ## __VA_ARGS__)
#define exp_alloc_type(a, T, ...) exp_alloc_array(a, T, 1, ## __VA_ARGS__)
#define exp_resize_array(a, p, T, size, ...) (T *)exp_resize(a, p, sizeof(T)*(size),## __VA_ARGS__)
#define exp_alloc(a, size, ...) DEBUG_TRACE(exp__alloc(a, size, ## __VA_ARGS__))
#define exp_resize(a,p,size) DEBUG_TRACE(exp__resize(a, p, size))
#define exp_resize_array(a, p, T, size) DEBUG_TRACE((T *)exp_resize(a, p, sizeof(T)*(size)))
#define exp_free(a, p) DEBUG_TRACE(exp__free(a, p))
#define exp_free_all(a) DEBUG_TRACE(exp__free_all(a))
#define exp_destroy(a) DEBUG_TRACE(exp__destroy(a))
#include <stdio.h>
force_inline void *
exp_alloc(Allocator *a, SizeU size, Alloc_Flag flag = AF_None){
exp__alloc(Allocator *a, SizeU size, Alloc_Flag flag = AF_None){
printf("Alloc(%s) %s:%d %u\n", a->debug_name.str, thread_ctx.file, thread_ctx.line, (U32)size);
void *result = a->proc(a, Allocation_Alloc, 0, size);
if(flag & AF_ZeroMemory) memory_zero(result, size);
return result;
}
force_inline void *
exp_resize(Allocator *a, void *pointer, SizeU size){
exp__resize(Allocator *a, void *pointer, SizeU size){
printf("Resize(%s) %s:%d %u\n", a->debug_name.str, thread_ctx.file, thread_ctx.line, (U32)size);
return a->proc(a, Allocation_Resize, pointer, size);
}
force_inline void
exp_free(Allocator *a, void *pointer){
exp__free(Allocator *a, void *pointer){
printf("Free(%s) %s:%d\n", a->debug_name.str, thread_ctx.file, thread_ctx.line);
a->proc(a, Allocation_Free, pointer, 0);
}
force_inline void
exp_free_all(Allocator *a){
exp__free_all(Allocator *a){
printf("FreeAll(%s) %s:%d\n", a->debug_name.str, thread_ctx.file, thread_ctx.line);
a->proc(a, Allocation_FreeAll, 0, 0);
}
force_inline void
exp_destroy(Allocator *a){
exp__destroy(Allocator *a){
printf("Destroy(%s) %s:%d\n", a->debug_name.str, thread_ctx.file, thread_ctx.line);
a->proc(a, Allocation_Destroy, 0, 0);
}
#define imp_alloc_array(T,size,...) (T *)imp_alloc(sizeof(T) * (size),##__VA_ARGS__)
#define imp_alloc_type (T,...) imp_alloc_array(T,1,## __VA_ARGS__)
#define imp_resize_array(p, T,size, ...) (T *)imp_resize(p, sizeof(T) * (size),##__VA_ARGS__)
//-----------------------------------------------------------------------------
// Implicit allocator
//-----------------------------------------------------------------------------
#define imp_alloc_array(T,size,...) (T *)imp_alloc(sizeof(T) * (size), ##__VA_ARGS__)
#define imp_alloc_type (T,...) imp_alloc_array(T,1, ## __VA_ARGS__)
#define imp_alloc(size,...) DEBUG_TRACE(imp__alloc(size, ##__VA_ARGS__))
#define imp_resize_array(p, T,size, ...) (T *)imp_resize(p, sizeof(T) * (size), ##__VA_ARGS__)
#define imp_resize(p,size) DEBUG_TRACE(imp_resize(p, size))
#define imp_free(p) DEBUG_TRACE(imp__free(p))
#define imp_free_all() DEBUG_TRACE(imp__free_all())
#define imp_destroy() DEBUG_TRACE(imp__destroy())
force_inline void *
imp_alloc(SizeU size, Alloc_Flag flag=AF_None){
return exp_alloc(thread_ctx.implicit_allocator, size, flag);
imp__alloc(SizeU size, Alloc_Flag flag=AF_None){
return exp__alloc(thread_ctx.implicit_allocator, size, flag);
}
force_inline void *
imp_resize(void *pointer, SizeU size){
return exp_resize(thread_ctx.implicit_allocator, pointer, size);
imp__resize(void *pointer, SizeU size){
return exp__resize(thread_ctx.implicit_allocator, pointer, size);
}
force_inline void
imp_free(void *pointer){
exp_free(thread_ctx.implicit_allocator, pointer);
imp__free(void *pointer){
exp__free(thread_ctx.implicit_allocator, pointer);
}
force_inline void
imp_free_all(){
exp_free_all(thread_ctx.implicit_allocator);
imp__free_all(){
exp__free_all(thread_ctx.implicit_allocator);
}
force_inline void
imp_destroy(){
exp_destroy(thread_ctx.implicit_allocator);
imp__destroy(){
exp__destroy(thread_ctx.implicit_allocator);
}
force_inline Allocator *
@@ -515,12 +589,14 @@ imp_get(){
function void
thread_ctx_init(){
arena_init(thread_ctx.scratch);
arena_init(thread_ctx.scratch+1);
arena_init(&pernament_arena);
os_process_heap.proc = os_heap_allocator_proc;
os_process_heap.handle = GetProcessHeap();
thread_ctx.implicit_allocator = &os_process_heap;
arena_init(thread_ctx.scratch, "Scratch1"_s);
arena_init(thread_ctx.scratch+1, "Scratch2"_s);
arena_init(&pernament_arena, "Pernament Arena"_s);
os_process_heap.proc = os_heap_allocator_proc;
os_process_heap.handle = GetProcessHeap();
os_process_heap.debug_name = "Win32 Process Heap"_s;
thread_ctx.implicit_allocator = &os_process_heap;
}
function String
@@ -546,10 +622,10 @@ string_fmtv(Allocator *a, const char *str, va_list args1) {
return res;
}
#define STRING_FMT(alloc, str, result) \
va_list args1; \
va_start(args1, str); \
String result = string_fmtv(alloc, str, args1); \
#define STRING_FMT(alloc, str, result) \
va_list args1; \
va_start(args1, str); \
String result = string_fmtv(alloc, str, args1); \
va_end(args1)
function String
@@ -573,6 +649,7 @@ handle_log_message(Log_Kind kind, int line, const char *file, const char *str, .
function void
test_heap_allocator(){
OS_Heap heap = win32_os_heap_create(false, mib(1), 0);
heap.debug_name = "Test heap"_s;
Set_Allocator(&heap);
assert(thread_ctx.implicit_allocator == &heap);
@@ -665,9 +742,9 @@ struct Array{
init(cap);
}
else if(len + required_size > cap){
S64 cap = (len + required_size)*2;
data = exp_resize_array(allocator, data, T, cap);
cap = cap;
U64 new_cap = max(cap * 2, len+required_size+1);
data = exp_resize_array(allocator, data, T, new_cap);
cap = new_cap;
}
}
@@ -676,11 +753,6 @@ struct Array{
data[len++] = item;
}
void add(T *item){
grow(1);
data[len++] = *item;
}
void clear(){
len = 0;
}
@@ -712,7 +784,7 @@ test_array(){
assert(*it == i);
}
Arena arena = arena_make_personal();
Arena arena = arena_make_personal("Test personal arena"_s);
Array<int> array2 = {};
array2.allocator = &arena;
for(int i = 0; i < size; i++){
@@ -760,7 +832,7 @@ map_grow(Map *map, S64 new_size){
map_insert_u64(&new_map, map->data[i].key, map->data[i].value);
}
}
if(map->data) free(map->data);
if(map->data) exp_free(map->allocator, map->data);
*map = new_map;
}
@@ -834,6 +906,7 @@ map_insert(Map *map, void *key, void *value){
function void
map_test(){
Set_Scratch();
Map map = {0};
const SizeU size = 1025;
for(SizeU i = 1; i < size; i++){
@@ -874,7 +947,6 @@ if(l){\
//-----------------------------------------------------------------------------
// String builder
//-----------------------------------------------------------------------------
#include <stdio.h>
struct String_Builder_Block{
String_Builder_Block *next;
S64 cap;
@@ -951,36 +1023,6 @@ string_flatten(String_Builder *b){
return result;
}
function B32
string_compare(String a, String b){
if(a.len != b.len)
return false;
for(S64 i = 0; i < a.len; i++){
if(a.str[i] != b.str[i])
return false;
}
return true;
}
function U8
char_to_lower(U8 c){
if(c >= 'A' && c <= 'Z')
c += 32;
return c;
}
function U8
char_to_upper(U8 c){
if(c >= 'a' && c <= 'z')
c -= 32;
return c;
}
force_inline String
operator""_s(const char *str, size_t size){
return String{(U8 *)str, (S64)size};
}
function void
test_string_builder(){
Set_Scratch();
@@ -1053,12 +1095,12 @@ int main(){
test_os_memory();
thread_ctx_init();
map_test();
test_parse_decl();
test_parse_expr();
test_array();
map_test();
test_string_builder();
test_intern_table();
lex_test();