aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2025-01-27 09:59:09 +0000
committerGitHub <noreply@github.com>2025-01-27 09:59:09 +0000
commit2e64cf7ef5495055757cd736d9dd461bccde73bc (patch)
treeb6bc9dc493db98ad6492dc106f1bbbc8c4f4a9b6
parent6572a52a84016ad9c8d0a7906ca06686a76ce5f7 (diff)
parent98b3a9eacd9b95a5db75fb001da0bfb0c7a18645 (diff)
Merge pull request #4751 from Barinzaya/arena-grow-in-place
Grow-in-place for some arenas
-rw-r--r--base/runtime/default_temp_allocator_arena.odin22
-rw-r--r--core/mem/virtual/arena.odin22
2 files changed, 36 insertions, 8 deletions
diff --git a/base/runtime/default_temp_allocator_arena.odin b/base/runtime/default_temp_allocator_arena.odin
index 878a2d070..6e2900411 100644
--- a/base/runtime/default_temp_allocator_arena.odin
+++ b/base/runtime/default_temp_allocator_arena.odin
@@ -210,10 +210,24 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
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
+ case uintptr(old_data) & uintptr(alignment-1) == 0:
+ if size < old_size {
+ // shrink data in-place
+ data = old_data[:size]
+ return
+ }
+
+ if block := arena.curr_block; block != nil {
+ start := uint(uintptr(old_memory)) - uint(uintptr(block.base))
+ old_end := start + old_size
+ new_end := start + size
+ if start < old_end && old_end == block.used && new_end <= block.capacity {
+ // grow data in-place, adjusting next allocation
+ block.used = uint(new_end)
+ data = block.base[start:new_end]
+ return
+ }
+ }
}
new_memory := arena_alloc(arena, size, alignment, location) or_return
diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin
index 675558ec8..5191505cf 100644
--- a/core/mem/virtual/arena.odin
+++ b/core/mem/virtual/arena.odin
@@ -328,10 +328,24 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
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
+ case uintptr(old_data) & uintptr(alignment-1) == 0:
+ if size < old_size {
+ // shrink data in-place
+ data = old_data[:size]
+ return
+ }
+
+ if block := arena.curr_block; block != nil {
+ start := uint(uintptr(old_memory)) - uint(uintptr(block.base))
+ old_end := start + old_size
+ new_end := start + size
+ if start < old_end && old_end == block.used && new_end <= block.reserved {
+ // grow data in-place, adjusting next allocation
+ _ = alloc_from_memory_block(block, new_end - old_end, 1, default_commit_size=arena.default_commit_size) or_return
+ data = block.base[start:new_end]
+ return
+ }
+ }
}
new_memory := arena_alloc(arena, size, alignment, location) or_return