From 7145b877511e2a38fbdea32a375e398371d1980b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 21 May 2020 11:03:33 +1000 Subject: [PATCH] Remove the `reserve_in_place` calls in `{Typed,Dropless}Arena::grow`. They are pointless. No reasonable allocator will be able to satisfy a `reserve_in_place` request that *doubles* the size of an allocation when dealing with allocations that are 4 KiB and larger. Just to be sure, I confirmed on Linux that the `reserve_in_place` calls never succeed. (Note however that the `reserve_in_place` call for `DroplessArena::grow` did occasionally succeed prior to the off-by-one fix in the previous commit, because we would sometimes do a `reserve_in_place` request for the chunk's current size, which would trivially succeed!) --- src/librustc_arena/lib.rs | 52 +++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/src/librustc_arena/lib.rs b/src/librustc_arena/lib.rs index 725850036bb..fbf68a5ca35 100644 --- a/src/librustc_arena/lib.rs +++ b/src/librustc_arena/lib.rs @@ -216,26 +216,21 @@ impl TypedArena { #[cold] fn grow(&self, n: usize) { unsafe { - // We need the element size in to convert chunk sizes (ranging from + // We need the element size to convert chunk sizes (ranging from // PAGE to HUGE_PAGE bytes) to element counts. let elem_size = cmp::max(1, mem::size_of::()); let mut chunks = self.chunks.borrow_mut(); - let (chunk, mut new_capacity); + let mut new_capacity; if let Some(last_chunk) = chunks.last_mut() { let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize; - let currently_used_cap = used_bytes / mem::size_of::(); - last_chunk.entries = currently_used_cap; - if last_chunk.storage.reserve_in_place(currently_used_cap, n) { - self.end.set(last_chunk.end()); - return; - } else { - // If the previous chunk's capacity is less than HUGE_PAGE - // bytes, then this chunk will be least double the previous - // chunk's size. - new_capacity = last_chunk.storage.capacity(); - if new_capacity < HUGE_PAGE / elem_size { - new_capacity = new_capacity.checked_mul(2).unwrap(); - } + last_chunk.entries = used_bytes / mem::size_of::(); + + // If the previous chunk's capacity is less than HUGE_PAGE + // bytes, then this chunk will be least double the previous + // chunk's size. + new_capacity = last_chunk.storage.capacity(); + if new_capacity < HUGE_PAGE / elem_size { + new_capacity = new_capacity.checked_mul(2).unwrap(); } } else { new_capacity = PAGE / elem_size; @@ -243,7 +238,7 @@ impl TypedArena { // Also ensure that this chunk can fit `n`. new_capacity = cmp::max(n, new_capacity); - chunk = TypedArenaChunk::::new(new_capacity); + let chunk = TypedArenaChunk::::new(new_capacity); self.ptr.set(chunk.start()); self.end.set(chunk.end()); chunks.push(chunk); @@ -350,20 +345,17 @@ impl DroplessArena { fn grow(&self, needed_bytes: usize) { unsafe { let mut chunks = self.chunks.borrow_mut(); - let (chunk, mut new_capacity); + let mut new_capacity; if let Some(last_chunk) = chunks.last_mut() { - let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize; - if last_chunk.storage.reserve_in_place(used_bytes, needed_bytes) { - self.end.set(last_chunk.end()); - return; - } else { - // If the previous chunk's capacity is less than HUGE_PAGE - // bytes, then this chunk will be least double the previous - // chunk's size. - new_capacity = last_chunk.storage.capacity(); - if new_capacity < HUGE_PAGE { - new_capacity = new_capacity.checked_mul(2).unwrap(); - } + // There is no need to update `last_chunk.entries` because that + // field isn't used by `DroplessArena`. + + // If the previous chunk's capacity is less than HUGE_PAGE + // bytes, then this chunk will be least double the previous + // chunk's size. + new_capacity = last_chunk.storage.capacity(); + if new_capacity < HUGE_PAGE { + new_capacity = new_capacity.checked_mul(2).unwrap(); } } else { new_capacity = PAGE; @@ -371,7 +363,7 @@ impl DroplessArena { // Also ensure that this chunk can fit `needed_bytes`. new_capacity = cmp::max(needed_bytes, new_capacity); - chunk = TypedArenaChunk::::new(new_capacity); + let chunk = TypedArenaChunk::::new(new_capacity); self.ptr.set(chunk.start()); self.end.set(chunk.end()); chunks.push(chunk);