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