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 {...@@ -139,7 +139,11 @@ pub const DirectAllocator = struct {
139 return shrink(allocator, old_mem, old_align, new_size, new_align);139 return shrink(allocator, old_mem, old_align, new_size, new_align);
140 }140 }
141 const result = try alloc(allocator, new_size, new_align);141 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 }
143 _ = os.posix.munmap(@ptrToInt(old_mem.ptr), old_mem.len);147 _ = os.posix.munmap(@ptrToInt(old_mem.ptr), old_mem.len);
144 return result;148 return result;
145 },149 },
...@@ -258,7 +262,11 @@ pub const ArenaAllocator = struct {...@@ -258,7 +262,11 @@ pub const ArenaAllocator = struct {
258 return error.OutOfMemory;262 return error.OutOfMemory;
259 } else {263 } else {
260 const result = try alloc(allocator, new_size, new_align);264 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 }
262 return result;270 return result;
263 }271 }
264 }272 }
...@@ -316,7 +324,11 @@ pub const FixedBufferAllocator = struct {...@@ -316,7 +324,11 @@ pub const FixedBufferAllocator = struct {
316 return error.OutOfMemory;324 return error.OutOfMemory;
317 } else {325 } else {
318 const result = try alloc(allocator, new_size, new_align);326 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 }
320 return result;332 return result;
321 }333 }
322 }334 }
...@@ -459,7 +471,11 @@ pub const ThreadSafeFixedBufferAllocator = blk: {...@@ -459,7 +471,11 @@ pub const ThreadSafeFixedBufferAllocator = blk: {
459 return error.OutOfMemory;471 return error.OutOfMemory;
460 } else {472 } else {
461 const result = try alloc(allocator, new_size, new_align);473 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 }
463 return result;479 return result;
464 }480 }
465 }481 }
...@@ -569,6 +585,7 @@ test "DirectAllocator" {...@@ -569,6 +585,7 @@ test "DirectAllocator" {
569 try testAllocator(allocator);585 try testAllocator(allocator);
570 try testAllocatorAligned(allocator, 16);586 try testAllocatorAligned(allocator, 16);
571 try testAllocatorLargeAlignment(allocator);587 try testAllocatorLargeAlignment(allocator);
588 try testAllocatorAlignedShrink(allocator);
572}589}
573590
574test "ArenaAllocator" {591test "ArenaAllocator" {
...@@ -581,6 +598,7 @@ test "ArenaAllocator" {...@@ -581,6 +598,7 @@ test "ArenaAllocator" {
581 try testAllocator(&arena_allocator.allocator);598 try testAllocator(&arena_allocator.allocator);
582 try testAllocatorAligned(&arena_allocator.allocator, 16);599 try testAllocatorAligned(&arena_allocator.allocator, 16);
583 try testAllocatorLargeAlignment(&arena_allocator.allocator);600 try testAllocatorLargeAlignment(&arena_allocator.allocator);
601 try testAllocatorAlignedShrink(&arena_allocator.allocator);
584}602}
585603
586var test_fixed_buffer_allocator_memory: [30000 * @sizeOf(usize)]u8 = undefined;604var test_fixed_buffer_allocator_memory: [30000 * @sizeOf(usize)]u8 = undefined;
...@@ -590,6 +608,7 @@ test "FixedBufferAllocator" {...@@ -590,6 +608,7 @@ test "FixedBufferAllocator" {
590 try testAllocator(&fixed_buffer_allocator.allocator);608 try testAllocator(&fixed_buffer_allocator.allocator);
591 try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);609 try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);
592 try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);610 try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);
611 try testAllocatorAlignedShrink(&fixed_buffer_allocator.allocator);
593}612}
594613
595test "FixedBufferAllocator Reuse memory on realloc" {614test "FixedBufferAllocator Reuse memory on realloc" {
...@@ -627,6 +646,7 @@ test "ThreadSafeFixedBufferAllocator" {...@@ -627,6 +646,7 @@ test "ThreadSafeFixedBufferAllocator" {
627 try testAllocator(&fixed_buffer_allocator.allocator);646 try testAllocator(&fixed_buffer_allocator.allocator);
628 try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);647 try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);
629 try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);648 try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);
649 try testAllocatorAlignedShrink(&fixed_buffer_allocator.allocator);
630}650}
631651
632fn testAllocator(allocator: *mem.Allocator) !void {652fn testAllocator(allocator: *mem.Allocator) !void {
...@@ -709,3 +729,28 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo...@@ -709,3 +729,28 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo
709729
710 allocator.free(slice);730 allocator.free(slice);
711}731}
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}