Implement custom temporary allocator using ring buffer

This commit is contained in:
gingerBill
2020-11-15 19:36:37 +00:00
parent 17ec3e72a6
commit 0d6f5cec37
7 changed files with 105 additions and 88 deletions
-1
View File
@@ -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);
-9
View File
@@ -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) {
-5
View File
@@ -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
View File
@@ -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};
}
-2
View File
@@ -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) {
-24
View File
@@ -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
View File
@@ -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;