authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2019-04-19 17:54:53-07:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2019-04-20 23:56:39-07:00
log66020856b21b493d32355d58a1d4c58265abd198
tree28c57ebf5f9a998bebf3e9671678a3b59ce96546
parentbb25f212b3630eeaac6a76575f21875d7d94e1a4

fix heap allocators when shrinking an object but growing its alignment


1 files changed, 49 insertions(+), 4 deletions(-)

std/heap.zig+49-4
......@@ -139,7 +139,11 @@ pub const DirectAllocator = struct {
139139 return shrink(allocator, old_mem, old_align, new_size, new_align);
140140 }
141141 const result = try alloc(allocator, new_size, new_align);
142 mem.copy(u8, result, old_mem);
142 if (result.len >= old_mem.len) {
143 mem.copy(u8, result, old_mem);
144 } else {
145 @memcpy(result.ptr, old_mem.ptr, new_size);
146 }
143147 _ = os.posix.munmap(@ptrToInt(old_mem.ptr), old_mem.len);
144148 return result;
145149 },
......@@ -258,7 +262,11 @@ pub const ArenaAllocator = struct {
258262 return error.OutOfMemory;
259263 } else {
260264 const result = try alloc(allocator, new_size, new_align);
261 mem.copy(u8, result, old_mem);
265 if (result.len >= old_mem.len) {
266 mem.copy(u8, result, old_mem);
267 } else {
268 @memcpy(result.ptr, old_mem.ptr, new_size);
269 }
262270 return result;
263271 }
264272 }
......@@ -316,7 +324,11 @@ pub const FixedBufferAllocator = struct {
316324 return error.OutOfMemory;
317325 } else {
318326 const result = try alloc(allocator, new_size, new_align);
319 mem.copy(u8, result, old_mem);
327 if (result.len >= old_mem.len) {
328 mem.copy(u8, result, old_mem);
329 } else {
330 @memcpy(result.ptr, old_mem.ptr, new_size);
331 }
320332 return result;
321333 }
322334 }
......@@ -459,7 +471,11 @@ pub const ThreadSafeFixedBufferAllocator = blk: {
459471 return error.OutOfMemory;
460472 } else {
461473 const result = try alloc(allocator, new_size, new_align);
462 mem.copy(u8, result, old_mem);
474 if (result.len >= old_mem.len) {
475 mem.copy(u8, result, old_mem);
476 } else {
477 @memcpy(result.ptr, old_mem.ptr, new_size);
478 }
463479 return result;
464480 }
465481 }
......@@ -569,6 +585,7 @@ test "DirectAllocator" {
569585 try testAllocator(allocator);
570586 try testAllocatorAligned(allocator, 16);
571587 try testAllocatorLargeAlignment(allocator);
588 try testAllocatorAlignedShrink(allocator);
572589}
573590
574591test "ArenaAllocator" {
......@@ -581,6 +598,7 @@ test "ArenaAllocator" {
581598 try testAllocator(&arena_allocator.allocator);
582599 try testAllocatorAligned(&arena_allocator.allocator, 16);
583600 try testAllocatorLargeAlignment(&arena_allocator.allocator);
601 try testAllocatorAlignedShrink(&arena_allocator.allocator);
584602}
585603
586604var test_fixed_buffer_allocator_memory: [30000 * @sizeOf(usize)]u8 = undefined;
......@@ -590,6 +608,7 @@ test "FixedBufferAllocator" {
590608 try testAllocator(&fixed_buffer_allocator.allocator);
591609 try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);
592610 try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);
611 try testAllocatorAlignedShrink(&fixed_buffer_allocator.allocator);
593612}
594613
595614test "FixedBufferAllocator Reuse memory on realloc" {
......@@ -627,6 +646,7 @@ test "ThreadSafeFixedBufferAllocator" {
627646 try testAllocator(&fixed_buffer_allocator.allocator);
628647 try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);
629648 try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);
649 try testAllocatorAlignedShrink(&fixed_buffer_allocator.allocator);
630650}
631651
632652fn testAllocator(allocator: *mem.Allocator) !void {
......@@ -709,3 +729,28 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo
709729
710730 allocator.free(slice);
711731}
732
733fn testAllocatorAlignedShrink(allocator: *mem.Allocator) mem.Allocator.Error!void {
734 var debug_buffer: [1000]u8 = undefined;
735 const debug_allocator = &FixedBufferAllocator.init(&debug_buffer).allocator;
736
737 const alloc_size = os.page_size * 2 + 50;
738 var slice = try allocator.alignedAlloc(u8, 16, alloc_size);
739 defer allocator.free(slice);
740
741 var stuff_to_free = std.ArrayList([]align(16) u8).init(debug_allocator);
742 while (@ptrToInt(slice.ptr) == mem.alignForward(@ptrToInt(slice.ptr), os.page_size * 2)) {
743 try stuff_to_free.append(slice);
744 slice = try allocator.alignedAlloc(u8, 16, alloc_size);
745 }
746 while (stuff_to_free.popOrNull()) |item| {
747 allocator.free(item);
748 }
749 slice[0] = 0x12;
750 slice[60] = 0x34;
751
752 // realloc to a smaller size but with a larger alignment
753 slice = try allocator.alignedRealloc(slice, os.page_size * 2, alloc_size / 2);
754 testing.expect(slice[0] == 0x12);
755 testing.expect(slice[60] == 0x34);
756}