Skip to content

Commit 92b2894

Browse files
Switch to reserve over extend_from_slice
This is a 0.15% win on diesel.
1 parent 299ac75 commit 92b2894

File tree

1 file changed

+21
-25
lines changed

1 file changed

+21
-25
lines changed

library/proc_macro/src/bridge/buffer.rs

+21-25
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub struct Buffer<T: Copy> {
3939
data: *mut T,
4040
len: usize,
4141
capacity: usize,
42-
extend_from_slice: extern "C" fn(Buffer<T>, Slice<'_, T>) -> Buffer<T>,
42+
reserve: extern "C" fn(Buffer<T>, usize) -> Buffer<T>,
4343
drop: extern "C" fn(Buffer<T>),
4444
}
4545

@@ -79,32 +79,28 @@ impl<T: Copy> Buffer<T> {
7979
}
8080

8181
pub(super) fn extend_from_slice(&mut self, xs: &[T]) {
82-
// Fast path to avoid going through an FFI call.
83-
if let Some(final_len) = self.len.checked_add(xs.len()) {
84-
if final_len <= self.capacity {
85-
let dst = unsafe { slice::from_raw_parts_mut(self.data, self.capacity) };
86-
dst[self.len..][..xs.len()].copy_from_slice(xs);
87-
self.len = final_len;
88-
return;
89-
}
82+
if xs.len() > self.capacity.wrapping_sub(self.len) {
83+
let b = self.take();
84+
*self = (b.reserve)(b, xs.len());
85+
}
86+
unsafe {
87+
xs.as_ptr().copy_to_nonoverlapping(self.data.add(self.len), xs.len());
88+
self.len += xs.len();
9089
}
91-
let b = self.take();
92-
*self = (b.extend_from_slice)(b, Slice::from(xs));
9390
}
9491

9592
pub(super) fn push(&mut self, v: T) {
96-
// Fast path to avoid going through an FFI call.
97-
if let Some(final_len) = self.len.checked_add(1) {
98-
if final_len <= self.capacity {
99-
unsafe {
100-
*self.data.add(self.len) = v;
101-
}
102-
self.len = final_len;
103-
return;
104-
}
93+
// The code here is taken from Vec::push, and we know that reserve()
94+
// will panic if we're exceeding isize::MAX bytes and so there's no need
95+
// to check for overflow.
96+
if self.len == self.capacity {
97+
let b = self.take();
98+
*self = (b.reserve)(b, 1);
99+
}
100+
unsafe {
101+
*self.data.add(self.len) = v;
102+
self.len += 1;
105103
}
106-
let b = self.take();
107-
*self = (b.extend_from_slice)(b, Slice::from(std::slice::from_ref(&v)));
108104
}
109105
}
110106

@@ -146,16 +142,16 @@ impl<T: Copy> From<Vec<T>> for Buffer<T> {
146142
}
147143
}
148144

149-
extern "C" fn extend_from_slice<T: Copy>(b: Buffer<T>, xs: Slice<'_, T>) -> Buffer<T> {
145+
extern "C" fn reserve<T: Copy>(b: Buffer<T>, additional: usize) -> Buffer<T> {
150146
let mut v = to_vec(b);
151-
v.extend_from_slice(&xs);
147+
v.reserve(additional);
152148
Buffer::from(v)
153149
}
154150

155151
extern "C" fn drop<T: Copy>(b: Buffer<T>) {
156152
mem::drop(to_vec(b));
157153
}
158154

159-
Buffer { data, len, capacity, extend_from_slice, drop }
155+
Buffer { data, len, capacity, reserve, drop }
160156
}
161157
}

0 commit comments

Comments
 (0)