From eed873c6ec9ac1631fbf1285d4047596b353e9bf Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Wed, 5 Jul 2017 13:51:25 +0100 Subject: [PATCH] Add `free` for maps (a previous oversight) --- core/_preload.odin | 181 +++++++++++++++++-------------------------- core/hash.odin | 6 +- core/mem.odin | 9 ++- core/os_windows.odin | 10 +-- core/strings.odin | 4 +- src/checker.cpp | 15 ++-- src/common.cpp | 176 +++++++++++++++++++++++++++-------------- src/ir.cpp | 19 ++--- 8 files changed, 223 insertions(+), 197 deletions(-) diff --git a/core/_preload.odin b/core/_preload.odin index 32c01635c..bc1973703 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -117,6 +117,39 @@ __type_table: []TypeInfo; __argv__: ^^u8; __argc__: i32; +// IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it) +AllocatorMode :: enum u8 { + Alloc, + Free, + FreeAll, + Resize, +} +AllocatorProc :: proc(allocator_data: rawptr, mode: AllocatorMode, + size, alignment: int, + old_memory: rawptr, old_size: int, flags: u64 = 0) -> rawptr; +Allocator :: struct #ordered { + procedure: AllocatorProc, + data: rawptr, +} + + +Context :: struct #ordered { + thread_id: int, + + allocator: Allocator, + + user_data: rawptr, + user_index: int, +} + +DEFAULT_ALIGNMENT :: align_of([vector 4]f32); + +SourceCodeLocation :: struct { + fully_pathed_filename: string, + line, column: i64, + procedure: string, +} + __INITIAL_MAP_CAP :: 16; @@ -181,48 +214,14 @@ foreign __llvm_core { read_cycle_counter :: proc() -> u64 #link_name "llvm.readcyclecounter" ---; } -// IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it) -AllocatorMode :: enum u8 { - Alloc, - Free, - FreeAll, - Resize, -} -AllocatorProc :: proc(allocator_data: rawptr, mode: AllocatorMode, - size, alignment: int, - old_memory: rawptr, old_size: int, flags: u64 = 0) -> rawptr; -Allocator :: struct #ordered { - procedure: AllocatorProc, - data: rawptr, -} -Context :: struct #ordered { - thread_id: int, - - allocator: Allocator, - - user_data: rawptr, - user_index: int, -} - -// #thread_local var __context: Context; - - - -SourceCodeLocation :: struct { - fully_pathed_filename: string, - line, column: i64, - procedure: string, -} - make_source_code_location :: proc(file: string, line, column: i64, procedure: string) -> SourceCodeLocation #cc_contextless #inline { return SourceCodeLocation{file, line, column, procedure}; } -DEFAULT_ALIGNMENT :: align_of([vector 4]f32); __init_context_from_ptr :: proc(c: ^Context, other: ^Context) #cc_contextless { if c == nil do return; @@ -255,35 +254,25 @@ __check_context :: proc() { */ alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline { - // __check_context(); a := context.allocator; return a.procedure(a.data, AllocatorMode.Alloc, size, alignment, nil, 0, 0); } free_ptr_with_allocator :: proc(a: Allocator, ptr: rawptr) #inline { - if ptr == nil { - return; - } - if a.procedure == nil { - return; - } + if ptr == nil do return; + if a.procedure == nil do return; a.procedure(a.data, AllocatorMode.Free, 0, 0, ptr, 0, 0); } -free_ptr :: proc(ptr: rawptr) #inline { - // __check_context(); - free_ptr_with_allocator(context.allocator, ptr); -} +free_ptr :: proc(ptr: rawptr) #inline do free_ptr_with_allocator(context.allocator, ptr); free_all :: proc() #inline { - // __check_context(); a := context.allocator; a.procedure(a.data, AllocatorMode.FreeAll, 0, 0, nil, 0, 0); } resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline { - // __check_context(); a := context.allocator; return a.procedure(a.data, AllocatorMode.Resize, new_size, alignment, ptr, old_size, 0); } @@ -298,14 +287,12 @@ copy :: proc(dst, src: []$T) -> int #cc_contextless { append :: proc(array: ^[]$T, args: ..T) -> int { - if array == nil { - return 0; - } + if array == nil do return 0; + slice := ^raw.Slice(array); + arg_len := len(args); - if arg_len <= 0 { - return slice.len; - } + if arg_len <= 0 do return slice.len; arg_len = min(slice.cap-slice.len, arg_len); if arg_len > 0 { @@ -319,15 +306,12 @@ append :: proc(array: ^[]$T, args: ..T) -> int { } append :: proc(array: ^[dynamic]$T, args: ..T) -> int { - if array == nil { - return 0; - } + if array == nil do return 0; + a := ^raw.DynamicArray(array); arg_len := len(args); - if arg_len <= 0 { - return a.len; - } + if arg_len <= 0 do return a.len; ok := true; @@ -345,7 +329,7 @@ append :: proc(array: ^[dynamic]$T, args: ..T) -> int { return a.len; } -pop :: proc(array: ^[]$T) -> T { +pop :: proc(array: ^[]$T) -> T #cc_contextless { res: T; if array do return res; assert(len(array) > 0); @@ -354,7 +338,7 @@ pop :: proc(array: ^[]$T) -> T { return res; } -pop :: proc(array: ^[dynamic]$T) -> T { +pop :: proc(array: ^[dynamic]$T) -> T #cc_contextless { res: T; if array do return res; assert(len(array) > 0); @@ -384,7 +368,6 @@ reserve :: proc(array: ^[dynamic]$T, capacity: int) -> bool { if capacity <= a.cap do return true; - // __check_context(); if a.allocator.procedure == nil { a.allocator = context.allocator; } @@ -403,7 +386,7 @@ reserve :: proc(array: ^[dynamic]$T, capacity: int) -> bool { } -__get_map_header :: proc(m: ^map[$K]$V) -> __MapHeader { +__get_map_header :: proc(m: ^map[$K]$V) -> __MapHeader #cc_contextless { header := __MapHeader{m = ^raw.DynamicMap(m)}; Entry :: struct { key: __MapKey, @@ -419,9 +402,9 @@ __get_map_header :: proc(m: ^map[$K]$V) -> __MapHeader { return header; } -__get_map_key :: proc(key: $K) -> __MapKey { +__get_map_key :: proc(key: $K) -> __MapKey #cc_contextless { map_key: __MapKey; - ti := type_info(K); + ti := type_info_base_without_enum(type_info(K)); match { case types.is_integer(ti): match 8*size_of(key) { @@ -463,30 +446,16 @@ delete :: proc(m: ^map[$K]$V, key: K) { new :: proc(T: type) -> ^T #inline do return ^T(alloc(size_of(T), align_of(T))); +free :: proc(ptr: rawptr) do free_ptr(ptr); +free :: proc(str: string) do free_ptr(^raw.String(&str).data); free :: proc(array: [dynamic]$T) do free_ptr(^raw.DynamicArray(&array).data); free :: proc(slice: []$T) do free_ptr(^raw.Slice(&slice).data); -free :: proc(str: string) do free_ptr(^raw.String(&str).data); -free :: proc(ptr: rawptr) do free_ptr(ptr); - -slice_to_bytes :: proc(slice: []$T) -> []u8 { - s := ^raw.Slice(&slice); - s.len *= size_of(T); - s.cap *= size_of(T); - return ^[]u8(s)^; +free :: proc(m: map[$K]$V) { + raw := ^raw.DynamicMap(&m); + free(raw.hashes); + free(raw.entries.data); } -slice_ptr :: proc(ptr: ^$T, len: int) -> []T { - assert(0 <= len); - s := raw.Slice{ptr, len, len}; - return ^[]T(&s)^; -} -slice_ptr :: proc(ptr: ^$T, len, cap: int) -> []T { - assert(0 <= len && len <= cap); - s := raw.Slice{ptr, len, cap}; - return ^[]T(&s)^; -} - - default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr { if old_memory == nil do return alloc(new_size, alignment); @@ -625,14 +594,12 @@ __string_decode_rune :: proc(s: string) -> (rune, int) #cc_contextless #inline { __mem_set :: proc(data: rawptr, value: i32, len: int) -> rawptr #cc_contextless { when size_of(rawptr) == 8 { - foreign __llvm_core llvm_memset_64bit :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #link_name "llvm.memset.p0i8.i64" ---; - llvm_memset_64bit(data, u8(value), len, 1, false); - return data; + foreign __llvm_core llvm_memset :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #link_name "llvm.memset.p0i8.i64" ---; } else { - foreign __llvm_core llvm_memset_32bit :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #link_name "llvm.memset.p0i8.i32" ---; - llvm_memset_32bit(data, u8(value), len, 1, false); - return data; + foreign __llvm_core llvm_memset :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #link_name "llvm.memset.p0i8.i32" ---; } + llvm_memset(data, u8(value), len, 1, false); + return data; } __mem_zero :: proc(data: rawptr, len: int) -> rawptr #cc_contextless { return __mem_set(data, 0, len); @@ -640,26 +607,22 @@ __mem_zero :: proc(data: rawptr, len: int) -> rawptr #cc_contextless { __mem_copy :: proc(dst, src: rawptr, len: int) -> rawptr #cc_contextless { // NOTE(bill): This _must_ be implemented like C's memmove when size_of(rawptr) == 8 { - foreign __llvm_core llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memmove.p0i8.p0i8.i64" ---; - llvm_memmove_64bit(dst, src, len, 1, false); - return dst; + foreign __llvm_core llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memmove.p0i8.p0i8.i64" ---; } else { - foreign __llvm_core llvm_memmove_32bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memmove.p0i8.p0i8.i32" ---; - llvm_memmove_32bit(dst, src, len, 1, false); - return dst; + foreign __llvm_core llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memmove.p0i8.p0i8.i32" ---; } + llvm_memmove(dst, src, len, 1, false); + return dst; } __mem_copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #cc_contextless { // NOTE(bill): This _must_ be implemented like C's memcpy when size_of(rawptr) == 8 { - foreign __llvm_core llvm_memcpy_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i64" ---; - llvm_memcpy_64bit(dst, src, len, 1, false); - return dst; + foreign __llvm_core llvm_memcpy_ :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i64" ---; } else { - foreign __llvm_core llvm_memcpy_32bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i32"; - llvm_memcpy_32bit(dst, src, len, 1, false); - return dst; + foreign __llvm_core llvm_memcpy_ :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i32"; } + llvm_memcpy_(dst, src, len, 1, false); + return dst; } __mem_compare :: proc(a, b: ^u8, n: int) -> int #cc_contextless { @@ -702,7 +665,6 @@ __abs_complex128 :: proc(x: complex128) -> f64 #inline #cc_contextless { __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int) { array := ^raw.DynamicArray(array_); - // __check_context(); array.allocator = context.allocator; assert(array.allocator.procedure != nil); @@ -717,7 +679,6 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: if cap <= array.cap do return true; - // __check_context(); if array.allocator.procedure == nil { array.allocator = context.allocator; } @@ -866,8 +827,7 @@ __dynamic_map_get :: proc(h: __MapHeader, key: __MapKey) -> rawptr { index := __dynamic_map_find(h, key).entry_index; if index >= 0 { data := ^u8(__dynamic_map_get_entry(h, index)); - val := data + h.value_offset; - return val; + return data + h.value_offset; } return nil; } @@ -932,9 +892,7 @@ __dynamic_map_find :: proc(using h: __MapHeader, key: __MapKey) -> __MapFindResu fr.entry_index = m.hashes[fr.hash_index]; for fr.entry_index >= 0 { entry := __dynamic_map_get_entry(h, fr.entry_index); - if __dynamic_map_hash_equal(h, entry.key, key) { - return fr; - } + if __dynamic_map_hash_equal(h, entry.key, key) do return fr; fr.entry_prev = fr.entry_index; fr.entry_index = entry.next; } @@ -961,8 +919,7 @@ __dynamic_map_delete :: proc(using h: __MapHeader, key: __MapKey) { } __dynamic_map_get_entry :: proc(using h: __MapHeader, index: int) -> ^__MapEntryHeader { - data := ^u8(m.entries.data) + index*entry_size; - return ^__MapEntryHeader(data); + return ^__MapEntryHeader(^u8(m.entries.data) + index*entry_size); } __dynamic_map_erase :: proc(using h: __MapHeader, fr: __MapFindResult) { diff --git a/core/hash.odin b/core/hash.odin index cc262f7d8..ca1c6cbf7 100644 --- a/core/hash.odin +++ b/core/hash.odin @@ -1,3 +1,5 @@ +import "mem.odin"; + crc32 :: proc(data: []u8) -> u32 { result := ~u32(0); for b in data { @@ -102,7 +104,7 @@ murmur64 :: proc(data: []u8) -> u64 { r :: 47; h: u64 = SEED ~ (u64(len(data)) * m); - data64 := slice_ptr(^u64(&data[0]), len(data)/size_of(u64)); + data64 := mem.slice_ptr(^u64(&data[0]), len(data)/size_of(u64)); for _, i in data64 { k := data64[i]; @@ -138,7 +140,7 @@ murmur64 :: proc(data: []u8) -> u64 { h1 := u32(SEED) ~ u32(len(data)); h2 := u32(SEED) >> 32; - data32 := slice_ptr(^u32(&data[0]), len(data)/size_of(u32)); + data32 := mem.slice_ptr(^u32(&data[0]), len(data)/size_of(u32)); len := len(data); i := 0; diff --git a/core/mem.odin b/core/mem.odin index 6f9575322..dfd15c138 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -25,7 +25,7 @@ compare :: proc(a, b: []u8) -> int #cc_contextless { return __mem_compare(&a[0], &b[0], min(len(a), len(b))); } -/* + slice_ptr :: proc(ptr: ^$T, len: int) -> []T #cc_contextless { assert(len >= 0); slice := raw.Slice{data = ptr, len = len, cap = len}; @@ -43,7 +43,6 @@ slice_to_bytes :: proc(slice: []$T) -> []u8 #cc_contextless { s.cap *= size_of(T); return ^[]u8(s)^; } -*/ kilobytes :: proc(x: int) -> int #inline #cc_contextless { return (x) * 1024; } @@ -121,7 +120,7 @@ init_arena_from_context :: proc(using a: ^Arena, size: int) { temp_count = 0; } -free_arena :: proc(using a: ^Arena) { +destroy_arena :: proc(using a: ^Arena) { if backing.procedure != nil { push_allocator backing { free(memory); @@ -214,6 +213,8 @@ align_of_type_info :: proc(type_info: ^TypeInfo) -> int { return align_of_type_info(info.base); case Integer: return info.size; + case Rune: + return info.size; case Float: return info.size; case String: @@ -267,6 +268,8 @@ size_of_type_info :: proc(type_info: ^TypeInfo) -> int { return size_of_type_info(info.base); case Integer: return info.size; + case Rune: + return info.size; case Float: return info.size; case String: diff --git a/core/os_windows.odin b/core/os_windows.odin index ccc0eb9f8..443ab909d 100644 --- a/core/os_windows.odin +++ b/core/os_windows.odin @@ -57,9 +57,7 @@ args := _alloc_command_line_arguments(); open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errno) { - if len(path) == 0 { - return INVALID_HANDLE, ERROR_FILE_NOT_FOUND; - } + if len(path) == 0 do return INVALID_HANDLE, ERROR_FILE_NOT_FOUND; access: u32; match mode & (O_RDONLY|O_WRONLY|O_RDWR) { @@ -245,9 +243,7 @@ heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr { return win32.heap_realloc(win32.get_process_heap(), win32.HEAP_ZERO_MEMORY, ptr, new_size); } heap_free :: proc(ptr: rawptr) { - if ptr == nil { - return; - } + if ptr == nil do return; win32.heap_free(win32.get_process_heap(), 0, ptr); } @@ -272,7 +268,7 @@ _alloc_command_line_arguments :: proc() -> []string { len := 2*wstr_len-1; buf := make([]u8, len+1); - str := slice_ptr(wstr, wstr_len+1); + str := mem.slice_ptr(wstr, wstr_len+1); i, j := 0, 0; for str[j] != 0 { diff --git a/core/strings.odin b/core/strings.odin index a86b65f75..ddaeb4f96 100644 --- a/core/strings.odin +++ b/core/strings.odin @@ -1,3 +1,5 @@ +import "mem.odin"; + new_string :: proc(s: string) -> string { c := make([]u8, len(s)+1); copy(c, []u8(s)); @@ -15,5 +17,5 @@ new_c_string :: proc(s: string) -> ^u8 { to_odin_string :: proc(c: ^u8) -> string { len := 0; for (c+len)^ != 0 do len++; - return string(slice_ptr(c, len)); + return string(mem.slice_ptr(c, len)); } diff --git a/src/checker.cpp b/src/checker.cpp index 149435ed2..c66f9a63e 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -305,9 +305,10 @@ struct Checker { Array delayed_foreign_libraries; Array file_nodes; + Pool pool; + gbAllocator allocator; gbArena arena; gbArena tmp_arena; - gbAllocator allocator; gbAllocator tmp_allocator; CheckerContext context; @@ -773,11 +774,13 @@ void init_checker(Checker *c, Parser *parser) { total_token_count += f->tokens.count; } isize arena_size = 2 * item_size * total_token_count; - gb_arena_init_from_allocator(&c->arena, a, arena_size); gb_arena_init_from_allocator(&c->tmp_arena, a, arena_size); + gb_arena_init_from_allocator(&c->arena, a, arena_size); - - c->allocator = gb_arena_allocator(&c->arena); + pool_init(&c->pool, gb_megabytes(4), gb_kilobytes(384)); + // c->allocator = pool_allocator(&c->pool); + c->allocator = heap_allocator(); + // c->allocator = gb_arena_allocator(&c->arena); c->tmp_allocator = gb_arena_allocator(&c->tmp_arena); c->global_scope = make_scope(universal_scope, c->allocator); @@ -793,7 +796,9 @@ void destroy_checker(Checker *c) { array_free(&c->delayed_foreign_libraries); array_free(&c->file_nodes); - gb_arena_free(&c->arena); + pool_destroy(&c->pool); + gb_arena_free(&c->tmp_arena); + // gb_arena_free(&c->arena); } diff --git a/src/common.cpp b/src/common.cpp index 40386375d..54d80f1e7 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -23,6 +23,9 @@ gbAllocator heap_allocator(void) { #include "integer128.cpp" #include "murmurhash3.cpp" +#define for_array(index_, array_) for (isize index_ = 0; index_ < (array_).count; index_++) + + u128 fnv128a(void const *data, isize len) { u128 o = u128_lo_hi(0x13bull, 0x1000000ull); u128 h = u128_lo_hi(0x62b821756295c58dull, 0x6c62272e07bb0142ull); @@ -52,87 +55,145 @@ gbAllocator scratch_allocator(void) { return gb_scratch_allocator(&scratch_memory); } +struct Pool { + isize memblock_size; + isize out_of_band_size; + isize alignment; -struct DynamicArenaBlock { - DynamicArenaBlock *prev; - DynamicArenaBlock *next; - u8 * start; - isize count; - isize capacity; + Array unused_memblock; + Array used_memblock; + Array out_of_band_allocations; - gbVirtualMemory vm; + u8 * current_memblock; + u8 * current_pos; + isize bytes_left; + + gbAllocator block_allocator; }; -struct DynamicArena { - DynamicArenaBlock *start_block; - DynamicArenaBlock *current_block; - isize block_size; +enum { + POOL_BUCKET_SIZE_DEFAULT = 65536, + POOL_OUT_OF_BAND_SIZE_DEFAULT = 6554, }; -DynamicArenaBlock *add_dynamic_arena_block(DynamicArena *a) { - GB_ASSERT(a != NULL); - GB_ASSERT(a->block_size > 0); +void pool_init(Pool *pool, + isize memblock_size = POOL_BUCKET_SIZE_DEFAULT, + isize out_of_band_size = POOL_OUT_OF_BAND_SIZE_DEFAULT, + isize alignment = 8, + gbAllocator block_allocator = heap_allocator(), + gbAllocator array_allocator = heap_allocator()) { + pool->memblock_size = memblock_size; + pool->out_of_band_size = out_of_band_size; + pool->alignment = alignment; + pool->block_allocator = block_allocator; - gbVirtualMemory vm = gb_vm_alloc(NULL, a->block_size); - DynamicArenaBlock *block = cast(DynamicArenaBlock *)vm.data; + array_init(&pool->unused_memblock, array_allocator); + array_init(&pool->used_memblock, array_allocator); + array_init(&pool->out_of_band_allocations, array_allocator); +} - u8 *start = cast(u8 *)gb_align_forward(cast(u8 *)(block + 1), GB_DEFAULT_MEMORY_ALIGNMENT); - u8 *end = cast(u8 *)vm.data + vm.size; - - block->vm = vm; - block->start = start; - block->count = 0; - block->capacity = end-start; - - if (a->current_block != NULL) { - a->current_block->next = block; - block->prev = a->current_block; +void pool_free_all(Pool *p) { + if (p->current_memblock != NULL) { + array_add(&p->unused_memblock, p->current_memblock); + p->current_memblock = NULL; } - a->current_block = block; - return block; + + for_array(i, p->used_memblock) { + array_add(&p->unused_memblock, p->used_memblock[i]); + } + array_clear(&p->unused_memblock); + + for_array(i, p->out_of_band_allocations) { + gb_free(p->block_allocator, p->out_of_band_allocations[i]); + } + array_clear(&p->out_of_band_allocations); } -void init_dynamic_arena(DynamicArena *a, isize block_size) { - isize size = gb_size_of(DynamicArenaBlock) + block_size; - size = cast(isize)gb_align_forward(cast(void *)cast(uintptr)size, GB_DEFAULT_MEMORY_ALIGNMENT); - a->block_size = size; - a->start_block = add_dynamic_arena_block(a); -} +void pool_destroy(Pool *p) { + pool_free_all(p); -void destroy_dynamic_arena(DynamicArena *a) { - DynamicArenaBlock *b = a->current_block; - while (b != NULL) { - gbVirtualMemory vm = b->vm; - b = b->prev; - gb_vm_free(b->vm); + for_array(i, p->unused_memblock) { + gb_free(p->block_allocator, p->unused_memblock[i]); } } -GB_ALLOCATOR_PROC(dynamic_arena_allocator_proc) { - DynamicArena *a = cast(DynamicArena *)allocator_data; +void pool_cycle_new_block(Pool *p) { + GB_ASSERT_MSG(p->block_allocator.proc != NULL, + "You must call pool_init on a Pool before using it!"); + + if (p->current_memblock != NULL) { + array_add(&p->used_memblock, p->current_memblock); + } + + u8 *new_block = NULL; + + if (p->unused_memblock.count > 0) { + new_block = array_pop(&p->unused_memblock); + } else { + GB_ASSERT(p->block_allocator.proc != NULL); + new_block = cast(u8 *)gb_alloc_align(p->block_allocator, p->memblock_size, p->alignment); + } + + p->bytes_left = p->memblock_size; + p->current_memblock = new_block; + p->current_memblock = new_block; +} + +void *pool_get(Pool *p, + isize size, isize alignment = 0) { + if (alignment <= 0) alignment = p->alignment; + + isize extra = alignment - (size & alignment); + size += extra; + if (size >= p->out_of_band_size) { + GB_ASSERT(p->block_allocator.proc != NULL); + u8 *memory = cast(u8 *)gb_alloc_align(p->block_allocator, p->memblock_size, alignment); + if (memory != NULL) { + array_add(&p->out_of_band_allocations, memory); + } + return memory; + } + + if (p->bytes_left < size) { + pool_cycle_new_block(p); + if (p->current_memblock != NULL) { + return NULL; + } + } + + u8 *res = p->current_pos; + p->current_pos += size; + p->bytes_left -= size; + return res; +} + + +gbAllocator pool_allocator(Pool *pool); + +GB_ALLOCATOR_PROC(pool_allocator_procedure) { + Pool *p = cast(Pool *)allocator_data; void *ptr = NULL; switch (type) { - case gbAllocation_Alloc: { - - } break; - - case gbAllocation_Free: { - } break; - - case gbAllocation_Resize: { - } break; - - case gbAllocation_FreeAll: - GB_PANIC("free_all is not supported by this allocator"); + case gbAllocation_Alloc: + return pool_get(p, size, alignment); + case gbAllocation_Free: + // Does nothing break; + case gbAllocation_FreeAll: + pool_free_all(p); + break; + case gbAllocation_Resize: + return gb_default_resize_align(pool_allocator(p), old_memory, old_size, size, alignment); } return ptr; } -gbAllocator dynamic_arena_allocator(DynamicArena *a) { - gbAllocator allocator = {dynamic_arena_allocator_proc, a}; +gbAllocator pool_allocator(Pool *pool) { + gbAllocator allocator; + allocator.proc = pool_allocator_procedure; + allocator.data = pool; return allocator; } @@ -224,7 +285,6 @@ f64 gb_sqrt(f64 x) { -#define for_array(index_, array_) for (isize index_ = 0; index_ < (array_).count; index_++) // Doubly Linked Lists diff --git a/src/ir.cpp b/src/ir.cpp index 930132cce..fc4c97c9a 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -7123,20 +7123,21 @@ void ir_init_module(irModule *m, Checker *c) { // TODO(bill): Determine a decent size for the arena isize token_count = c->parser->total_token_count; isize arena_size = 4 * token_count * gb_size_of(irValue); - gb_arena_init_from_allocator(&m->arena, heap_allocator(), arena_size); + gb_arena_init_from_allocator(&m->arena, heap_allocator(), arena_size); gb_arena_init_from_allocator(&m->tmp_arena, heap_allocator(), arena_size); - m->allocator = gb_arena_allocator(&m->arena); + // m->allocator = gb_arena_allocator(&m->arena); + m->allocator = heap_allocator(); m->tmp_allocator = gb_arena_allocator(&m->tmp_arena); m->info = &c->info; - map_init(&m->values, heap_allocator()); - map_init(&m->members, heap_allocator()); - map_init(&m->debug_info, heap_allocator()); - map_init(&m->entity_names, heap_allocator()); - array_init(&m->procs, heap_allocator()); - array_init(&m->procs_to_generate, heap_allocator()); + map_init(&m->values, heap_allocator()); + map_init(&m->members, heap_allocator()); + map_init(&m->debug_info, heap_allocator()); + map_init(&m->entity_names, heap_allocator()); + array_init(&m->procs, heap_allocator()); + array_init(&m->procs_to_generate, heap_allocator()); array_init(&m->foreign_library_paths, heap_allocator()); - map_init(&m->const_strings, heap_allocator()); + map_init(&m->const_strings, heap_allocator()); // Default states m->stmt_state_flags = 0;