Skip to content

Commit

Permalink
Reduce the size of panics in RawVec
Browse files Browse the repository at this point in the history
Create one canonical location which panics with "capacity overflow" instead of
having many. This reduces the size of a `panic!("{}", 1)` binary on wasm from
34k to 17k.
  • Loading branch information
alexcrichton committed Apr 13, 2018
1 parent c3a5d6b commit 66c5e3f
Showing 1 changed file with 15 additions and 8 deletions.
23 changes: 15 additions & 8 deletions src/liballoc/raw_vec.rs
Expand Up @@ -85,8 +85,8 @@ impl<T, A: Alloc> RawVec<T, A> {
unsafe {
let elem_size = mem::size_of::<T>();

let alloc_size = cap.checked_mul(elem_size).expect("capacity overflow");
alloc_guard(alloc_size).expect("capacity overflow");
let alloc_size = cap.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow());
alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow());

// handles ZSTs and `cap = 0` alike
let ptr = if alloc_size == 0 {
Expand Down Expand Up @@ -309,7 +309,7 @@ impl<T, A: Alloc> RawVec<T, A> {
// `from_size_align_unchecked`.
let new_cap = 2 * self.cap;
let new_size = new_cap * elem_size;
alloc_guard(new_size).expect("capacity overflow");
alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow());
let ptr_res = self.a.realloc(NonNull::from(self.ptr).as_opaque(),
cur,
new_size);
Expand Down Expand Up @@ -368,7 +368,7 @@ impl<T, A: Alloc> RawVec<T, A> {
// overflow and the alignment is sufficiently small.
let new_cap = 2 * self.cap;
let new_size = new_cap * elem_size;
alloc_guard(new_size).expect("capacity overflow");
alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow());
match self.a.grow_in_place(NonNull::from(self.ptr).as_opaque(), old_layout, new_size) {
Ok(_) => {
// We can't directly divide `size`.
Expand Down Expand Up @@ -440,7 +440,7 @@ impl<T, A: Alloc> RawVec<T, A> {

pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) {
match self.try_reserve_exact(used_cap, needed_extra_cap) {
Err(CapacityOverflow) => panic!("capacity overflow"),
Err(CapacityOverflow) => capacity_overflow(),
Err(AllocErr) => self.a.oom(),
Ok(()) => { /* yay */ }
}
Expand Down Expand Up @@ -550,7 +550,7 @@ impl<T, A: Alloc> RawVec<T, A> {
/// The same as try_reserve, but errors are lowered to a call to oom().
pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) {
match self.try_reserve(used_cap, needed_extra_cap) {
Err(CapacityOverflow) => panic!("capacity overflow"),
Err(CapacityOverflow) => capacity_overflow(),
Err(AllocErr) => self.a.oom(),
Ok(()) => { /* yay */ }
}
Expand Down Expand Up @@ -591,15 +591,15 @@ impl<T, A: Alloc> RawVec<T, A> {
}

let new_cap = self.amortized_new_size(used_cap, needed_extra_cap)
.expect("capacity overflow");
.unwrap_or_else(|_| capacity_overflow());

// Here, `cap < used_cap + needed_extra_cap <= new_cap`
// (regardless of whether `self.cap - used_cap` wrapped).
// Therefore we can safely call grow_in_place.

let new_layout = Layout::new::<T>().repeat(new_cap).unwrap().0;
// FIXME: may crash and burn on over-reserve
alloc_guard(new_layout.size()).expect("capacity overflow");
alloc_guard(new_layout.size()).unwrap_or_else(|_| capacity_overflow());
match self.a.grow_in_place(
NonNull::from(self.ptr).as_opaque(), old_layout, new_layout.size(),
) {
Expand Down Expand Up @@ -731,6 +731,13 @@ fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> {
}
}

// One central function responsible for reporting capacity overflows. This'll
// ensure that the code generation related to these panics is minimal as there's
// only one location which panics rather than a bunch throughout the module.
fn capacity_overflow() -> ! {
panic!("capacity overflow")
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit 66c5e3f

Please sign in to comment.