| ... | @@ -608,7 +608,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -608,7 +608,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 608 | | 608 | |
| 609 | if (config.safety and old_mem.len != entry.value_ptr.bytes.len) { | 609 | if (config.safety and old_mem.len != entry.value_ptr.bytes.len) { |
| 610 | var addresses: [stack_n]usize = [1]usize{0} ** stack_n; | 610 | var addresses: [stack_n]usize = [1]usize{0} ** stack_n; |
| 611 | var free_stack_trace = StackTrace{ | 611 | var free_stack_trace: StackTrace = .{ |
| 612 | .instruction_addresses = &addresses, | 612 | .instruction_addresses = &addresses, |
| 613 | .index = 0, | 613 | .index = 0, |
| 614 | }; | 614 | }; |
| ... | @@ -635,9 +635,15 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -635,9 +635,15 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 635 | self.total_requested_bytes = new_req_bytes; | 635 | self.total_requested_bytes = new_req_bytes; |
| 636 | } | 636 | } |
| 637 | | 637 | |
| 638 | const opt_resized_ptr = if (may_move) | 638 | const opt_resized_ptr = if (may_move) b: { |
| 639 | self.backing_allocator.rawRemap(old_mem, alignment, new_size, ret_addr) | 639 | // So that if the allocation moves, we can memcpy the |
| 640 | else if (self.backing_allocator.rawResize(old_mem, alignment, new_size, ret_addr)) | 640 | // `LargeAlloc` value directly from old to new location. |
| | 641 | // It's also not clear to me whether removing one item from std |
| | 642 | // lib hash map guarantees that unused capacity increases by |
| | 643 | // one. |
| | 644 | self.large_allocations.ensureUnusedCapacity(self.backing_allocator, 1) catch return null; |
| | 645 | break :b self.backing_allocator.rawRemap(old_mem, alignment, new_size, ret_addr); |
| | 646 | } else if (self.backing_allocator.rawResize(old_mem, alignment, new_size, ret_addr)) |
| 641 | old_mem.ptr | 647 | old_mem.ptr |
| 642 | else | 648 | else |
| 643 | null; | 649 | null; |
| ... | @@ -660,6 +666,25 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -660,6 +666,25 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 660 | } | 666 | } |
| 661 | entry.value_ptr.bytes = resized_ptr[0..new_size]; | 667 | entry.value_ptr.bytes = resized_ptr[0..new_size]; |
| 662 | entry.value_ptr.captureStackTrace(ret_addr, .alloc); | 668 | entry.value_ptr.captureStackTrace(ret_addr, .alloc); |
| | 669 | |
| | 670 | // Update the key of the hash map if the memory was relocated. |
| | 671 | if (resized_ptr != old_mem.ptr) { |
| | 672 | const gop = self.large_allocations.getOrPutAssumeCapacity(@intFromPtr(resized_ptr)); |
| | 673 | if (config.retain_metadata and !config.never_unmap) { |
| | 674 | // Backing allocator may be reusing memory that we're retaining metadata for |
| | 675 | assert(!gop.found_existing or gop.value_ptr.freed); |
| | 676 | } else { |
| | 677 | assert(!gop.found_existing); // This would mean the kernel double-mapped pages. |
| | 678 | } |
| | 679 | gop.value_ptr.* = entry.value_ptr.*; |
| | 680 | if (!config.retain_metadata) { |
| | 681 | self.large_allocations.removeByPtr(entry.key_ptr); |
| | 682 | } else { |
| | 683 | entry.value_ptr.freed = true; |
| | 684 | entry.value_ptr.captureStackTrace(ret_addr, .free); |
| | 685 | } |
| | 686 | } |
| | 687 | |
| 663 | return resized_ptr; | 688 | return resized_ptr; |
| 664 | } | 689 | } |
| 665 | | 690 | |