diff options
| -rw-r--r-- | base/runtime/core_builtin_soa.odin | 19 | ||||
| -rw-r--r-- | tests/core/runtime/test_core_runtime.odin | 58 |
2 files changed, 58 insertions, 19 deletions
diff --git a/base/runtime/core_builtin_soa.odin b/base/runtime/core_builtin_soa.odin index 7548f6735..46c767751 100644 --- a/base/runtime/core_builtin_soa.odin +++ b/base/runtime/core_builtin_soa.odin @@ -266,6 +266,12 @@ _reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, zero_memory: boo // from: |x x y y z z _ _ _| // to: |x x _ y y _ z z _| + // move old data to the end of the new allocation to avoid overlap + old_start := uintptr(new_data) + uintptr(new_size - old_size) + mem_copy(rawptr(old_start), old_data, old_size) + + // now: |_ _ _ x x y y z z| + for i in 0..<field_count { type := si.types[i].variant.(Type_Info_Multi_Pointer).elem @@ -273,18 +279,21 @@ _reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, zero_memory: boo new_offset = align_forward_int(new_offset, max_align) new_data_elem := rawptr(uintptr(new_data) + uintptr(new_offset)) - old_data_elem := rawptr(uintptr(new_data) + uintptr(old_offset)) + old_data_elem := rawptr(old_start + uintptr(old_offset)) + + old_size_elem := type.size * old_cap + new_size_elem := type.size * capacity - mem_copy(new_data_elem, old_data_elem, type.size * old_cap) + mem_copy(new_data_elem, old_data_elem, old_size_elem) (^rawptr)(uintptr(array) + i*size_of(rawptr))^ = new_data_elem if zero_memory { - mem_zero(old_data_elem, int(uintptr(new_data_elem) - uintptr(old_data_elem))) + mem_zero(rawptr(uintptr(new_data_elem) + uintptr(old_size_elem)), new_size_elem - old_size_elem) } - old_offset += type.size * old_cap - new_offset += type.size * capacity + old_offset += old_size_elem + new_offset += new_size_elem } return nil diff --git a/tests/core/runtime/test_core_runtime.odin b/tests/core/runtime/test_core_runtime.odin index d74edd3f8..1bc100348 100644 --- a/tests/core/runtime/test_core_runtime.odin +++ b/tests/core/runtime/test_core_runtime.odin @@ -181,28 +181,58 @@ test_map_get :: proc(t: ^testing.T) { @(test) test_soa_array_allocator_resize :: proc(t: ^testing.T) { + arena: runtime.Arena context.allocator = runtime.arena_allocator(&arena) defer runtime.arena_destroy(&arena) - array, err := make(#soa[dynamic][2]int, 2, 3) - array[0] = [2]int{1, 2} - array[1] = [2]int{3, 4} + { + // |1 3 _ 2 4 _| + // |1 3 _ _ 2 4 _ _| - testing.expect_value(t, err, nil) - testing.expect_value(t, len(array), 2) - testing.expect_value(t, cap(array), 3) + array, err := make(#soa[dynamic][2]int, 2, 3) + array[0] = [2]int{1, 2} + array[1] = [2]int{3, 4} - err = resize(&array, 4) + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 2) + testing.expect_value(t, cap(array), 3) - testing.expect_value(t, err, nil) - testing.expect_value(t, len(array), 4) - testing.expect_value(t, cap(array), 4) + err = resize(&array, 4) + + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 4) + testing.expect_value(t, cap(array), 4) + + testing.expect_value(t, array[0], [2]int{1, 2}) + testing.expect_value(t, array[1], [2]int{3, 4}) + testing.expect_value(t, array[2], [2]int{0, 0}) + testing.expect_value(t, array[3], [2]int{0, 0}) + } - testing.expect_value(t, array[0], [2]int{1, 2}) - testing.expect_value(t, array[1], [2]int{3, 4}) - testing.expect_value(t, array[2], [2]int{0, 0}) - testing.expect_value(t, array[3], [2]int{0, 0}) + { + // |1 4 2 5 3 6| + // |1 4 _ _ 2 5 _ _ 3 6 _ _| + + array, err := make(#soa[dynamic][3]int, 2, 2) + array[0] = [3]int{1, 2, 3} + array[1] = [3]int{4, 5, 6} + + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 2) + testing.expect_value(t, cap(array), 2) + + err = resize(&array, 4) + + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 4) + testing.expect_value(t, cap(array), 4) + + testing.expect_value(t, array[0], [3]int{1, 2, 3}) + testing.expect_value(t, array[1], [3]int{4, 5, 6}) + testing.expect_value(t, array[2], [3]int{0, 0, 0}) + testing.expect_value(t, array[3], [3]int{0, 0, 0}) + } } @(test) |