authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-31 17:38:17-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-08-31 17:38:17-04:00
log0d94cb932fa1cbccb59cfd55ba63324459d6adc5
tree7f2d42fee265ac98aeb90fe42853bc668e2ff30f
parent82273f1a2a3bf3d90e24c3aeb77fbcdafdc82872
parent29de809a92cdc243149fd26a8f3c50180fc33ed5
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6197 from LemonBoy/fix-6049

gpa: Fix bookkeeping logic

1 files changed, 30 insertions(+), 16 deletions(-)

lib/std/heap/general_purpose_allocator.zig+30-16
......@@ -561,24 +561,25 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
561561 return error.OutOfMemory;
562562 }
563563
564 // Returns true if an allocation of `size` bytes is within the specified
565 // limits if enable_memory_limit is true
566 fn isAllocationAllowed(self: *Self, size: usize) bool {
567 if (config.enable_memory_limit) {
568 const new_req_bytes = self.total_requested_bytes + size;
569 if (new_req_bytes > self.requested_memory_limit)
570 return false;
571 self.total_requested_bytes = new_req_bytes;
572 }
573
574 return true;
575 }
576
564577 fn alloc(allocator: *Allocator, len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) Error![]u8 {
565578 const self = @fieldParentPtr(Self, "allocator", allocator);
566579
567580 const held = self.mutex.acquire();
568581 defer held.release();
569582
570 const prev_req_bytes = self.total_requested_bytes;
571 if (config.enable_memory_limit) {
572 const new_req_bytes = prev_req_bytes + len;
573 if (new_req_bytes > self.requested_memory_limit) {
574 return error.OutOfMemory;
575 }
576 self.total_requested_bytes = new_req_bytes;
577 }
578 errdefer if (config.enable_memory_limit) {
579 self.total_requested_bytes = prev_req_bytes;
580 };
581
582583 const new_aligned_size = math.max(len, ptr_align);
583584 if (new_aligned_size > largest_bucket_object_size) {
584585 try self.large_allocations.ensureCapacity(
......@@ -588,17 +589,30 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
588589
589590 const slice = try self.backing_allocator.allocFn(self.backing_allocator, len, ptr_align, len_align, ret_addr);
590591
592 // The backing allocator may return a memory block bigger than
593 // `len`, use the effective size for bookkeeping purposes
594 if (!self.isAllocationAllowed(slice.len)) {
595 // Free the block so no memory is leaked
596 const new_len = try self.backing_allocator.resizeFn(self.backing_allocator, slice, ptr_align, 0, 0, ret_addr);
597 assert(new_len == 0);
598 return error.OutOfMemory;
599 }
600
591601 const gop = self.large_allocations.getOrPutAssumeCapacity(@ptrToInt(slice.ptr));
592602 assert(!gop.found_existing); // This would mean the kernel double-mapped pages.
593603 gop.entry.value.bytes = slice;
594604 collectStackTrace(ret_addr, &gop.entry.value.stack_addresses);
595605
596606 return slice;
597 } else {
598 const new_size_class = math.ceilPowerOfTwoAssert(usize, new_aligned_size);
599 const ptr = try self.allocSlot(new_size_class, ret_addr);
600 return ptr[0..len];
601607 }
608
609 if (!self.isAllocationAllowed(len)) {
610 return error.OutOfMemory;
611 }
612
613 const new_size_class = math.ceilPowerOfTwoAssert(usize, new_aligned_size);
614 const ptr = try self.allocSlot(new_size_class, ret_addr);
615 return ptr[0..len];
602616 }
603617
604618 fn createBucket(self: *Self, size_class: usize, bucket_index: usize) Error!*BucketHeader {