diff options
| author | bors <bors@rust-lang.org> | 2015-09-21 16:36:26 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-09-21 16:36:26 +0000 |
| commit | 547fd5c11e6902e2f9748e7b46893211b36da421 (patch) | |
| tree | 51df2f4c747f3352bfd0379f1cee358188c6188e | |
| parent | 0a967561783f093c2b63057283784892e855a408 (diff) | |
| parent | 77f5da77a91af88130fcff3e726931934c71ba3f (diff) | |
| download | rust-547fd5c11e6902e2f9748e7b46893211b36da421.tar.gz rust-547fd5c11e6902e2f9748e7b46893211b36da421.zip | |
Auto merge of #28531 - whitequark:patch-1, r=Gankro
With -O2, LLVM's inliner can remove this code, but this does not happen with -O1 and lower. As a result, dropping Vec<u8> was linear with length, resulting in abysmal performance for large buffers. See issue #24280.
| -rw-r--r-- | src/libcollections/vec.rs | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index c99460a55c9..4110faa41b3 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -65,7 +65,7 @@ use alloc::heap::EMPTY; use core::cmp::Ordering; use core::fmt; use core::hash::{self, Hash}; -use core::intrinsics::{arith_offset, assume, drop_in_place}; +use core::intrinsics::{arith_offset, assume, drop_in_place, needs_drop}; use core::iter::FromIterator; use core::mem; use core::ops::{Index, IndexMut, Deref}; @@ -1322,8 +1322,14 @@ impl<T> Drop for Vec<T> { // OK because exactly when this stops being a valid assumption, we // don't need unsafe_no_drop_flag shenanigans anymore. if self.buf.unsafe_no_drop_flag_needs_drop() { - for x in self.iter_mut() { - unsafe { drop_in_place(x); } + unsafe { + // The branch on needs_drop() is an -O1 performance optimization. + // Without the branch, dropping Vec<u8> takes linear time. + if needs_drop::<T>() { + for x in self.iter_mut() { + drop_in_place(x); + } + } } } // RawVec handles deallocation |
