| ... | @@ -532,6 +532,13 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -532,6 +532,13 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 532 | ret_addr: usize, | 532 | ret_addr: usize, |
| 533 | may_move: bool, | 533 | may_move: bool, |
| 534 | ) ?[*]u8 { | 534 | ) ?[*]u8 { |
| | 535 | if (config.retain_metadata and may_move) { |
| | 536 | // Before looking up the entry (since this could invalidate |
| | 537 | // it), we must reserve space for the new entry in case the |
| | 538 | // allocation is relocated. |
| | 539 | self.large_allocations.ensureUnusedCapacity(self.backing_allocator, 1) catch return null; |
| | 540 | } |
| | 541 | |
| 535 | const entry = self.large_allocations.getEntry(@intFromPtr(old_mem.ptr)) orelse { | 542 | const entry = self.large_allocations.getEntry(@intFromPtr(old_mem.ptr)) orelse { |
| 536 | if (config.safety) { | 543 | if (config.safety) { |
| 537 | @panic("Invalid free"); | 544 | @panic("Invalid free"); |
| ... | @@ -584,15 +591,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -584,15 +591,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 584 | self.total_requested_bytes = new_req_bytes; | 591 | self.total_requested_bytes = new_req_bytes; |
| 585 | } | 592 | } |
| 586 | | 593 | |
| 587 | const opt_resized_ptr = if (may_move) b: { | 594 | const opt_resized_ptr = if (may_move) |
| 588 | // So that if the allocation moves, we can memcpy the | 595 | self.backing_allocator.rawRemap(old_mem, alignment, new_size, ret_addr) |
| 589 | // `LargeAlloc` value directly from old to new location. | 596 | else if (self.backing_allocator.rawResize(old_mem, alignment, new_size, ret_addr)) |
| 590 | // It's also not clear to me whether removing one item from std | | |
| 591 | // lib hash map guarantees that unused capacity increases by | | |
| 592 | // one. | | |
| 593 | self.large_allocations.ensureUnusedCapacity(self.backing_allocator, 1) catch return null; | | |
| 594 | break :b self.backing_allocator.rawRemap(old_mem, alignment, new_size, ret_addr); | | |
| 595 | } else if (self.backing_allocator.rawResize(old_mem, alignment, new_size, ret_addr)) | | |
| 596 | old_mem.ptr | 597 | old_mem.ptr |
| 597 | else | 598 | else |
| 598 | null; | 599 | null; |
| ... | @@ -619,6 +620,14 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -619,6 +620,14 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 619 | | 620 | |
| 620 | // Update the key of the hash map if the memory was relocated. | 621 | // Update the key of the hash map if the memory was relocated. |
| 621 | if (resized_ptr != old_mem.ptr) { | 622 | if (resized_ptr != old_mem.ptr) { |
| | 623 | const large_alloc = entry.value_ptr.*; |
| | 624 | if (config.retain_metadata) { |
| | 625 | entry.value_ptr.freed = true; |
| | 626 | entry.value_ptr.captureStackTrace(ret_addr, .free); |
| | 627 | } else { |
| | 628 | self.large_allocations.removeByPtr(entry.key_ptr); |
| | 629 | } |
| | 630 | |
| 622 | const gop = self.large_allocations.getOrPutAssumeCapacity(@intFromPtr(resized_ptr)); | 631 | const gop = self.large_allocations.getOrPutAssumeCapacity(@intFromPtr(resized_ptr)); |
| 623 | if (config.retain_metadata and !config.never_unmap) { | 632 | if (config.retain_metadata and !config.never_unmap) { |
| 624 | // Backing allocator may be reusing memory that we're retaining metadata for | 633 | // Backing allocator may be reusing memory that we're retaining metadata for |
| ... | @@ -626,13 +635,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -626,13 +635,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 626 | } else { | 635 | } else { |
| 627 | assert(!gop.found_existing); // This would mean the kernel double-mapped pages. | 636 | assert(!gop.found_existing); // This would mean the kernel double-mapped pages. |
| 628 | } | 637 | } |
| 629 | gop.value_ptr.* = entry.value_ptr.*; | 638 | gop.value_ptr.* = large_alloc; |
| 630 | if (!config.retain_metadata) { | | |
| 631 | self.large_allocations.removeByPtr(entry.key_ptr); | | |
| 632 | } else { | | |
| 633 | entry.value_ptr.freed = true; | | |
| 634 | entry.value_ptr.captureStackTrace(ret_addr, .free); | | |
| 635 | } | | |
| 636 | } | 639 | } |
| 637 | | 640 | |
| 638 | return resized_ptr; | 641 | return resized_ptr; |