-
-
Notifications
You must be signed in to change notification settings - Fork 15.1k
simplify some proc_macro things
#157271
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
simplify some proc_macro things
#157271
Changes from all commits
49ceda6
e789c00
11ffc80
effe248
3912299
7f9f32a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,15 @@ | ||
| //! Buffer management for same-process client<->server communication. | ||
|
|
||
| use std::io::{self, Write}; | ||
| use std::mem::{self, ManuallyDrop}; | ||
| use std::ops::{Deref, DerefMut}; | ||
| use std::slice; | ||
| use std::alloc::{self, Layout}; | ||
| use std::ops::Deref; | ||
| use std::ptr::null_mut; | ||
| use std::{mem, slice}; | ||
|
|
||
| #[repr(C)] | ||
| pub struct Buffer { | ||
| data: *mut u8, | ||
| len: usize, | ||
| capacity: usize, | ||
| reserve: extern "C" fn(Buffer, usize) -> Buffer, | ||
| drop: extern "C" fn(Buffer), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is it better to directly manage |
||
| } | ||
|
|
||
| unsafe impl Sync for Buffer {} | ||
|
|
@@ -20,7 +18,7 @@ unsafe impl Send for Buffer {} | |
| impl Default for Buffer { | ||
| #[inline] | ||
| fn default() -> Self { | ||
| Self::from(vec![]) | ||
| Self { data: null_mut(), len: 0, capacity: 0 } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -32,13 +30,6 @@ impl Deref for Buffer { | |
| } | ||
| } | ||
|
|
||
| impl DerefMut for Buffer { | ||
| #[inline] | ||
| fn deref_mut(&mut self) -> &mut [u8] { | ||
| unsafe { slice::from_raw_parts_mut(self.data, self.len) } | ||
| } | ||
| } | ||
|
|
||
| impl Buffer { | ||
| #[inline] | ||
| pub(super) fn new() -> Self { | ||
|
|
@@ -55,27 +46,10 @@ impl Buffer { | |
| mem::take(self) | ||
| } | ||
|
|
||
| // We have the array method separate from extending from a slice. This is | ||
| // because in the case of small arrays, codegen can be more efficient | ||
| // (avoiding a memmove call). With extend_from_slice, LLVM at least | ||
| // currently is not able to make that optimization. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any specific reason to remove this optimization? |
||
| #[inline] | ||
| pub(super) fn extend_from_array<const N: usize>(&mut self, xs: &[u8; N]) { | ||
| if xs.len() > (self.capacity - 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(); | ||
| } | ||
| } | ||
|
|
||
| #[inline] | ||
| pub(super) fn extend_from_slice(&mut self, xs: &[u8]) { | ||
| if xs.len() > (self.capacity - self.len) { | ||
| let b = self.take(); | ||
| *self = (b.reserve)(b, xs.len()); | ||
| self.reserve(xs.len()); | ||
| } | ||
| unsafe { | ||
| xs.as_ptr().copy_to_nonoverlapping(self.data.add(self.len), xs.len()); | ||
|
|
@@ -89,67 +63,42 @@ impl Buffer { | |
| // 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); | ||
| self.reserve(1); | ||
| } | ||
| unsafe { | ||
| *self.data.add(self.len) = v; | ||
| self.len += 1; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl Write for Buffer { | ||
| #[inline] | ||
| fn write(&mut self, xs: &[u8]) -> io::Result<usize> { | ||
| self.extend_from_slice(xs); | ||
| Ok(xs.len()) | ||
| } | ||
|
|
||
| #[inline] | ||
| fn write_all(&mut self, xs: &[u8]) -> io::Result<()> { | ||
| self.extend_from_slice(xs); | ||
| Ok(()) | ||
| fn layout(&self) -> Layout { | ||
| Layout::array::<u8>(self.capacity).unwrap() | ||
| } | ||
|
|
||
| #[inline] | ||
| fn flush(&mut self) -> io::Result<()> { | ||
| Ok(()) | ||
| fn reserve(&mut self, amount: usize) { | ||
| debug_assert!(amount > 0); | ||
| self.capacity += amount; | ||
| assert!(self.capacity < isize::MAX as usize); | ||
| let layout = self.layout(); | ||
| self.data = if self.data.is_null() { | ||
| unsafe { alloc::alloc(layout) } | ||
| } else { | ||
| unsafe { alloc::realloc(self.data, layout, self.capacity) } | ||
| }; | ||
| if self.data.is_null() { | ||
| alloc::handle_alloc_error(layout); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl Drop for Buffer { | ||
| #[inline] | ||
| fn drop(&mut self) { | ||
| let b = self.take(); | ||
| (b.drop)(b); | ||
| } | ||
| } | ||
|
|
||
| impl From<Vec<u8>> for Buffer { | ||
| fn from(v: Vec<u8>) -> Self { | ||
| let mut v = ManuallyDrop::new(v); | ||
| let (data, len, capacity) = (v.as_mut_ptr(), v.len(), v.capacity()); | ||
|
|
||
| // This utility function is nested in here because it can *only* | ||
| // be safely called on `Buffer`s created by *this* `proc_macro`. | ||
| fn to_vec(b: Buffer) -> Vec<u8> { | ||
| if !self.data.is_null() { | ||
| unsafe { | ||
| let b = ManuallyDrop::new(b); | ||
| Vec::from_raw_parts(b.data, b.len, b.capacity) | ||
| alloc::dealloc(self.data, self.layout()); | ||
| } | ||
| } | ||
|
|
||
| extern "C" fn reserve(b: Buffer, additional: usize) -> Buffer { | ||
| let mut v = to_vec(b); | ||
| v.reserve(additional); | ||
| Buffer::from(v) | ||
| } | ||
|
|
||
| extern "C" fn drop(b: Buffer) { | ||
| mem::drop(to_vec(b)); | ||
| } | ||
|
|
||
| Buffer { data, len, capacity, reserve, drop } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this cause all tokenstreams to be unnecessarily retained on the server side until the end of the proc macro invocation even if the client drops it earlier?
View changes since the review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, the motivation is missing for this change now - what did this drop do, what happens now when it's removed, why it's good.