Skip to content

Commit f1dae0f

Browse files
committed
Auto merge of #157451 - cyrgani:pm-fast-1, r=<try>
[PERF] directly manage `Buffer` memory without using `Vec`
2 parents 688ab44 + e833bab commit f1dae0f

1 file changed

Lines changed: 30 additions & 38 deletions

File tree

library/proc_macro/src/bridge/buffer.rs

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
//! Buffer management for same-process client<->server communication.
22
3+
use std::alloc::{self, Layout};
34
use std::io::{self, Write};
4-
use std::mem::{self, ManuallyDrop};
55
use std::ops::{Deref, DerefMut};
6-
use std::slice;
6+
use std::ptr::null_mut;
7+
use std::{mem, slice};
78

89
#[repr(C)]
910
pub struct Buffer {
1011
data: *mut u8,
1112
len: usize,
1213
capacity: usize,
13-
reserve: extern "C" fn(Buffer, usize) -> Buffer,
14-
drop: extern "C" fn(Buffer),
1514
}
1615

1716
unsafe impl Sync for Buffer {}
@@ -20,7 +19,7 @@ unsafe impl Send for Buffer {}
2019
impl Default for Buffer {
2120
#[inline]
2221
fn default() -> Self {
23-
Self::from(vec![])
22+
Self { data: null_mut(), len: 0, capacity: 0 }
2423
}
2524
}
2625

@@ -62,8 +61,7 @@ impl Buffer {
6261
#[inline]
6362
pub(super) fn extend_from_array<const N: usize>(&mut self, xs: &[u8; N]) {
6463
if xs.len() > (self.capacity - self.len) {
65-
let b = self.take();
66-
*self = (b.reserve)(b, xs.len());
64+
self.reserve(xs.len());
6765
}
6866
unsafe {
6967
xs.as_ptr().copy_to_nonoverlapping(self.data.add(self.len), xs.len());
@@ -74,8 +72,7 @@ impl Buffer {
7472
#[inline]
7573
pub(super) fn extend_from_slice(&mut self, xs: &[u8]) {
7674
if xs.len() > (self.capacity - self.len) {
77-
let b = self.take();
78-
*self = (b.reserve)(b, xs.len());
75+
self.reserve(xs.len());
7976
}
8077
unsafe {
8178
xs.as_ptr().copy_to_nonoverlapping(self.data.add(self.len), xs.len());
@@ -89,14 +86,34 @@ impl Buffer {
8986
// will panic if we're exceeding isize::MAX bytes and so there's no need
9087
// to check for overflow.
9188
if self.len == self.capacity {
92-
let b = self.take();
93-
*self = (b.reserve)(b, 1);
89+
self.reserve(1);
9490
}
9591
unsafe {
9692
*self.data.add(self.len) = v;
9793
self.len += 1;
9894
}
9995
}
96+
97+
#[inline]
98+
fn layout(&self) -> Layout {
99+
Layout::array::<u8>(self.capacity).unwrap()
100+
}
101+
102+
#[inline(never)]
103+
fn reserve(&mut self, amount: usize) {
104+
debug_assert!(amount > 0);
105+
self.capacity += amount;
106+
assert!(self.capacity < isize::MAX as usize);
107+
let layout = self.layout();
108+
self.data = if self.data.is_null() {
109+
unsafe { alloc::alloc(layout) }
110+
} else {
111+
unsafe { alloc::realloc(self.data, layout, self.capacity) }
112+
};
113+
if self.data.is_null() {
114+
alloc::handle_alloc_error(layout);
115+
}
116+
}
100117
}
101118

102119
impl Write for Buffer {
@@ -121,35 +138,10 @@ impl Write for Buffer {
121138
impl Drop for Buffer {
122139
#[inline]
123140
fn drop(&mut self) {
124-
let b = self.take();
125-
(b.drop)(b);
126-
}
127-
}
128-
129-
impl From<Vec<u8>> for Buffer {
130-
fn from(v: Vec<u8>) -> Self {
131-
let mut v = ManuallyDrop::new(v);
132-
let (data, len, capacity) = (v.as_mut_ptr(), v.len(), v.capacity());
133-
134-
// This utility function is nested in here because it can *only*
135-
// be safely called on `Buffer`s created by *this* `proc_macro`.
136-
fn to_vec(b: Buffer) -> Vec<u8> {
141+
if !self.data.is_null() {
137142
unsafe {
138-
let b = ManuallyDrop::new(b);
139-
Vec::from_raw_parts(b.data, b.len, b.capacity)
143+
alloc::dealloc(self.data, self.layout());
140144
}
141145
}
142-
143-
extern "C" fn reserve(b: Buffer, additional: usize) -> Buffer {
144-
let mut v = to_vec(b);
145-
v.reserve(additional);
146-
Buffer::from(v)
147-
}
148-
149-
extern "C" fn drop(b: Buffer) {
150-
mem::drop(to_vec(b));
151-
}
152-
153-
Buffer { data, len, capacity, reserve, drop }
154146
}
155147
}

0 commit comments

Comments
 (0)