| ... | @@ -402,41 +402,6 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -402,41 +402,6 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 402 | } | 402 | } |
| 403 | } | 403 | } |
| 404 | | 404 | |
| 405 | fn freeSlot( | | |
| 406 | self: *Self, | | |
| 407 | bucket: *BucketHeader, | | |
| 408 | bucket_index: usize, | | |
| 409 | size_class: usize, | | |
| 410 | slot_index: SlotIndex, | | |
| 411 | used_byte: *u8, | | |
| 412 | used_bit_index: u3, | | |
| 413 | trace_addr: usize, | | |
| 414 | ) void { | | |
| 415 | // Capture stack trace to be the "first free", in case a double free happens. | | |
| 416 | bucket.captureStackTrace(trace_addr, size_class, slot_index, .free); | | |
| 417 | | | |
| 418 | used_byte.* &= ~(@as(u8, 1) << used_bit_index); | | |
| 419 | bucket.used_count -= 1; | | |
| 420 | if (bucket.used_count == 0) { | | |
| 421 | if (bucket.next == bucket) { | | |
| 422 | // it's the only bucket and therefore the current one | | |
| 423 | self.buckets[bucket_index] = null; | | |
| 424 | } else { | | |
| 425 | bucket.next.prev = bucket.prev; | | |
| 426 | bucket.prev.next = bucket.next; | | |
| 427 | self.buckets[bucket_index] = bucket.prev; | | |
| 428 | } | | |
| 429 | if (!config.never_unmap) { | | |
| 430 | self.backing_allocator.free(bucket.page[0..page_size]); | | |
| 431 | } | | |
| 432 | const bucket_size = bucketSize(size_class); | | |
| 433 | const bucket_slice = @ptrCast([*]align(@alignOf(BucketHeader)) u8, bucket)[0..bucket_size]; | | |
| 434 | self.backing_allocator.free(bucket_slice); | | |
| 435 | } else { | | |
| 436 | @memset(bucket.page + slot_index * size_class, undefined, size_class); | | |
| 437 | } | | |
| 438 | } | | |
| 439 | | | |
| 440 | /// This function assumes the object is in the large object storage regardless | 405 | /// This function assumes the object is in the large object storage regardless |
| 441 | /// of the parameters. | 406 | /// of the parameters. |
| 442 | fn resizeLarge( | 407 | fn resizeLarge( |
| ... | @@ -560,7 +525,29 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { | ... | @@ -560,7 +525,29 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 560 | } | 525 | } |
| 561 | } | 526 | } |
| 562 | if (new_size == 0) { | 527 | if (new_size == 0) { |
| 563 | self.freeSlot(bucket, bucket_index, size_class, slot_index, used_byte, used_bit_index, ret_addr); | 528 | // Capture stack trace to be the "first free", in case a double free happens. |
| | 529 | bucket.captureStackTrace(ret_addr, size_class, slot_index, .free); |
| | 530 | |
| | 531 | used_byte.* &= ~(@as(u8, 1) << used_bit_index); |
| | 532 | bucket.used_count -= 1; |
| | 533 | if (bucket.used_count == 0) { |
| | 534 | if (bucket.next == bucket) { |
| | 535 | // it's the only bucket and therefore the current one |
| | 536 | self.buckets[bucket_index] = null; |
| | 537 | } else { |
| | 538 | bucket.next.prev = bucket.prev; |
| | 539 | bucket.prev.next = bucket.next; |
| | 540 | self.buckets[bucket_index] = bucket.prev; |
| | 541 | } |
| | 542 | if (!config.never_unmap) { |
| | 543 | self.backing_allocator.free(bucket.page[0..page_size]); |
| | 544 | } |
| | 545 | const bucket_size = bucketSize(size_class); |
| | 546 | const bucket_slice = @ptrCast([*]align(@alignOf(BucketHeader)) u8, bucket)[0..bucket_size]; |
| | 547 | self.backing_allocator.free(bucket_slice); |
| | 548 | } else { |
| | 549 | @memset(old_mem.ptr, undefined, old_mem.len); |
| | 550 | } |
| 564 | return @as(usize, 0); | 551 | return @as(usize, 0); |
| 565 | } | 552 | } |
| 566 | const new_aligned_size = math.max(new_size, old_align); | 553 | const new_aligned_size = math.max(new_size, old_align); |