]> git.lizzy.rs Git - rust.git/commitdiff
RawVec: don't recompute capacity after allocating.
authorNicholas Nethercote <n.nethercote@gmail.com>
Tue, 21 Dec 2021 18:13:41 +0000 (05:13 +1100)
committerNicholas Nethercote <n.nethercote@gmail.com>
Tue, 21 Dec 2021 18:13:41 +0000 (05:13 +1100)
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.

library/alloc/src/raw_vec.rs

index 3d38e73305a37a577667e03a2cfc5491e4080bd4..3806bc546ee7b522f90104c77ffd8b03b6a1b12c 100644 (file)
@@ -190,9 +190,12 @@ fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self {
                 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 @@ pub fn try_reserve_exact(
         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 @@ pub fn try_reserve_exact(
     ///
     /// 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 @@ fn needs_to_grow(&self, len: usize, additional: usize) -> bool {
         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 @@ fn grow_amortized(&mut self, len: usize, additional: usize) -> Result<(), TryRes
 
         // `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 @@ fn grow_exact(&mut self, len: usize, additional: usize) -> Result<(), TryReserve
 
         // `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 @@ fn shrink(&mut self, amount: usize) -> Result<(), TryReserveError> {
                 .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(())
     }
 }