| ... | ... | @@ -532,6 +532,13 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 532 | 532 | ret_addr: usize, |
| 533 | 533 | may_move: bool, |
| 534 | 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 | 542 | const entry = self.large_allocations.getEntry(@intFromPtr(old_mem.ptr)) orelse { |
| 536 | 543 | if (config.safety) { |
| 537 | 544 | @panic("Invalid free"); |
| ... | ... | @@ -584,15 +591,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 584 | 591 | self.total_requested_bytes = new_req_bytes; |
| 585 | 592 | } |
| 586 | 593 | |
| 587 | | const opt_resized_ptr = if (may_move) b: { |
| 588 | | // So that if the allocation moves, we can memcpy the |
| 589 | | // `LargeAlloc` value directly from old to new location. |
| 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)) |
| 594 | const opt_resized_ptr = if (may_move) |
| 595 | self.backing_allocator.rawRemap(old_mem, alignment, new_size, ret_addr) |
| 596 | else if (self.backing_allocator.rawResize(old_mem, alignment, new_size, ret_addr)) |
| 596 | 597 | old_mem.ptr |
| 597 | 598 | else |
| 598 | 599 | null; |
| ... | ... | @@ -619,6 +620,14 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 619 | 620 | |
| 620 | 621 | // Update the key of the hash map if the memory was relocated. |
| 621 | 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 | 631 | const gop = self.large_allocations.getOrPutAssumeCapacity(@intFromPtr(resized_ptr)); |
| 623 | 632 | if (config.retain_metadata and !config.never_unmap) { |
| 624 | 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 | 635 | } else { |
| 627 | 636 | assert(!gop.found_existing); // This would mean the kernel double-mapped pages. |
| 628 | 637 | } |
| 629 | | gop.value_ptr.* = entry.value_ptr.*; |
| 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 | | } |
| 638 | gop.value_ptr.* = large_alloc; |
| 636 | 639 | } |
| 637 | 640 | |
| 638 | 641 | return resized_ptr; |