Working on simplifying the allocation scheme

This commit is contained in:
Krzosa Karol
2023-01-01 10:48:06 +01:00
parent d10b72057e
commit 8c0a8bf72b
9 changed files with 126 additions and 98 deletions

View File

@@ -517,6 +517,17 @@ arena_init(Arena *a, String debug_name){
a->deallocate = (Allocator::Deallocate *)deallocate_stub; a->deallocate = (Allocator::Deallocate *)deallocate_stub;
} }
CORE_Static Arena
arena_sub(Arena *base, size_t size, String debug_name) {
Arena result = {};
result.memory.data = (U8 *)arena_push_size(base, size);
result.memory.commit = size;
result.memory.reserve = size;
result.alignment = default_alignment;
result.len = 0;
return result;
}
enum Log_Kind{Log_Kind_Normal_No_NewLine, Log_Kind_Normal, Log_Kind_Error, Log_Kind_Trace}; enum Log_Kind{Log_Kind_Normal_No_NewLine, Log_Kind_Normal, Log_Kind_Error, Log_Kind_Trace};
typedef void Log_Proc(Log_Kind kind, String string, char *file, int line); typedef void Log_Proc(Log_Kind kind, String string, char *file, int line);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -652,7 +663,7 @@ struct Array{
cap = size; cap = size;
} }
Array<T> copy(Arena *a){ Array<T> copy(Allocator *a){
Array<T> result = {}; Array<T> result = {};
result.len = len; result.len = len;
result.cap = len*2; result.cap = len*2;
@@ -662,7 +673,7 @@ struct Array{
return result; return result;
} }
Array<T> tight_copy(Arena *a){ Array<T> tight_copy(Allocator *a){
Array<T> result = {}; Array<T> result = {};
result.len = len; result.len = len;
result.cap = len; result.cap = len;
@@ -952,17 +963,6 @@ test_intern_table(){
assert(intern3.str != intern2.str); assert(intern3.str != intern2.str);
} }
CORE_Static Arena
arena_sub(Arena *base, size_t size, String debug_name) {
Arena result = {};
result.memory.data = (U8 *)arena_push_size(base, size);
result.memory.commit = size;
result.memory.reserve = size;
result.alignment = default_alignment;
result.len = 0;
return result;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Array List // Array List
// @todo(krzosa): If even one item got removed from block // @todo(krzosa): If even one item got removed from block
@@ -990,21 +990,23 @@ struct List{
}; };
template<class T> template<class T>
List_Node<T> *list_allocate_node(Arena *arena, int size){ List_Node<T> *list_allocate_node(Allocator *arena, int size){
auto node = (List_Node<T> *)arena_push_size(arena, sizeof(List_Node<T>) + size*sizeof(T)); auto node = (List_Node<T> *)allocate_size(arena, sizeof(List_Node<T>) + size*sizeof(T), false);
node->cap = size; node->cap = size;
node->len = 0; node->len = 0;
node->next = 0;
node->prev = 0;
return node; return node;
} }
template<class T> template<class T>
void list_allocate_free_node(Arena *arena, List<T> *list, int size){ void list_allocate_free_node(Allocator *arena, List<T> *list, int size){
List_Node<T> *node = list_allocate_node<T>(arena, size); List_Node<T> *node = list_allocate_node<T>(arena, size);
DLL_STACK_ADD(list->first_free, node); DLL_STACK_ADD(list->first_free, node);
} }
template<class T> template<class T>
void list_make_sure_there_is_room_for_item_count(Arena *arena, List<T> *list, int item_count){ void list_make_sure_there_is_room_for_item_count(Allocator *arena, List<T> *list, int item_count){
if(list->last == 0 || list->last->len + item_count > list->last->cap){ if(list->last == 0 || list->last->len + item_count > list->last->cap){
// Not enough space we need to get a new block // Not enough space we need to get a new block
List_Node<T> *node = 0; List_Node<T> *node = 0;
@@ -1064,13 +1066,13 @@ T get(List<T> *list, int index){
} }
template<class T> template<class T>
void add(Arena *arena, List<T> *list, T item){ void add(Allocator *arena, List<T> *list, T item){
list_make_sure_there_is_room_for_item_count(arena, list, 1); list_make_sure_there_is_room_for_item_count(arena, list, 1);
list->last->data[list->last->len++] = item; list->last->data[list->last->len++] = item;
} }
template<class T> template<class T>
T *add_size(Arena *arena, List<T> *list, int count = 1, int zero_memory = 0){ T *add_size(Allocator *arena, List<T> *list, int count = 1, int zero_memory = 0){
list_make_sure_there_is_room_for_item_count(arena, list, count); list_make_sure_there_is_room_for_item_count(arena, list, count);
T *result = list->last->data + list->last->len; T *result = list->last->data + list->last->len;
list->last->len += count; list->last->len += count;
@@ -1183,9 +1185,9 @@ T pop(List<T> *list){
} }
template<class T> template<class T>
T *merge(Arena *arena, List<T> *list){ T *merge(Allocator *arena, List<T> *list){
int len = length(list); int len = length(list);
T *result = arena_push_array(arena, T, len); T *result = allocate_size(arena, T, len, false);
int i = 0; int i = 0;
For_Linked_List(list->first){ For_Linked_List(list->first){

View File

@@ -159,7 +159,7 @@ utf16_to_utf32(U16 *c, S32 max_advance) {
} }
CORE_Static String32 CORE_Static String32
string16_to_string32(Arena *allocator, String16 string){ string16_to_string32(Allocator *allocator, String16 string){
String32 result = {allocate_array(allocator, U32, string.len+1)}; String32 result = {allocate_array(allocator, U32, string.len+1)};
for(S64 i = 0; i < string.len;){ for(S64 i = 0; i < string.len;){
UTF32_Result decode = utf16_to_utf32(string.str + i, string.len - i); UTF32_Result decode = utf16_to_utf32(string.str + i, string.len - i);
@@ -175,7 +175,7 @@ string16_to_string32(Arena *allocator, String16 string){
} }
CORE_Static String32 CORE_Static String32
string8_to_string32(Arena *allocator, String string){ string8_to_string32(Allocator *allocator, String string){
String32 result = {allocate_array(allocator, U32, string.len+1)}; String32 result = {allocate_array(allocator, U32, string.len+1)};
for(S64 i = 0; i < string.len;){ for(S64 i = 0; i < string.len;){
UTF32_Result decode = utf8_to_utf32(string.str + i, string.len - i); UTF32_Result decode = utf8_to_utf32(string.str + i, string.len - i);
@@ -190,7 +190,7 @@ string8_to_string32(Arena *allocator, String string){
} }
CORE_Static String16 CORE_Static String16
string8_to_string16(Arena *allocator, String in){ string8_to_string16(Allocator *allocator, String in){
String16 result = {allocate_array(allocator, U16, (in.len*2)+1)}; // @Note(Krzosa): Should be more then enough space String16 result = {allocate_array(allocator, U16, (in.len*2)+1)}; // @Note(Krzosa): Should be more then enough space
for(S64 i = 0; i < in.len;){ for(S64 i = 0; i < in.len;){
UTF32_Result decode = utf8_to_utf32(in.str + i, in.len - i); UTF32_Result decode = utf8_to_utf32(in.str + i, in.len - i);
@@ -212,7 +212,7 @@ string8_to_string16(Arena *allocator, String in){
} }
CORE_Static String CORE_Static String
string16_to_string8(Arena *allocator, String16 in){ string16_to_string8(Allocator *allocator, String16 in){
String result = {allocate_array(allocator, U8, in.len*4+1)}; String result = {allocate_array(allocator, U8, in.len*4+1)};
for(S64 i = 0; i < in.len;){ for(S64 i = 0; i < in.len;){
UTF32_Result decode = utf16_to_utf32(in.str + i, in.len - i); UTF32_Result decode = utf16_to_utf32(in.str + i, in.len - i);
@@ -266,7 +266,7 @@ string16_from_widechar(wchar_t *string){
} }
CORE_Static String CORE_Static String
string16_copy(Arena *a, String string){ string16_copy(Allocator *a, String string){
U8 *copy = allocate_array(a, U8, string.len+1); U8 *copy = allocate_array(a, U8, string.len+1);
memory_copy(copy, string.str, string.len); memory_copy(copy, string.str, string.len);
copy[string.len] = 0; copy[string.len] = 0;

View File

@@ -4,10 +4,10 @@ set clang-flags=-O0 -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-abs
pushd %~dp0 pushd %~dp0
rem cl main.cpp -I.. user32.lib rem cl main.cpp -I.. user32.lib
rem clang core_main.cpp %clang-flags% clang core_main.cpp %clang-flags%
rem ubuntu run clang core_main.cpp -O0 -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o core.out rem ubuntu run clang core_main.cpp -O0 -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o core.out
clang core_arena.cpp %clang-flags% rem clang core_arena.cpp %clang-flags%
rem clang test.cpp rem clang test.cpp

View File

@@ -1,67 +1,97 @@
#include "base.cpp" constexpr size_t ARENA_BLOCK_SIZE = mib(1);
constexpr size_t ARENA_ALIGNMENT = 8;
struct Arena_Block { struct Scratch_Arena : Allocator {
Arena_Block *next; int cap, len;
Arena_Block *prev;
size_t cap;
size_t len;
uint8_t memory[]; uint8_t memory[];
}; };
constexpr size_t default_block_size = mib(1); struct Scratch_Scope {
struct Arena_Block_Based : Allocator { Scratch_Arena *arena;
Arena_Block *first; int pos;
Arena_Block *last; Scratch_Scope(Scratch_Arena *arena) { this->arena = arena; this->pos = arena->len; }
Arena_Block *first_free; ~Scratch_Scope() { this->arena->len = this->pos; }
Allocator *block_allocator;
size_t alignment;
}; };
static void arena_add_block(Arena_Block_Based *arena, size_t min_size) { static void *scratch_arena_push_size(Scratch_Arena *arena, size_t size) {
Arena_Block *block = 0; size_t generous_size = size + ARENA_ALIGNMENT;
for (Arena_Block *it = arena->first_free; it; it = it->next) { if (arena->len + generous_size > arena->cap) {
if (it->cap > min_size) { assert(size < arena->cap);
block = it; assert_message(0, "Scratch arena is too small, failed to handle a request, capacity: %d, occupied: %d, allocation: %d", generous_size);
DLL_STACK_REMOVE(arena->first_free, it); return 0;
break;
}
} }
if (!block) { size_t aligned_fill = align_up((size_t)arena->memory + arena->len, ARENA_ALIGNMENT) - (size_t)arena->memory;
block = (Arena_Block *)allocate_size(arena->block_allocator, sizeof(Arena_Block) + min_size + default_alignment, false); assert(((int64_t)aligned_fill - (int64_t)arena->len) >= 0);
block->cap = min_size + default_alignment; assert(((int64_t)aligned_fill - (int64_t)arena->len) <= ARENA_ALIGNMENT);
} arena->len = aligned_fill;
block->len = 0; uint8_t *result = arena->memory + arena->len;
block->next = 0; arena->len += size;
block->prev = 0;
DLL_QUEUE_ADD(arena->first, arena->last, block);
}
static void *block_arena_push_size(Arena_Block_Based *arena, size_t size) {
size_t generous_size = size + arena->alignment;
if (!arena->last || (arena->last->len + generous_size > arena->last->cap)) {
assert(arena->block_allocator);
size_t block_size = max(default_block_size, generous_size);
arena_add_block(arena, block_size);
}
Arena_Block *L = arena->last;
size_t adjusted_len = align_up((size_t)L->memory + L->len, arena->alignment) - (size_t)L->memory;
assert(((int64_t)adjusted_len - (int64_t)L->len) > 0);
assert(((int64_t)adjusted_len - (int64_t)L->len) <= arena->alignment);
L->len = adjusted_len;
uint8_t *result = L->memory + L->len;
L->len += size;
return (void *)result; return (void *)result;
} }
static Arena_Block_Based make_arena_block_based(Allocator *allocator) { static Scratch_Arena *allocate_scratch_arena(Allocator *allocator, size_t size_without_members) {
Arena_Block_Based result = {}; Scratch_Arena *scratch = (Scratch_Arena *)allocate_size(allocator, size_without_members + sizeof(Scratch_Arena), false);
scratch->cap = size_without_members;
scratch->len = 0;
scratch->allocate = (Allocator::Allocate *)scratch_arena_push_size;
scratch->deallocate = deallocate_stub;
return scratch;
}
struct Push_Arena_Block {
Push_Arena_Block *next;
uint8_t memory[];
};
struct Push_Arena : Allocator {
Allocator *block_allocator;
Push_Arena_Block *blocks;
size_t allocated_block_count;
size_t block_fill;
size_t wasted_memory;
};
static void push_arena_add_block(Push_Arena *arena) {
Push_Arena_Block *block = (Push_Arena_Block *)allocate_size(arena->block_allocator, sizeof(Push_Arena_Block) + ARENA_BLOCK_SIZE, false);
memory_zero(block, sizeof(Push_Arena_Block));
SLL_STACK_ADD(arena->blocks, block);
if (arena->allocated_block_count) arena->wasted_memory += ARENA_BLOCK_SIZE - arena->block_fill;
arena->allocated_block_count += 1;
arena->block_fill = 0;
}
static void push_arena_deallocate(Push_Arena *arena) {
for(Push_Arena_Block *it = arena->blocks; it; it = it->next) {
deallocate(arena->block_allocator, it);
}
memory_zero(arena, sizeof(*arena));
}
static void *push_arena_push_size(Push_Arena *arena, size_t size) {
assert(arena->block_allocator);
assert(size < ARENA_BLOCK_SIZE / 2);
size_t generous_size = size + ARENA_ALIGNMENT;
if (arena->blocks == 0 || (arena->block_fill + generous_size > ARENA_BLOCK_SIZE)) {
push_arena_add_block(arena);
}
Push_Arena_Block *L = arena->blocks;
size_t aligned_fill = align_up((size_t)L->memory + arena->block_fill, ARENA_ALIGNMENT) - (size_t)L->memory;
assert(((int64_t)aligned_fill - (int64_t)arena->block_fill) >= 0);
assert(((int64_t)aligned_fill - (int64_t)arena->block_fill) <= ARENA_ALIGNMENT);
arena->block_fill = aligned_fill;
uint8_t *result = L->memory + arena->block_fill;
arena->block_fill += size;
return (void *)result;
}
static Push_Arena make_push_arena(Allocator *allocator) {
Push_Arena result = {};
result.block_allocator = allocator; result.block_allocator = allocator;
result.alignment = default_alignment; result.allocate = (Allocator::Allocate *)push_arena_push_size;
result.allocate = (Allocator::Allocate *)block_arena_push_size;
result.deallocate = (Allocator::Deallocate *)deallocate_stub; result.deallocate = (Allocator::Deallocate *)deallocate_stub;
return result; return result;
} }
@@ -75,9 +105,3 @@ static CRT_Heap make_crt_heap() {
result.deallocate = crt_deallocate; result.deallocate = crt_deallocate;
return result; return result;
} }
int main() {
CRT_Heap heap = make_crt_heap();
Arena_Block_Based arena = make_arena_block_based(&heap);
void *result = allocate_size(&arena, 32);
}

View File

@@ -1,8 +1,9 @@
CORE_Static void CORE_Static void
core_init_compiler(Parse_Ctx *ctx, Arena *perm, Allocator *heap) { core_init_compiler(Core_Ctx *ctx, Arena *perm, Allocator *heap) {
ctx->init_ctx_time_begin = os_time(); ctx->init_ctx_time_begin = os_time();
pctx = ctx; pctx = ctx;
ctx->scratch = allocate_scratch_arena(perm, mib(1));
ctx->perm = perm; ctx->perm = perm;
ctx->heap = heap; ctx->heap = heap;
ctx->type_map = map_make(heap, 2048); ctx->type_map = map_make(heap, 2048);
@@ -95,7 +96,7 @@ core_init_compiler(Parse_Ctx *ctx, Arena *perm, Allocator *heap) {
CORE_Static void CORE_Static void
core_bootstrap_compiler(Allocator *allocator) { core_bootstrap_compiler(Allocator *allocator) {
Parse_Ctx *ctx = allocate_struct(allocator, Parse_Ctx); Core_Ctx *ctx = allocate_struct(allocator, Core_Ctx);
assert((uintptr_t)allocator->allocate == (uintptr_t)arena_push_size); assert((uintptr_t)allocator->allocate == (uintptr_t)arena_push_size);
core_init_compiler(ctx, (Arena *)allocator, allocator); core_init_compiler(ctx, (Arena *)allocator, allocator);

View File

@@ -20,13 +20,13 @@ struct Lex_Stream{
Array<Token *> indent_stack; Array<Token *> indent_stack;
}; };
struct Parse_Ctx{ struct Core_Ctx{
Arena *perm; // Stores: AST, tokens, interns Arena *perm; // Stores: AST, tokens, interns
Allocator *heap; Allocator *heap;
Scratch_Arena *scratch;
Arena stage_arena; Arena stage_arena;
Arena _scratch;
Arena *scratch;
// Lexer stuff // Lexer stuff
Lex_Stream stream; Lex_Stream stream;

View File

@@ -5,7 +5,7 @@ global B32 single_header_library_mode = false;
global String single_header_library_name = ""_s; global String single_header_library_name = ""_s;
global bool color_codes_enabled; global bool color_codes_enabled;
thread_local Parse_Ctx *pctx; thread_local Core_Ctx *pctx;
Arena *bigint_allocator; Arena *bigint_allocator;

View File

@@ -56,7 +56,7 @@ lex_set_len(Lex_Stream *s, Token *token){
} }
CORE_Static void CORE_Static void
lex_set_keywords(Parse_Ctx *lexer, Array<String> keywords){ lex_set_keywords(Core_Ctx *lexer, Array<String> keywords){
Intern_String keyword = {}; Intern_String keyword = {};
For(keywords){ For(keywords){
keyword = intern_string(&lexer->interns, it); keyword = intern_string(&lexer->interns, it);
@@ -79,7 +79,7 @@ token_error(Token *t, String error_val){
} }
CORE_Static void CORE_Static void
lex_parse_u64(Parse_Ctx *lexer, Token *t, S64 base){ lex_parse_u64(Core_Ctx *lexer, Token *t, S64 base){
Scratch scratch; Scratch scratch;
Set_BigInt_Arena(scratch); Set_BigInt_Arena(scratch);
@@ -175,7 +175,7 @@ lex_parse_ident(Intern_Table *table, Lex_Stream *s, Token *t){
break break
CORE_Static Token CORE_Static Token
token_make(Parse_Ctx *lexer, U8 *str, Intern_String file, int line, U8 *line_begin){ token_make(Core_Ctx *lexer, U8 *str, Intern_String file, int line, U8 *line_begin){
Token t = {}; Token t = {};
t.str = str; t.str = str;
t.file = file; t.file = file;
@@ -186,7 +186,7 @@ token_make(Parse_Ctx *lexer, U8 *str, Intern_String file, int line, U8 *line_beg
} }
CORE_Static Token CORE_Static Token
token_make(Parse_Ctx *lexer){ token_make(Core_Ctx *lexer){
return token_make(lexer, lexcp(&lexer->stream), lexer->stream.file, lexer->stream.line, lexer->stream.line_begin); return token_make(lexer, lexcp(&lexer->stream), lexer->stream.file, lexer->stream.line, lexer->stream.line_begin);
} }
@@ -228,7 +228,7 @@ lex_unwind_indent_stack(Token *t, Lex_Stream *s, Array<Token> *array){
} }
CORE_Static void CORE_Static void
lex__stream(Parse_Ctx *lexer){ lex__stream(Core_Ctx *lexer){
Intern_Table *table = &lexer->interns; Intern_Table *table = &lexer->interns;
Array<Token> *array = &lexer->tokens; Array<Token> *array = &lexer->tokens;
Lex_Stream *s = &lexer->stream; Lex_Stream *s = &lexer->stream;
@@ -586,7 +586,7 @@ lex__stream(Parse_Ctx *lexer){
} }
CORE_Static void CORE_Static void
lex_restream(Parse_Ctx *lexer, String istream, String file){ lex_restream(Core_Ctx *lexer, String istream, String file){
lexer->stream = {}; lexer->stream = {};
lexer->stream.stream = istream; lexer->stream.stream = istream;
lexer->stream.line_begin = istream.str; lexer->stream.line_begin = istream.str;

View File

@@ -259,6 +259,7 @@ For modules it's a bit different cause they should be distributed as valid.
#include "base.cpp" #include "base.cpp"
#include "base_unicode.cpp" #include "base_unicode.cpp"
#include "core_arena.cpp"
#include "os.h" #include "os.h"
#if OS_WINDOWS #if OS_WINDOWS
#include "os_windows.cpp" #include "os_windows.cpp"