| ... | @@ -98,7 +98,7 @@ | ... | @@ -98,7 +98,7 @@ |
| 98 | //! in a `std.HashMap` using the backing allocator. | 98 | //! in a `std.HashMap` using the backing allocator. |
| 99 | | 99 | |
| 100 | const std = @import("std"); | 100 | const std = @import("std"); |
| 101 | const log = std.log.scoped(.std); | 101 | const log = std.log.scoped(.gpa); |
| 102 | const math = std.math; | 102 | const math = std.math; |
| 103 | const assert = std.debug.assert; | 103 | const assert = std.debug.assert; |
| 104 | const mem = std.mem; | 104 | const mem = std.mem; |
| ... | @@ -162,6 +162,9 @@ pub const Config = struct { | ... | @@ -162,6 +162,9 @@ pub const Config = struct { |
| 162 | /// logged error messages with stack trace details. The downside is that every allocation | 162 | /// logged error messages with stack trace details. The downside is that every allocation |
| 163 | /// will be leaked! | 163 | /// will be leaked! |
| 164 | never_unmap: bool = false, | 164 | never_unmap: bool = false, |
| | 165 | |
| | 166 | /// Enables emitting info messages with the size and address of every allocation. |
| | 167 | verbose_log: bool = false, |
| 165 | }; | 168 | }; |
| 166 | | 169 | |
| 167 | pub fn GeneralPurposeAllocator(comptime config: Config) type { | 170 | pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| ... | @@ -454,10 +457,19 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -454,10 +457,19 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 454 | const result_len = try self.backing_allocator.resizeFn(self.backing_allocator, old_mem, old_align, new_size, len_align, ret_addr); | 457 | const result_len = try self.backing_allocator.resizeFn(self.backing_allocator, old_mem, old_align, new_size, len_align, ret_addr); |
| 455 | | 458 | |
| 456 | if (result_len == 0) { | 459 | if (result_len == 0) { |
| | 460 | if (config.verbose_log) { |
| | 461 | log.info("large free {d} bytes at {*}", .{ old_mem.len, old_mem.ptr }); |
| | 462 | } |
| | 463 | |
| 457 | self.large_allocations.removeAssertDiscard(@ptrToInt(old_mem.ptr)); | 464 | self.large_allocations.removeAssertDiscard(@ptrToInt(old_mem.ptr)); |
| 458 | return 0; | 465 | return 0; |
| 459 | } | 466 | } |
| 460 | | 467 | |
| | 468 | if (config.verbose_log) { |
| | 469 | log.info("large resize {d} bytes at {*} to {d}", .{ |
| | 470 | old_mem.len, old_mem.ptr, new_size, |
| | 471 | }); |
| | 472 | } |
| 461 | entry.value.bytes = old_mem.ptr[0..result_len]; | 473 | entry.value.bytes = old_mem.ptr[0..result_len]; |
| 462 | collectStackTrace(ret_addr, &entry.value.stack_addresses); | 474 | collectStackTrace(ret_addr, &entry.value.stack_addresses); |
| 463 | return result_len; | 475 | return result_len; |
| ... | @@ -568,6 +580,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -568,6 +580,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 568 | } else { | 580 | } else { |
| 569 | @memset(old_mem.ptr, undefined, old_mem.len); | 581 | @memset(old_mem.ptr, undefined, old_mem.len); |
| 570 | } | 582 | } |
| | 583 | if (config.verbose_log) { |
| | 584 | log.info("small free {d} bytes at {*}", .{ old_mem.len, old_mem.ptr }); |
| | 585 | } |
| 571 | return @as(usize, 0); | 586 | return @as(usize, 0); |
| 572 | } | 587 | } |
| 573 | const new_aligned_size = math.max(new_size, old_align); | 588 | const new_aligned_size = math.max(new_size, old_align); |
| ... | @@ -576,6 +591,11 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -576,6 +591,11 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 576 | if (old_mem.len > new_size) { | 591 | if (old_mem.len > new_size) { |
| 577 | @memset(old_mem.ptr + new_size, undefined, old_mem.len - new_size); | 592 | @memset(old_mem.ptr + new_size, undefined, old_mem.len - new_size); |
| 578 | } | 593 | } |
| | 594 | if (config.verbose_log) { |
| | 595 | log.info("small resize {d} bytes at {*} to {d}", .{ |
| | 596 | old_mem.len, old_mem.ptr, new_size, |
| | 597 | }); |
| | 598 | } |
| 579 | return new_size; | 599 | return new_size; |
| 580 | } | 600 | } |
| 581 | return error.OutOfMemory; | 601 | return error.OutOfMemory; |
| ... | @@ -623,6 +643,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -623,6 +643,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 623 | gop.entry.value.bytes = slice; | 643 | gop.entry.value.bytes = slice; |
| 624 | collectStackTrace(ret_addr, &gop.entry.value.stack_addresses); | 644 | collectStackTrace(ret_addr, &gop.entry.value.stack_addresses); |
| 625 | | 645 | |
| | 646 | if (config.verbose_log) { |
| | 647 | log.info("large alloc {d} bytes at {*}", .{ slice.len, slice.ptr }); |
| | 648 | } |
| 626 | return slice; | 649 | return slice; |
| 627 | } | 650 | } |
| 628 | | 651 | |
| ... | @@ -632,6 +655,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -632,6 +655,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 632 | | 655 | |
| 633 | const new_size_class = math.ceilPowerOfTwoAssert(usize, new_aligned_size); | 656 | const new_size_class = math.ceilPowerOfTwoAssert(usize, new_aligned_size); |
| 634 | const ptr = try self.allocSlot(new_size_class, ret_addr); | 657 | const ptr = try self.allocSlot(new_size_class, ret_addr); |
| | 658 | if (config.verbose_log) { |
| | 659 | log.info("small alloc {d} bytes at {*}", .{ len, ptr }); |
| | 660 | } |
| 635 | return ptr[0..len]; | 661 | return ptr[0..len]; |
| 636 | } | 662 | } |
| 637 | | 663 | |