From a456a55feaee9cdda257f80720c09a5dc731e5d4 Mon Sep 17 00:00:00 2001 From: tabokie Date: Tue, 7 Sep 2021 18:44:10 +0800 Subject: [PATCH 1/3] Optimize VecDeque::append Signed-off-by: tabokie --- .../alloc/src/collections/vec_deque/mod.rs | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index e4b28204158d9..e702ddb3f2ae6 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -417,6 +417,26 @@ impl VecDeque { } } + /// Append all values from `src` to `self`, wrapping around if needed. + /// Assumes capacity is sufficient. + #[inline] + unsafe fn append_slice(&mut self, src: &[T]) { + debug_assert!(self.len() + src.len() + 1 <= self.cap()); + let head_room = self.cap() - self.head; + if self.head < self.tail || src.len() <= head_room { + unsafe { + ptr::copy_nonoverlapping(src.as_ptr(), self.ptr().add(self.head), src.len()); + } + } else { + let (left, right) = src.split_at(head_room); + unsafe { + ptr::copy_nonoverlapping(left.as_ptr(), self.ptr().add(self.head), left.len()); + ptr::copy_nonoverlapping(right.as_ptr(), self.ptr(), right.len()); + } + } + self.head = self.wrap_add(self.head, src.len()); + } + /// Frobs the head and tail sections around to handle the fact that we /// just reallocated. Unsafe because it trusts old_capacity. #[inline] @@ -2088,8 +2108,14 @@ impl VecDeque { #[inline] #[stable(feature = "append", since = "1.4.0")] pub fn append(&mut self, other: &mut Self) { - // naive impl - self.extend(other.drain(..)); + self.reserve(other.len()); + unsafe { + let (left, right) = other.as_slices(); + self.append_slice(left); + self.append_slice(right); + } + // Silently drop values in `other`. + other.tail = other.head; } /// Retains only the elements specified by the predicate. From a929e6070777279ab326abd27efdc724afecd334 Mon Sep 17 00:00:00 2001 From: tabokie Date: Wed, 8 Sep 2021 11:46:20 +0800 Subject: [PATCH 2/3] rearrange to be panic safe Signed-off-by: tabokie --- .../alloc/src/collections/vec_deque/mod.rs | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index e702ddb3f2ae6..f703efd6fbe97 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -417,24 +417,23 @@ impl VecDeque { } } - /// Append all values from `src` to `self`, wrapping around if needed. + /// Append all values from `src` to `dst`, wrapping around if needed. /// Assumes capacity is sufficient. #[inline] - unsafe fn append_slice(&mut self, src: &[T]) { - debug_assert!(self.len() + src.len() + 1 <= self.cap()); - let head_room = self.cap() - self.head; - if self.head < self.tail || src.len() <= head_room { + unsafe fn copy_slice(&mut self, dst: usize, src: &[T]) { + debug_assert!(src.len() <= self.cap()); + let head_room = self.cap() - dst; + if src.len() <= head_room { unsafe { - ptr::copy_nonoverlapping(src.as_ptr(), self.ptr().add(self.head), src.len()); + ptr::copy_nonoverlapping(src.as_ptr(), self.ptr().add(dst), src.len()); } } else { let (left, right) = src.split_at(head_room); unsafe { - ptr::copy_nonoverlapping(left.as_ptr(), self.ptr().add(self.head), left.len()); + ptr::copy_nonoverlapping(left.as_ptr(), self.ptr().add(dst), left.len()); ptr::copy_nonoverlapping(right.as_ptr(), self.ptr(), right.len()); } } - self.head = self.wrap_add(self.head, src.len()); } /// Frobs the head and tail sections around to handle the fact that we @@ -2111,9 +2110,12 @@ impl VecDeque { self.reserve(other.len()); unsafe { let (left, right) = other.as_slices(); - self.append_slice(left); - self.append_slice(right); + self.copy_slice(self.head, left); + self.copy_slice(self.wrap_add(self.head, left.len()), right); } + // SAFETY: Update pointers after copying to avoid leaving doppelganger + // in case of panics. + self.head = self.wrap_add(self.head, other.len()); // Silently drop values in `other`. other.tail = other.head; } From cd773c358793beaae4688b4bbb60d793509f7cc0 Mon Sep 17 00:00:00 2001 From: Xinye Tao Date: Mon, 4 Oct 2021 00:27:32 +0800 Subject: [PATCH 3/3] Update outdated comment --- library/alloc/src/collections/vec_deque/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index f703efd6fbe97..8a9f06ff242e9 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -417,7 +417,7 @@ impl VecDeque { } } - /// Append all values from `src` to `dst`, wrapping around if needed. + /// Copies all values from `src` to `dst`, wrapping around if needed. /// Assumes capacity is sufficient. #[inline] unsafe fn copy_slice(&mut self, dst: usize, src: &[T]) {