Skip to content

Commit cf808ff

Browse files
committed
Move more code out of grow_amortized().
1 parent e0ba4b7 commit cf808ff

File tree

1 file changed

+41
-30
lines changed

1 file changed

+41
-30
lines changed

src/liballoc/raw_vec.rs

+41-30
Original file line numberDiff line numberDiff line change
@@ -395,37 +395,8 @@ impl<T, A: AllocRef> RawVec<T, A> {
395395
// of the code that doesn't depend on `T` as possible is in functions that
396396
// are non-generic over `T`.
397397
fn grow_amortized(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
398-
// This is ensured by the calling contexts.
399-
debug_assert!(additional > 0);
400-
401-
if mem::size_of::<T>() == 0 {
402-
// Since we return a capacity of `usize::MAX` when `elem_size` is
403-
// 0, getting to here necessarily means the `RawVec` is overfull.
404-
return Err(CapacityOverflow);
405-
}
406-
407-
// Nothing we can really do about these checks, sadly.
408-
let required_cap = len.checked_add(additional).ok_or(CapacityOverflow)?;
409-
410-
// This guarantees exponential growth. The doubling cannot overflow
411-
// because `cap <= isize::MAX` and the type of `cap` is `usize`.
412-
let cap = cmp::max(self.cap * 2, required_cap);
413-
414-
// Tiny Vecs are dumb. Skip to:
415-
// - 8 if the element size is 1, because any heap allocators is likely
416-
// to round up a request of less than 8 bytes to at least 8 bytes.
417-
// - 4 if elements are moderate-sized (<= 1 KiB).
418-
// - 1 otherwise, to avoid wasting too much space for very short Vecs.
419-
// Note that `min_non_zero_cap` is computed statically.
420398
let elem_size = mem::size_of::<T>();
421-
let min_non_zero_cap = if elem_size == 1 {
422-
8
423-
} else if elem_size <= 1024 {
424-
4
425-
} else {
426-
1
427-
};
428-
let cap = cmp::max(min_non_zero_cap, cap);
399+
let cap = cap_amortized(elem_size, len, additional, self.cap)?;
429400

430401
let elem_layout = Layout::new::<T>();
431402

@@ -478,6 +449,46 @@ impl<T, A: AllocRef> RawVec<T, A> {
478449
}
479450
}
480451

452+
// This function is outside `RawVec` to minimize compile times. See the comment
453+
// above `RawVec::grow_amortized` for details.
454+
#[inline]
455+
fn cap_amortized(
456+
elem_size: usize,
457+
len: usize,
458+
additional: usize,
459+
curr_cap: usize,
460+
) -> Result<usize, TryReserveError> {
461+
// This is ensured by the calling contexts.
462+
debug_assert!(additional > 0);
463+
464+
// Tiny Vecs are dumb. Skip to:
465+
// - 8 if the element size is 1, because any heap allocators is likely
466+
// to round up a request of less than 8 bytes to at least 8 bytes.
467+
// - 4 if elements are moderate-sized (<= 1 KiB).
468+
// - 1 otherwise, to avoid wasting too much space for very short Vecs.
469+
// Note that `min_non_zero_cap` is computed statically.
470+
let min_non_zero_cap = if elem_size == 0 {
471+
// Since we return a capacity of `usize::MAX` when `elem_size` is
472+
// 0, getting to here necessarily means the `RawVec` is overfull.
473+
return Err(CapacityOverflow);
474+
} else if elem_size == 1 {
475+
8
476+
} else if elem_size <= 1024 {
477+
4
478+
} else {
479+
1
480+
};
481+
482+
// Nothing we can really do about these checks, sadly.
483+
let required_cap = len.checked_add(additional).ok_or(CapacityOverflow)?;
484+
485+
// This guarantees exponential growth. The doubling cannot overflow
486+
// because `cap <= isize::MAX` and the type of `cap` is `usize`.
487+
let cap = cmp::max(curr_cap * 2, required_cap);
488+
489+
Ok(cmp::max(min_non_zero_cap, cap))
490+
}
491+
481492
// This function is outside `RawVec` to minimize compile times. See the comment
482493
// above `RawVec::grow_amortized` for details. (The `A` parameter isn't
483494
// significant, because the number of different `A` types seen in practice is

0 commit comments

Comments
 (0)