mirror of
https://github.com/odin-lang/Odin.git
synced 2026-07-12 02:49:31 +00:00
Change mem.Dynamic_Arena's alignment to be minimum_alignment
This commit is contained in:
@@ -1637,7 +1637,7 @@ Dynamic arena allocator data.
|
||||
Dynamic_Arena :: struct {
|
||||
block_size: int,
|
||||
out_band_size: int,
|
||||
alignment: int,
|
||||
minimum_alignment: int,
|
||||
unused_blocks: [dynamic]rawptr,
|
||||
used_blocks: [dynamic]rawptr,
|
||||
out_band_allocations: [dynamic]rawptr,
|
||||
@@ -1654,19 +1654,19 @@ This procedure initializes a dynamic arena. The specified `block_allocator`
|
||||
will be used to allocate arena blocks, and `array_allocator` to allocate
|
||||
arrays of blocks and out-band blocks. The blocks have the default size of
|
||||
`block_size` and out-band threshold will be `out_band_size`. All allocations
|
||||
will be aligned to a boundary specified by `alignment`.
|
||||
will be aligned at a minimum to a boundary specified by `minimum_alignment`.
|
||||
*/
|
||||
dynamic_arena_init :: proc(
|
||||
arena: ^Dynamic_Arena,
|
||||
block_allocator := context.allocator,
|
||||
array_allocator := context.allocator,
|
||||
block_size := DYNAMIC_ARENA_BLOCK_SIZE_DEFAULT,
|
||||
out_band_size := DYNAMIC_ARENA_OUT_OF_BAND_SIZE_DEFAULT,
|
||||
alignment := DEFAULT_ALIGNMENT,
|
||||
block_allocator := context.allocator,
|
||||
array_allocator := context.allocator,
|
||||
block_size := DYNAMIC_ARENA_BLOCK_SIZE_DEFAULT,
|
||||
out_band_size := DYNAMIC_ARENA_OUT_OF_BAND_SIZE_DEFAULT,
|
||||
minimum_alignment := DEFAULT_ALIGNMENT,
|
||||
) {
|
||||
arena.block_size = block_size
|
||||
arena.out_band_size = out_band_size
|
||||
arena.alignment = alignment
|
||||
arena.minimum_alignment = minimum_alignment
|
||||
arena.block_allocator = block_allocator
|
||||
arena.out_band_allocations.allocator = array_allocator
|
||||
arena.unused_blocks.allocator = array_allocator
|
||||
@@ -1714,7 +1714,7 @@ dynamic_arena_destroy :: proc(a: ^Dynamic_Arena) {
|
||||
}
|
||||
|
||||
@(private="file")
|
||||
_dynamic_arena_cycle_new_block :: proc(a: ^Dynamic_Arena, loc := #caller_location) -> (err: Allocator_Error) {
|
||||
_dynamic_arena_cycle_new_block :: proc(a: ^Dynamic_Arena, alignment: int, loc := #caller_location) -> (err: Allocator_Error) {
|
||||
if a.block_allocator.procedure == nil {
|
||||
panic("You must call `dynamic_arena_init` on a Dynamic Arena before using it.", loc)
|
||||
}
|
||||
@@ -1730,7 +1730,7 @@ _dynamic_arena_cycle_new_block :: proc(a: ^Dynamic_Arena, loc := #caller_locatio
|
||||
a.block_allocator.data,
|
||||
Allocator_Mode.Alloc,
|
||||
a.block_size,
|
||||
a.alignment,
|
||||
max(a.minimum_alignment, alignment),
|
||||
nil,
|
||||
0,
|
||||
)
|
||||
@@ -1752,8 +1752,8 @@ zero-initialized. This procedure returns a pointer to the newly allocated memory
|
||||
region.
|
||||
*/
|
||||
@(require_results)
|
||||
dynamic_arena_alloc :: proc(a: ^Dynamic_Arena, size: int, loc := #caller_location) -> (rawptr, Allocator_Error) {
|
||||
data, err := dynamic_arena_alloc_bytes(a, size, loc)
|
||||
dynamic_arena_alloc :: proc(a: ^Dynamic_Arena, size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> (rawptr, Allocator_Error) {
|
||||
data, err := dynamic_arena_alloc_bytes(a, size, alignment, loc)
|
||||
return raw_data(data), err
|
||||
}
|
||||
|
||||
@@ -1766,8 +1766,8 @@ zero-initialized. This procedure returns a slice of the newly allocated memory
|
||||
region.
|
||||
*/
|
||||
@(require_results)
|
||||
dynamic_arena_alloc_bytes :: proc(a: ^Dynamic_Arena, size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
||||
bytes, err := dynamic_arena_alloc_bytes_non_zeroed(a, size, loc)
|
||||
dynamic_arena_alloc_bytes :: proc(a: ^Dynamic_Arena, size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
||||
bytes, err := dynamic_arena_alloc_bytes_non_zeroed(a, size, alignment, loc)
|
||||
if bytes != nil {
|
||||
zero_slice(bytes)
|
||||
}
|
||||
@@ -1783,8 +1783,8 @@ zero-initialized. This procedure returns a pointer to the newly allocated
|
||||
memory region.
|
||||
*/
|
||||
@(require_results)
|
||||
dynamic_arena_alloc_non_zeroed :: proc(a: ^Dynamic_Arena, size: int, loc := #caller_location) -> (rawptr, Allocator_Error) {
|
||||
data, err := dynamic_arena_alloc_bytes_non_zeroed(a, size, loc)
|
||||
dynamic_arena_alloc_non_zeroed :: proc(a: ^Dynamic_Arena, size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> (rawptr, Allocator_Error) {
|
||||
data, err := dynamic_arena_alloc_bytes_non_zeroed(a, size, alignment, loc)
|
||||
return raw_data(data), err
|
||||
}
|
||||
|
||||
@@ -1797,21 +1797,21 @@ zero-initialized. This procedure returns a slice of the newly allocated
|
||||
memory region.
|
||||
*/
|
||||
@(require_results)
|
||||
dynamic_arena_alloc_bytes_non_zeroed :: proc(a: ^Dynamic_Arena, size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
||||
dynamic_arena_alloc_bytes_non_zeroed :: proc(a: ^Dynamic_Arena, size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
||||
if size >= a.out_band_size {
|
||||
assert(a.out_band_allocations.allocator.procedure != nil, "Backing array allocator must be initialized", loc=loc)
|
||||
memory, err := alloc_bytes_non_zeroed(size, a.alignment, a.out_band_allocations.allocator, loc)
|
||||
memory, err := alloc_bytes_non_zeroed(size, alignment, a.out_band_allocations.allocator, loc)
|
||||
if memory != nil {
|
||||
append(&a.out_band_allocations, raw_data(memory), loc = loc)
|
||||
}
|
||||
return memory, err
|
||||
}
|
||||
n := align_formula(size, a.alignment)
|
||||
n := align_formula(size, max(a.minimum_alignment, alignment))
|
||||
if n > a.block_size {
|
||||
return nil, .Invalid_Argument
|
||||
}
|
||||
if a.bytes_left < n {
|
||||
err := _dynamic_arena_cycle_new_block(a, loc)
|
||||
err := _dynamic_arena_cycle_new_block(a, alignment, loc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1886,9 +1886,10 @@ dynamic_arena_resize :: proc(
|
||||
old_memory: rawptr,
|
||||
old_size: int,
|
||||
size: int,
|
||||
alignment: int = DEFAULT_ALIGNMENT,
|
||||
loc := #caller_location,
|
||||
) -> (rawptr, Allocator_Error) {
|
||||
bytes, err := dynamic_arena_resize_bytes(a, byte_slice(old_memory, old_size), size, loc)
|
||||
bytes, err := dynamic_arena_resize_bytes(a, byte_slice(old_memory, old_size), size, alignment, loc)
|
||||
return raw_data(bytes), err
|
||||
}
|
||||
|
||||
@@ -1907,16 +1908,17 @@ This procedure returns the slice of the resized memory region.
|
||||
*/
|
||||
@(require_results)
|
||||
dynamic_arena_resize_bytes :: proc(
|
||||
a: ^Dynamic_Arena,
|
||||
old_data: []byte,
|
||||
size: int,
|
||||
a: ^Dynamic_Arena,
|
||||
old_data: []byte,
|
||||
size: int,
|
||||
alignment: int = DEFAULT_ALIGNMENT,
|
||||
loc := #caller_location,
|
||||
) -> ([]byte, Allocator_Error) {
|
||||
if size == 0 {
|
||||
// NOTE: This allocator has no Free mode.
|
||||
return nil, nil
|
||||
}
|
||||
bytes, err := dynamic_arena_resize_bytes_non_zeroed(a, old_data, size, loc)
|
||||
bytes, err := dynamic_arena_resize_bytes_non_zeroed(a, old_data, size, alignment, loc)
|
||||
if bytes != nil {
|
||||
if old_data == nil {
|
||||
zero_slice(bytes)
|
||||
@@ -1946,9 +1948,10 @@ dynamic_arena_resize_non_zeroed :: proc(
|
||||
old_memory: rawptr,
|
||||
old_size: int,
|
||||
size: int,
|
||||
alignment: int = DEFAULT_ALIGNMENT,
|
||||
loc := #caller_location,
|
||||
) -> (rawptr, Allocator_Error) {
|
||||
bytes, err := dynamic_arena_resize_bytes_non_zeroed(a, byte_slice(old_memory, old_size), size, loc)
|
||||
bytes, err := dynamic_arena_resize_bytes_non_zeroed(a, byte_slice(old_memory, old_size), size, alignment, loc)
|
||||
return raw_data(bytes), err
|
||||
}
|
||||
|
||||
@@ -1967,9 +1970,10 @@ This procedure returns the slice of the resized memory region.
|
||||
*/
|
||||
@(require_results)
|
||||
dynamic_arena_resize_bytes_non_zeroed :: proc(
|
||||
a: ^Dynamic_Arena,
|
||||
old_data: []byte,
|
||||
size: int,
|
||||
a: ^Dynamic_Arena,
|
||||
old_data: []byte,
|
||||
size: int,
|
||||
alignment: int = DEFAULT_ALIGNMENT,
|
||||
loc := #caller_location,
|
||||
) -> ([]byte, Allocator_Error) {
|
||||
if size == 0 {
|
||||
@@ -1984,7 +1988,7 @@ dynamic_arena_resize_bytes_non_zeroed :: proc(
|
||||
}
|
||||
// No information is kept about allocations in this allocator, thus we
|
||||
// cannot truly resize anything and must reallocate.
|
||||
data, err := dynamic_arena_alloc_bytes_non_zeroed(a, size, loc)
|
||||
data, err := dynamic_arena_alloc_bytes_non_zeroed(a, size, alignment, loc)
|
||||
if err == nil {
|
||||
runtime.copy(data, byte_slice(old_memory, old_size))
|
||||
}
|
||||
@@ -2003,17 +2007,17 @@ dynamic_arena_allocator_proc :: proc(
|
||||
arena := (^Dynamic_Arena)(allocator_data)
|
||||
switch mode {
|
||||
case .Alloc:
|
||||
return dynamic_arena_alloc_bytes(arena, size, loc)
|
||||
return dynamic_arena_alloc_bytes(arena, size, alignment, loc)
|
||||
case .Alloc_Non_Zeroed:
|
||||
return dynamic_arena_alloc_bytes_non_zeroed(arena, size, loc)
|
||||
return dynamic_arena_alloc_bytes_non_zeroed(arena, size, alignment, loc)
|
||||
case .Free:
|
||||
return nil, .Mode_Not_Implemented
|
||||
case .Free_All:
|
||||
dynamic_arena_free_all(arena, loc)
|
||||
case .Resize:
|
||||
return dynamic_arena_resize_bytes(arena, byte_slice(old_memory, old_size), size, loc)
|
||||
return dynamic_arena_resize_bytes(arena, byte_slice(old_memory, old_size), size, alignment, loc)
|
||||
case .Resize_Non_Zeroed:
|
||||
return dynamic_arena_resize_bytes_non_zeroed(arena, byte_slice(old_memory, old_size), size, loc)
|
||||
return dynamic_arena_resize_bytes_non_zeroed(arena, byte_slice(old_memory, old_size), size, alignment, loc)
|
||||
case .Query_Features:
|
||||
set := (^Allocator_Mode_Set)(old_memory)
|
||||
if set != nil {
|
||||
@@ -2024,7 +2028,7 @@ dynamic_arena_allocator_proc :: proc(
|
||||
info := (^Allocator_Query_Info)(old_memory)
|
||||
if info != nil && info.pointer != nil {
|
||||
info.size = arena.block_size
|
||||
info.alignment = arena.alignment
|
||||
info.alignment = arena.minimum_alignment
|
||||
return byte_slice(info, size_of(info^)), nil
|
||||
}
|
||||
return nil, nil
|
||||
|
||||
@@ -6,7 +6,7 @@ import "core:mem"
|
||||
|
||||
expect_pool_allocation :: proc(t: ^testing.T, expected_used_bytes, num_bytes, alignment: int) {
|
||||
pool: mem.Dynamic_Pool
|
||||
mem.dynamic_pool_init(&pool, alignment = alignment)
|
||||
mem.dynamic_pool_init(&pool, minimum_alignment = alignment)
|
||||
pool_allocator := mem.dynamic_pool_allocator(&pool)
|
||||
|
||||
element, err := mem.alloc(num_bytes, alignment, pool_allocator)
|
||||
@@ -18,20 +18,20 @@ expect_pool_allocation :: proc(t: ^testing.T, expected_used_bytes, num_bytes, al
|
||||
`
|
||||
Allocated data with size %v bytes, expected %v bytes left, got %v bytes left, off by %v bytes.
|
||||
Pool:
|
||||
block_size = %v
|
||||
out_band_size = %v
|
||||
alignment = %v
|
||||
unused_blocks = %v
|
||||
used_blocks = %v
|
||||
block_size = %v
|
||||
out_band_size = %v
|
||||
minimum_alignment = %v
|
||||
unused_blocks = %v
|
||||
used_blocks = %v
|
||||
out_band_allocations = %v
|
||||
current_block = %v
|
||||
current_pos = %v
|
||||
bytes_left = %v
|
||||
current_block = %v
|
||||
current_pos = %v
|
||||
bytes_left = %v
|
||||
`,
|
||||
num_bytes, expected_bytes_left, pool.bytes_left, expected_bytes_left - pool.bytes_left,
|
||||
pool.block_size,
|
||||
pool.out_band_size,
|
||||
pool.alignment,
|
||||
pool.minimum_alignment,
|
||||
pool.unused_blocks,
|
||||
pool.used_blocks,
|
||||
pool.out_band_allocations,
|
||||
@@ -39,6 +39,7 @@ expect_pool_allocation :: proc(t: ^testing.T, expected_used_bytes, num_bytes, al
|
||||
pool.current_pos,
|
||||
pool.bytes_left,
|
||||
)
|
||||
testing.expectf(t, uintptr(element) % uint(alignment) == 0, "Expected allocation to be aligned to %d byte boundary, got %v", alignment, element)
|
||||
|
||||
mem.dynamic_pool_destroy(&pool)
|
||||
testing.expect(t, pool.used_blocks == nil)
|
||||
Reference in New Issue
Block a user