about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMark Rousskov <mark.simulacrum@gmail.com>2021-05-15 19:49:54 -0400
committerMark Rousskov <mark.simulacrum@gmail.com>2021-05-29 12:45:07 -0400
commit92b2894d313b5d514d077bf65560df29cda35d13 (patch)
treeafcd84b6601299ebd2103551028b056ed846c7af
parent299ac7589410a4e9541d0483161abb9e455e0ec1 (diff)
downloadrust-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.rs46
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 }
     }
 }