From 5c62211f00ca1f11a92e7a97b3727b9e29fb0ebd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 12 Oct 2022 20:44:36 +0100 Subject: [PATCH] Inline resize logic for `virtual.Arena` --- core/mem/alloc.odin | 15 +++++++------ core/mem/virtual/arena.odin | 45 +++++++++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/core/mem/alloc.odin b/core/mem/alloc.odin index 54004d333..b5788c8a8 100644 --- a/core/mem/alloc.odin +++ b/core/mem/alloc.odin @@ -243,13 +243,11 @@ default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, a return alloc_bytes(new_size, alignment, allocator, loc) } - if new_size == 0 { - err := free_bytes(old_data, allocator, loc) - return nil, err - } - if new_size == old_size { - return old_data, .None + return old_data, nil + } + if new_size == 0 { + return nil, free_bytes(old_data, allocator, loc) } new_memory, err := alloc_bytes(new_size, alignment, allocator, loc) @@ -258,6 +256,9 @@ default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, a } runtime.copy(new_memory, old_data) - free_bytes(old_data, allocator, loc) + err1 := free_bytes(old_data, allocator, loc) + if err == nil { + err = err1 + } return new_memory, err } diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index d2ffa73f2..1dd8d249c 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -46,6 +46,10 @@ arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = STA arena_alloc :: proc(arena: ^Arena, min_size: int, alignment: int, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { assert(mem.is_power_of_two(uintptr(alignment)), "non-power of two alignment", loc) + if min_size == 0 { + return nil, nil + } + switch arena.kind { case .Growing: size := uint(min_size) @@ -186,9 +190,9 @@ arena_allocator :: proc(arena: ^Arena) -> mem.Allocator { } arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, - size, alignment: int, - old_memory: rawptr, old_size: int, - location := #caller_location) -> (data: []byte, err: Allocator_Error) { + size, alignment: int, + old_memory: rawptr, old_size: int, + location := #caller_location) -> (data: []byte, err: Allocator_Error) { arena := (^Arena)(allocator_data) switch mode { @@ -196,19 +200,42 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, return arena_alloc(arena, size, alignment) case .Free: err = .Mode_Not_Implemented - return case .Free_All: arena_free_all(arena) - return case .Resize: - return mem.default_resize_bytes_align(mem.byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena), location) + old_data := ([^]byte)(old_memory) - case .Query_Features, .Query_Info: + switch { + case old_data == nil: + return arena_alloc(arena, size, alignment) + case size == old_size: + // return old memory + data = old_data[:size] + return + case size == 0: + err = .Mode_Not_Implemented + return + case (uintptr(old_data) & uintptr(alignment-1) == 0) && size < old_size: + // shrink data in-place + data = old_data[:size] + return + } + + new_memory := arena_alloc(arena, size, alignment) or_return + if new_memory == nil { + return + } + copy(new_memory, old_data[:old_size]) + return new_memory, nil + case .Query_Features: + set := (^mem.Allocator_Mode_Set)(old_memory) + if set != nil { + set^ = {.Alloc, .Free_All, .Resize, .Query_Features} + } + case .Query_Info: err = .Mode_Not_Implemented - return } - err = .Mode_Not_Implemented return }