From 66c5e3ffb2b7a0804ceb989b9dc9138a7758bfd6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 6 Apr 2018 13:46:10 -0700 Subject: [PATCH] Reduce the size of panics in RawVec 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. --- src/liballoc/raw_vec.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 214cc7d7d0cd9..ae933f937c462 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -85,8 +85,8 @@ impl RawVec { unsafe { let elem_size = mem::size_of::(); - 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 { @@ -309,7 +309,7 @@ impl RawVec { // `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); @@ -368,7 +368,7 @@ impl RawVec { // 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`. @@ -440,7 +440,7 @@ impl RawVec { 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 */ } } @@ -550,7 +550,7 @@ impl RawVec { /// 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 */ } } @@ -591,7 +591,7 @@ impl RawVec { } 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). @@ -599,7 +599,7 @@ impl RawVec { let new_layout = Layout::new::().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(), ) { @@ -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::*;