| ... | @@ -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 | } |
| 573 | | 590 | |
| 574 | test "ArenaAllocator" { | 591 | test "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 | } |
| 585 | | 603 | |
| 586 | var test_fixed_buffer_allocator_memory: [30000 * @sizeOf(usize)]u8 = undefined; | 604 | var 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 | } |
| 594 | | 613 | |
| 595 | test "FixedBufferAllocator Reuse memory on realloc" { | 614 | test "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 | } |
| 631 | | 651 | |
| 632 | fn testAllocator(allocator: *mem.Allocator) !void { | 652 | fn 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 |
| 709 | | 729 | |
| 710 | allocator.free(slice); | 730 | allocator.free(slice); |
| 711 | } | 731 | } |
| | 732 | |
| | 733 | fn 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 | } |