diff --git a/core/mem/alloc.odin b/core/mem/alloc.odin index b63317815..00bfd904f 100644 --- a/core/mem/alloc.odin +++ b/core/mem/alloc.odin @@ -164,6 +164,7 @@ Scratch_Allocator :: struct { curr_offset: int, prev_offset: int, backup_allocator: Allocator, + leaked_allocations: [dynamic]rawptr, } scratch_allocator_init :: proc(scratch: ^Scratch_Allocator, data: []byte, backup_allocator := context.allocator) { @@ -179,6 +180,11 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, scratch := (^Scratch_Allocator)(allocator_data); + if scratch.data == nil { + DEFAULT_SCRATCH_BACKING_SIZE :: 1<<22; + scratch_allocator_init(scratch, make([]byte, 1<<22)); + } + switch mode { case Allocator_Mode.Alloc: switch { @@ -201,8 +207,16 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, a := scratch.backup_allocator; if a.procedure == nil { a = context.allocator; + scratch.backup_allocator = a; } - return alloc(size, alignment, a, loc); + + ptr := alloc(size, alignment, a, loc); + if scratch.leaked_allocations == nil { + scratch.leaked_allocations = make([dynamic]rawptr, a); + } + append(&scratch.leaked_allocations, ptr); + + return ptr; case Allocator_Mode.Free: last_ptr := rawptr(&scratch.data[scratch.prev_offset]); @@ -217,6 +231,10 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, case Allocator_Mode.Free_All: scratch.curr_offset = 0; scratch.prev_offset = 0; + for ptr in scratch.leaked_allocations { + free(ptr, scratch.backup_allocator); + } + clear(&scratch.leaked_allocations); case Allocator_Mode.Resize: last_ptr := rawptr(&scratch.data[scratch.prev_offset]); diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 9b3e96d56..6c22cf2cf 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -183,11 +183,15 @@ Source_Code_Location :: struct { procedure: string, } +Assertion_Failure_Proc :: #type proc(prefix, message: string, loc: Source_Code_Location); + Context :: struct { allocator: mem.Allocator, temp_allocator: mem.Allocator, thread_id: int, + assertion_failure_proc: Assertion_Failure_Proc, + user_data: any, user_index: int, @@ -320,6 +324,7 @@ __init_context :: proc "contextless" (c: ^Context) { c.allocator = os.heap_allocator(); c.temp_allocator = mem.scratch_allocator(&global_scratch_allocator_data); c.thread_id = os.current_thread_id(); + c.assertion_failure_proc = default_assertion_failure_proc; } @(builtin) @@ -327,6 +332,19 @@ init_global_temporary_allocator :: proc(data: []byte, backup_allocator := contex mem.scratch_allocator_init(&global_scratch_allocator_data, data, backup_allocator); } +default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) { + fd := os.stderr; + __print_caller_location(fd, loc); + os.write_string(fd, " "); + os.write_string(fd, prefix); + if len(message) > 0 { + os.write_string(fd, ": "); + os.write_string(fd, message); + } + os.write_byte(fd, '\n'); + debug_trap(); +} + @(builtin) @@ -535,32 +553,16 @@ excl_bit_set :: inline proc(s: ^$S/bit_set[$E; $U], other: S) -> S { @(builtin) -assert :: proc "contextless" (condition: bool, message := "", using loc := #caller_location) -> bool { +assert :: proc "contextless" (condition: bool, message := "", loc := #caller_location) -> bool { if !condition { - fd := os.stderr; - __print_caller_location(fd, loc); - os.write_string(fd, " Runtime assertion"); - if len(message) > 0 { - os.write_string(fd, ": "); - os.write_string(fd, message); - } - os.write_byte(fd, '\n'); - debug_trap(); + context.assertion_failure_proc("Runtime assertion", message, loc); } return condition; } @(builtin) -panic :: proc "contextless" (message := "", using loc := #caller_location) { - fd := os.stderr; - __print_caller_location(fd, loc); - os.write_string(fd, " Panic"); - if len(message) > 0 { - os.write_string(fd, ": "); - os.write_string(fd, message); - } - os.write_byte(fd, '\n'); - debug_trap(); +panic :: proc "contextless" (message := "", loc := #caller_location) { + context.assertion_failure_proc("Panic", message, loc); }