diff options
| author | Mark Rousskov <mark.simulacrum@gmail.com> | 2021-05-15 19:49:54 -0400 |
|---|---|---|
| committer | Mark Rousskov <mark.simulacrum@gmail.com> | 2021-05-29 12:45:07 -0400 |
| commit | 92b2894d313b5d514d077bf65560df29cda35d13 (patch) | |
| tree | afcd84b6601299ebd2103551028b056ed846c7af | |
| parent | 299ac7589410a4e9541d0483161abb9e455e0ec1 (diff) | |
| download | rust-92b2894d313b5d514d077bf65560df29cda35d13.tar.gz rust-92b2894d313b5d514d077bf65560df29cda35d13.zip | |
Switch to reserve over extend_from_slice
This is a 0.15% win on diesel.
| -rw-r--r-- | library/proc_macro/src/bridge/buffer.rs | 46 |
1 files changed, 21 insertions, 25 deletions
diff --git a/library/proc_macro/src/bridge/buffer.rs b/library/proc_macro/src/bridge/buffer.rs index 26d210a01c5..a2030b9b8bf 100644 --- a/library/proc_macro/src/bridge/buffer.rs +++ b/library/proc_macro/src/bridge/buffer.rs @@ -39,7 +39,7 @@ pub struct Buffer<T: Copy> { data: *mut T, len: usize, capacity: usize, - extend_from_slice: extern "C" fn(Buffer<T>, Slice<'_, T>) -> Buffer<T>, + reserve: extern "C" fn(Buffer<T>, usize) -> Buffer<T>, drop: extern "C" fn(Buffer<T>), } @@ -79,32 +79,28 @@ impl<T: Copy> Buffer<T> { } pub(super) fn extend_from_slice(&mut self, xs: &[T]) { - // Fast path to avoid going through an FFI call. - if let Some(final_len) = self.len.checked_add(xs.len()) { - if final_len <= self.capacity { - let dst = unsafe { slice::from_raw_parts_mut(self.data, self.capacity) }; - dst[self.len..][..xs.len()].copy_from_slice(xs); - self.len = final_len; - return; - } + if xs.len() > self.capacity.wrapping_sub(self.len) { + let b = self.take(); + *self = (b.reserve)(b, xs.len()); + } + unsafe { + xs.as_ptr().copy_to_nonoverlapping(self.data.add(self.len), xs.len()); + self.len += xs.len(); } - let b = self.take(); - *self = (b.extend_from_slice)(b, Slice::from(xs)); } pub(super) fn push(&mut self, v: T) { - // Fast path to avoid going through an FFI call. - if let Some(final_len) = self.len.checked_add(1) { - if final_len <= self.capacity { - unsafe { - *self.data.add(self.len) = v; - } - self.len = final_len; - return; - } + // The code here is taken from Vec::push, and we know that reserve() + // will panic if we're exceeding isize::MAX bytes and so there's no need + // to check for overflow. + if self.len == self.capacity { + let b = self.take(); + *self = (b.reserve)(b, 1); + } + unsafe { + *self.data.add(self.len) = v; + self.len += 1; } - let b = self.take(); - *self = (b.extend_from_slice)(b, Slice::from(std::slice::from_ref(&v))); } } @@ -146,9 +142,9 @@ impl<T: Copy> From<Vec<T>> for Buffer<T> { } } - extern "C" fn extend_from_slice<T: Copy>(b: Buffer<T>, xs: Slice<'_, T>) -> Buffer<T> { + extern "C" fn reserve<T: Copy>(b: Buffer<T>, additional: usize) -> Buffer<T> { let mut v = to_vec(b); - v.extend_from_slice(&xs); + v.reserve(additional); Buffer::from(v) } @@ -156,6 +152,6 @@ impl<T: Copy> From<Vec<T>> for Buffer<T> { mem::drop(to_vec(b)); } - Buffer { data, len, capacity, extend_from_slice, drop } + Buffer { data, len, capacity, reserve, drop } } } |
