mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-20 12:44:59 -07:00
Implement custom temporary allocator using ring buffer
This commit is contained in:
@@ -121,7 +121,6 @@ void check_init_variables(CheckerContext *ctx, Entity **lhs, isize lhs_count, Ar
|
||||
|
||||
// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
|
||||
// an extra allocation
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
auto operands = array_make<Operand>(temporary_allocator(), 0, 2*lhs_count);
|
||||
check_unpack_arguments(ctx, lhs, lhs_count, &operands, inits, true, false);
|
||||
|
||||
|
||||
@@ -1832,7 +1832,6 @@ void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) {
|
||||
}
|
||||
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
gbString err_str = nullptr;
|
||||
|
||||
if (check_is_assignable_to(c, x, y->type) ||
|
||||
@@ -2974,8 +2973,6 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
|
||||
|
||||
case Type_Union:
|
||||
if (!is_operand_nil(*operand) && !is_operand_undef(*operand)) {
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
isize count = t->Union.variants.count;
|
||||
ValidIndexAndScore *valids = gb_alloc_array(temporary_allocator(), ValidIndexAndScore, count);
|
||||
isize valid_count = 0;
|
||||
@@ -6536,8 +6533,6 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
||||
bool show_error = show_error_mode == CallArgumentMode_ShowErrors;
|
||||
CallArgumentError err = CallArgumentError_None;
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
isize param_count = pt->param_count;
|
||||
bool *visited = gb_alloc_array(temporary_allocator(), bool, param_count);
|
||||
auto ordered_operands = array_make<Operand>(temporary_allocator(), param_count);
|
||||
@@ -7385,8 +7380,6 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
|
||||
ordered_operands = array_make<Operand>(permanent_allocator(), param_count);
|
||||
array_copy(&ordered_operands, operands, 0);
|
||||
} else {
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
bool *visited = gb_alloc_array(temporary_allocator(), bool, param_count);
|
||||
|
||||
// LEAK(bill)
|
||||
@@ -8507,8 +8500,6 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
||||
}
|
||||
|
||||
if (cl->elems[0]->kind == Ast_FieldValue) {
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
bool *fields_visited = gb_alloc_array(temporary_allocator(), bool, field_count);
|
||||
|
||||
for_array(i, cl->elems) {
|
||||
|
||||
@@ -640,8 +640,6 @@ void add_constant_switch_case(CheckerContext *ctx, Map<TypeAndToken> *seen, Oper
|
||||
HashKey key = hash_exact_value(operand.value);
|
||||
TypeAndToken *found = map_get(seen, key);
|
||||
if (found != nullptr) {
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
isize count = multi_map_count(seen, key);
|
||||
TypeAndToken *taps = gb_alloc_array(temporary_allocator(), TypeAndToken, count);
|
||||
|
||||
@@ -1026,7 +1024,6 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
|
||||
GB_ASSERT(is_type_enum(et));
|
||||
auto fields = et->Enum.fields;
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
auto unhandled = array_make<Entity *>(temporary_allocator(), 0, fields.count);
|
||||
|
||||
for_array(i, fields) {
|
||||
@@ -1266,7 +1263,6 @@ void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
|
||||
GB_ASSERT(is_type_union(ut));
|
||||
auto variants = ut->Union.variants;
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
auto unhandled = array_make<Type *>(temporary_allocator(), 0, variants.count);
|
||||
|
||||
for_array(i, variants) {
|
||||
@@ -1434,7 +1430,6 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
|
||||
// an extra allocation
|
||||
|
||||
+98
-40
@@ -56,6 +56,14 @@ gb_inline isize align_formula_isize(isize size, isize align) {
|
||||
}
|
||||
return size;
|
||||
}
|
||||
gb_inline void *align_formula_ptr(void *ptr, isize align) {
|
||||
if (align > 0) {
|
||||
uintptr result = (cast(uintptr)ptr) + align-1;
|
||||
return (void *)(result - result%align);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
GB_ALLOCATOR_PROC(heap_allocator_proc);
|
||||
|
||||
@@ -380,6 +388,9 @@ typedef struct Arena {
|
||||
#define ARENA_MIN_ALIGNMENT 16
|
||||
#define ARENA_DEFAULT_BLOCK_SIZE (8*1024*1024)
|
||||
|
||||
|
||||
gb_global Arena permanent_arena = {};
|
||||
|
||||
void arena_init(Arena *arena, gbAllocator backing, isize block_size=ARENA_DEFAULT_BLOCK_SIZE) {
|
||||
arena->backing = backing;
|
||||
arena->block_size = block_size;
|
||||
@@ -491,51 +502,98 @@ GB_ALLOCATOR_PROC(arena_allocator_proc) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
struct SCOPED_TEMP_ARENA_MEMORY {
|
||||
Arena *arena;
|
||||
u8 * ptr;
|
||||
u8 * end;
|
||||
u8 * prev;
|
||||
isize total_used;
|
||||
isize block_count;
|
||||
|
||||
SCOPED_TEMP_ARENA_MEMORY(Arena *the_arena) {
|
||||
GB_ASSERT(!the_arena->use_mutex);
|
||||
arena = the_arena;
|
||||
ptr = arena->ptr;
|
||||
end = arena->end;
|
||||
prev = arena->prev;
|
||||
total_used = arena->total_used;
|
||||
block_count = arena->blocks.count;
|
||||
}
|
||||
~SCOPED_TEMP_ARENA_MEMORY() {
|
||||
if (arena->blocks.count != block_count) {
|
||||
for (isize i = block_count; i < arena->blocks.count; i++) {
|
||||
gb_free(arena->backing, arena->blocks[i]);
|
||||
}
|
||||
arena->blocks.count = block_count;
|
||||
}
|
||||
arena->ptr = ptr;
|
||||
arena->end = end;
|
||||
arena->prev = prev;
|
||||
arena->total_used = total_used;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
gb_global Arena permanent_arena = {};
|
||||
gb_global Arena temporary_arena = {};
|
||||
|
||||
gbAllocator permanent_allocator() {
|
||||
return arena_allocator(&permanent_arena);
|
||||
}
|
||||
gbAllocator temporary_allocator() {
|
||||
return arena_allocator(&temporary_arena);
|
||||
// return heap_allocator();
|
||||
}
|
||||
|
||||
#define SCOPED_TEMPORARY_BLOCK() auto GB_DEFER_3(_SCOPED_TEMPORARY_BLOCK_) = SCOPED_TEMP_ARENA_MEMORY(&temporary_arena)
|
||||
|
||||
|
||||
struct Temp_Allocator {
|
||||
u8 *data;
|
||||
isize len;
|
||||
isize curr_offset;
|
||||
gbAllocator backup_allocator;
|
||||
Array<void *> leaked_allocations;
|
||||
};
|
||||
|
||||
gb_global Temp_Allocator temporary_allocator_data = {};
|
||||
|
||||
void temp_allocator_init(Temp_Allocator *s, isize size) {
|
||||
s->backup_allocator = heap_allocator();
|
||||
s->data = cast(u8 *)gb_alloc_align(s->backup_allocator, size, 16);
|
||||
s->curr_offset = 0;
|
||||
s->leaked_allocations.allocator = s->backup_allocator;
|
||||
}
|
||||
|
||||
void *temp_allocator_alloc(Temp_Allocator *s, isize size, isize alignment) {
|
||||
size = align_formula_isize(size, alignment);
|
||||
if (s->curr_offset+size <= s->len) {
|
||||
u8 *start = s->data;
|
||||
u8 *ptr = start + s->curr_offset;
|
||||
ptr = cast(u8 *)align_formula_ptr(ptr, alignment);
|
||||
// assume memory is zero
|
||||
|
||||
isize offset = ptr - start;
|
||||
s->curr_offset = offset + size;
|
||||
return ptr;
|
||||
} else if (size <= s->len) {
|
||||
u8 *start = s->data;
|
||||
u8 *ptr = cast(u8 *)align_formula_ptr(start, alignment);
|
||||
// assume memory is zero
|
||||
|
||||
isize offset = ptr - start;
|
||||
s->curr_offset = offset + size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *ptr = gb_alloc_align(s->backup_allocator, size, alignment);
|
||||
array_add(&s->leaked_allocations, ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void temp_allocator_free_all(Temp_Allocator *s) {
|
||||
s->curr_offset = 0;
|
||||
for_array(i, s->leaked_allocations) {
|
||||
gb_free(s->backup_allocator, s->leaked_allocations[i]);
|
||||
}
|
||||
array_clear(&s->leaked_allocations);
|
||||
gb_zero_size(s->data, s->len);
|
||||
}
|
||||
|
||||
GB_ALLOCATOR_PROC(temp_allocator_proc) {
|
||||
void *ptr = nullptr;
|
||||
Temp_Allocator *s = cast(Temp_Allocator *)allocator_data;
|
||||
GB_ASSERT_NOT_NULL(s);
|
||||
|
||||
switch (type) {
|
||||
case gbAllocation_Alloc:
|
||||
return temp_allocator_alloc(s, size, alignment);
|
||||
case gbAllocation_Free:
|
||||
break;
|
||||
case gbAllocation_Resize:
|
||||
if (size == 0) {
|
||||
ptr = nullptr;
|
||||
} else if (size <= old_size) {
|
||||
ptr = old_memory;
|
||||
} else {
|
||||
ptr = temp_allocator_alloc(s, size, alignment);
|
||||
gb_memmove(ptr, old_memory, old_size);
|
||||
}
|
||||
break;
|
||||
case gbAllocation_FreeAll:
|
||||
temp_allocator_free_all(s);
|
||||
break;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
gbAllocator temporary_allocator() {
|
||||
return {temp_allocator_proc, &temporary_allocator_data};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -76,8 +76,6 @@ void ir_write_u64(irFileBuffer *f, u64 i) {
|
||||
}
|
||||
void ir_write_big_int(irFileBuffer *f, BigInt const &x, Type *type, bool swap_endian) {
|
||||
if (x.len == 2) {
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
u64 words[2] = {};
|
||||
BigInt y = x;
|
||||
if (swap_endian) {
|
||||
|
||||
@@ -781,8 +781,6 @@ void lb_emit_store_union_variant(lbProcedure *p, lbValue parent, lbValue variant
|
||||
|
||||
|
||||
void lb_clone_struct_type(LLVMTypeRef dst, LLVMTypeRef src) {
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
unsigned field_count = LLVMCountStructElementTypes(src);
|
||||
LLVMTypeRef *fields = gb_alloc_array(temporary_allocator(), LLVMTypeRef, field_count);
|
||||
LLVMGetStructElementTypes(src, fields);
|
||||
@@ -1279,8 +1277,6 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
m->internal_type_level += 1;
|
||||
defer (m->internal_type_level -= 1);
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
unsigned field_count = cast(unsigned)(type->Struct.fields.count + offset);
|
||||
LLVMTypeRef *fields = gb_alloc_array(temporary_allocator(), LLVMTypeRef, field_count);
|
||||
|
||||
@@ -1341,8 +1337,6 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
if (type->Tuple.variables.count == 1) {
|
||||
return lb_type(m, type->Tuple.variables[0]->type);
|
||||
} else {
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
unsigned field_count = cast(unsigned)(type->Tuple.variables.count);
|
||||
LLVMTypeRef *fields = gb_alloc_array(temporary_allocator(), LLVMTypeRef, field_count);
|
||||
|
||||
@@ -1442,8 +1436,6 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
extra_param_count += 1;
|
||||
}
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
isize param_count = type->Proc.abi_compat_params.count + extra_param_count;
|
||||
auto param_types = array_make<LLVMTypeRef>(temporary_allocator(), 0, param_count);
|
||||
|
||||
@@ -1490,8 +1482,6 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
{
|
||||
LLVMTypeRef internal_type = nullptr;
|
||||
{
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
GB_ASSERT(type->BitField.fields.count == type->BitField.sizes.count);
|
||||
unsigned field_count = cast(unsigned)type->BitField.fields.count;
|
||||
LLVMTypeRef *fields = gb_alloc_array(temporary_allocator(), LLVMTypeRef, field_count);
|
||||
@@ -5288,8 +5278,6 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
|
||||
return lb_const_nil(m, original_type);
|
||||
}
|
||||
if (cl->elems[0]->kind == Ast_FieldValue) {
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
// TODO(bill): This is O(N*M) and will be quite slow; it should probably be sorted before hand
|
||||
LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, type->Array.count);
|
||||
|
||||
@@ -5348,7 +5336,6 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
|
||||
} else {
|
||||
GB_ASSERT_MSG(elem_count == type->Array.count, "%td != %td", elem_count, type->Array.count);
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, type->Array.count);
|
||||
|
||||
for (isize i = 0; i < elem_count; i++) {
|
||||
@@ -5371,7 +5358,6 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
|
||||
return lb_const_nil(m, original_type);
|
||||
}
|
||||
if (cl->elems[0]->kind == Ast_FieldValue) {
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
// TODO(bill): This is O(N*M) and will be quite slow; it should probably be sorted before hand
|
||||
LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, type->EnumeratedArray.count);
|
||||
|
||||
@@ -5434,7 +5420,6 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
|
||||
} else {
|
||||
GB_ASSERT_MSG(elem_count == type->EnumeratedArray.count, "%td != %td", elem_count, type->EnumeratedArray.count);
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, type->EnumeratedArray.count);
|
||||
|
||||
for (isize i = 0; i < elem_count; i++) {
|
||||
@@ -5459,8 +5444,6 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
|
||||
}
|
||||
GB_ASSERT(elem_type_can_be_constant(elem_type));
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
isize total_elem_count = type->SimdVector.count;
|
||||
LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, total_elem_count);
|
||||
|
||||
@@ -5487,13 +5470,10 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
|
||||
isize value_count = type->Struct.fields.count + offset;
|
||||
LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, value_count);
|
||||
bool *visited = gb_alloc_array(temporary_allocator(), bool, value_count);
|
||||
|
||||
|
||||
if (cl->elems.count > 0) {
|
||||
if (cl->elems[0]->kind == Ast_FieldValue) {
|
||||
isize elem_count = cl->elems.count;
|
||||
@@ -10896,7 +10876,6 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
||||
if (cl->elems.count > 0) {
|
||||
lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
|
||||
|
||||
// NOTE(bill): Separate value, gep, store into their own chunks
|
||||
@@ -10996,7 +10975,6 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
||||
if (cl->elems.count > 0) {
|
||||
lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
|
||||
|
||||
// NOTE(bill): Separate value, gep, store into their own chunks
|
||||
@@ -11105,7 +11083,6 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
||||
|
||||
lbValue data = lb_slice_elem(p, slice);
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
|
||||
|
||||
for_array(i, cl->elems) {
|
||||
@@ -11954,7 +11931,6 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
|
||||
str_lit("$enum_values"), cast(i64)entry_index);
|
||||
|
||||
|
||||
SCOPED_TEMPORARY_BLOCK();
|
||||
LLVMValueRef *name_values = gb_alloc_array(temporary_allocator(), LLVMValueRef, fields.count);
|
||||
LLVMValueRef *value_values = gb_alloc_array(temporary_allocator(), LLVMValueRef, fields.count);
|
||||
|
||||
|
||||
+7
-7
@@ -1644,7 +1644,7 @@ int main(int arg_count, char const **arg_ptr) {
|
||||
defer (timings_destroy(timings));
|
||||
|
||||
arena_init(&permanent_arena, heap_allocator());
|
||||
arena_init(&temporary_arena, heap_allocator());
|
||||
temp_allocator_init(&temporary_allocator_data, 16*1024*1024);
|
||||
arena_init(&global_ast_arena, heap_allocator());
|
||||
permanent_arena.use_mutex = true;
|
||||
|
||||
@@ -1799,7 +1799,7 @@ int main(int arg_count, char const **arg_ptr) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
arena_free_all(&temporary_arena);
|
||||
temp_allocator_free_all(&temporary_allocator_data);
|
||||
|
||||
if (build_context.generate_docs) {
|
||||
// generate_documentation(&parser);
|
||||
@@ -1818,7 +1818,7 @@ int main(int arg_count, char const **arg_ptr) {
|
||||
check_parsed_files(&checker);
|
||||
}
|
||||
|
||||
arena_free_all(&temporary_arena);
|
||||
temp_allocator_free_all(&temporary_allocator_data);
|
||||
|
||||
if (build_context.no_output_files) {
|
||||
if (build_context.query_data_set_settings.ok) {
|
||||
@@ -1849,7 +1849,7 @@ int main(int arg_count, char const **arg_ptr) {
|
||||
}
|
||||
lb_generate_code(&gen);
|
||||
|
||||
arena_free_all(&temporary_arena);
|
||||
temp_allocator_free_all(&temporary_allocator_data);
|
||||
|
||||
switch (build_context.build_mode) {
|
||||
case BuildMode_Executable:
|
||||
@@ -1928,17 +1928,17 @@ int main(int arg_count, char const **arg_ptr) {
|
||||
timings_start_section(timings, str_lit("llvm ir gen"));
|
||||
ir_gen_tree(&ir_gen);
|
||||
|
||||
arena_free_all(&temporary_arena);
|
||||
temp_allocator_free_all(&temporary_allocator_data);
|
||||
|
||||
timings_start_section(timings, str_lit("llvm ir opt tree"));
|
||||
ir_opt_tree(&ir_gen);
|
||||
|
||||
arena_free_all(&temporary_arena);
|
||||
temp_allocator_free_all(&temporary_allocator_data);
|
||||
|
||||
timings_start_section(timings, str_lit("llvm ir print"));
|
||||
print_llvm_ir(&ir_gen);
|
||||
|
||||
arena_free_all(&temporary_arena);
|
||||
temp_allocator_free_all(&temporary_allocator_data);
|
||||
|
||||
|
||||
String output_name = ir_gen.output_name;
|
||||
|
||||
Reference in New Issue
Block a user