RawVec: don't recompute capacity after allocating.
Currently it sets the capacity to `ptr.len() / mem::size_of::<T>()` after any buffer allocation/reallocation. This would be useful if allocators ever returned a `NonNull<[u8]>` with a size larger than requested. But this never happens, so it's not useful. Removing this slightly reduces the size of generated LLVM IR, and slightly speeds up the hot path of `RawVec` growth.
This commit is contained in:
parent
e95e084a14
commit
8217138f44
1 changed files with 18 additions and 17 deletions
|
|
@ -190,9 +190,12 @@ impl<T, A: Allocator> RawVec<T, A> {
|
|||
Err(_) => handle_alloc_error(layout),
|
||||
};
|
||||
|
||||
// Allocators currently return a `NonNull<[u8]>` whose length
|
||||
// matches the size requested. If that ever changes, the capacity
|
||||
// here should change to `ptr.len() / mem::size_of::<T>()`.
|
||||
Self {
|
||||
ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) },
|
||||
cap: Self::capacity_from_bytes(ptr.len()),
|
||||
cap: capacity,
|
||||
alloc,
|
||||
}
|
||||
}
|
||||
|
|
@ -337,7 +340,7 @@ impl<T, A: Allocator> RawVec<T, A> {
|
|||
if self.needs_to_grow(len, additional) { self.grow_exact(len, additional) } else { Ok(()) }
|
||||
}
|
||||
|
||||
/// Shrinks the allocation down to the specified amount. If the given amount
|
||||
/// Shrinks the buffer down to the specified capacity. If the given amount
|
||||
/// is 0, actually completely deallocates.
|
||||
///
|
||||
/// # Panics
|
||||
|
|
@ -348,8 +351,8 @@ impl<T, A: Allocator> RawVec<T, A> {
|
|||
///
|
||||
/// Aborts on OOM.
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
pub fn shrink_to_fit(&mut self, amount: usize) {
|
||||
handle_reserve(self.shrink(amount));
|
||||
pub fn shrink_to_fit(&mut self, cap: usize) {
|
||||
handle_reserve(self.shrink(cap));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -360,14 +363,12 @@ impl<T, A: Allocator> RawVec<T, A> {
|
|||
additional > self.capacity().wrapping_sub(len)
|
||||
}
|
||||
|
||||
fn capacity_from_bytes(excess: usize) -> usize {
|
||||
debug_assert_ne!(mem::size_of::<T>(), 0);
|
||||
excess / mem::size_of::<T>()
|
||||
}
|
||||
|
||||
fn set_ptr(&mut self, ptr: NonNull<[u8]>) {
|
||||
fn set_ptr_and_cap(&mut self, ptr: NonNull<[u8]>, cap: usize) {
|
||||
// Allocators currently return a `NonNull<[u8]>` whose length matches
|
||||
// the size requested. If that ever changes, the capacity here should
|
||||
// change to `ptr.len() / mem::size_of::<T>()`.
|
||||
self.ptr = unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) };
|
||||
self.cap = Self::capacity_from_bytes(ptr.len());
|
||||
self.cap = cap;
|
||||
}
|
||||
|
||||
// This method is usually instantiated many times. So we want it to be as
|
||||
|
|
@ -399,7 +400,7 @@ impl<T, A: Allocator> RawVec<T, A> {
|
|||
|
||||
// `finish_grow` is non-generic over `T`.
|
||||
let ptr = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?;
|
||||
self.set_ptr(ptr);
|
||||
self.set_ptr_and_cap(ptr, cap);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -418,15 +419,15 @@ impl<T, A: Allocator> RawVec<T, A> {
|
|||
|
||||
// `finish_grow` is non-generic over `T`.
|
||||
let ptr = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?;
|
||||
self.set_ptr(ptr);
|
||||
self.set_ptr_and_cap(ptr, cap);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn shrink(&mut self, amount: usize) -> Result<(), TryReserveError> {
|
||||
assert!(amount <= self.capacity(), "Tried to shrink to a larger capacity");
|
||||
fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> {
|
||||
assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity");
|
||||
|
||||
let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) };
|
||||
let new_size = amount * mem::size_of::<T>();
|
||||
let new_size = cap * mem::size_of::<T>();
|
||||
|
||||
let ptr = unsafe {
|
||||
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
|
||||
|
|
@ -434,7 +435,7 @@ impl<T, A: Allocator> RawVec<T, A> {
|
|||
.shrink(ptr, layout, new_layout)
|
||||
.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })?
|
||||
};
|
||||
self.set_ptr(ptr);
|
||||
self.set_ptr_and_cap(ptr, cap);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue