diff --git a/src/lib.rs b/src/lib.rs index 1cb03f2..6078515 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -935,12 +935,6 @@ impl ThinVec { } } - unsafe fn deallocate(&mut self) { - if self.has_allocation() { - dealloc(self.ptr() as *mut u8, layout::(self.capacity())) - } - } - /// Resize the buffer and update its capacity, without changing the length. /// Unsafe because it can cause length to be greater than capacity. unsafe fn reallocate(&mut self, new_cap: usize) { @@ -1078,10 +1072,25 @@ impl ThinVec { } impl Drop for ThinVec { + #[inline] fn drop(&mut self) { - unsafe { - ptr::drop_in_place(&mut self[..]); - self.deallocate(); + #[cold] + #[inline(never)] + fn drop_non_singleton(this: &mut ThinVec) { + unsafe { + ptr::drop_in_place(&mut this[..]); + + #[cfg(feature = "gecko-ffi")] + if this.ptr.as_ref().uses_stack_allocated_buffer() { + return; + } + + dealloc(this.ptr() as *mut u8, layout::(this.capacity())) + } + } + + if !self.is_singleton() { + drop_non_singleton(self); } } } @@ -1125,7 +1134,10 @@ impl Extend for ThinVec { I: IntoIterator, { let iter = iter.into_iter(); - self.reserve(iter.size_hint().0); + let hint = iter.size_hint().0; + if hint > 0 { + self.reserve(hint); + } for x in iter { self.push(x); } @@ -1318,20 +1330,33 @@ impl Clone for ThinVec where T: Clone, { + #[inline] fn clone(&self) -> ThinVec { - let len = self.len(); - let mut new_vec = ThinVec::::with_capacity(len); - let mut data_raw = new_vec.data_raw(); - for x in self.iter() { + #[cold] + #[inline(never)] + fn clone_non_singleton(this: &ThinVec) -> ThinVec { + let len = this.len(); + let mut new_vec = ThinVec::::with_capacity(len); + let mut data_raw = new_vec.data_raw(); + for x in this.iter() { + unsafe { + ptr::write(data_raw, x.clone()); + data_raw = data_raw.add(1); + } + } unsafe { - ptr::write(data_raw, x.clone()); - data_raw = data_raw.add(1); + // `this` is not the singleton, but `new_vec` will be if + // `this` is empty. + new_vec.set_len(len); // could be the singleton } + new_vec } - unsafe { - new_vec.set_len(len); // could be the singleton + + if self.is_singleton() { + ThinVec::new() + } else { + clone_non_singleton(self) } - new_vec } } @@ -1394,11 +1419,20 @@ impl DoubleEndedIterator for IntoIter { } impl Drop for IntoIter { + #[inline] fn drop(&mut self) { - unsafe { - let mut vec = mem::replace(&mut self.vec, ThinVec::new()); - ptr::drop_in_place(&mut vec[self.start..]); - vec.set_len(0) // could be the singleton + #[cold] + #[inline(never)] + fn drop_non_singleton(this: &mut IntoIter) { + unsafe { + let mut vec = mem::replace(&mut this.vec, ThinVec::new()); + ptr::drop_in_place(&mut vec[this.start..]); + vec.set_len_non_singleton(0) + } + } + + if !self.vec.is_singleton() { + drop_non_singleton(self); } } } @@ -1795,6 +1829,27 @@ mod tests { assert_eq!(v.capacity(), 0); assert_eq!(&v[..], &[]); } + + { + let v = ThinVec::::new(); + let v = v.clone(); + + assert_eq!(v.len(), 0); + assert_eq!(v.capacity(), 0); + assert_eq!(&v[..], &[]); + } + } + + #[test] + fn test_clone() { + let mut v = ThinVec::::new(); + assert!(v.is_singleton()); + v.push(0); + v.pop(); + assert!(!v.is_singleton()); + + let v2 = v.clone(); + assert!(v2.is_singleton()); } }