Skip to content

Commit

Permalink
try
Browse files Browse the repository at this point in the history
  • Loading branch information
glandium committed Nov 25, 2023
1 parent 0f3f2d7 commit c4e4b69
Showing 1 changed file with 36 additions and 14 deletions.
50 changes: 36 additions & 14 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,13 +479,15 @@ pub struct RcSlice<T> {
rc: ManuallyDrop<Rc<[T]>>,
// The real capacity of the allocation.
capacity: usize,
displacement: usize,
}

impl<T> RcSlice<T> {
pub fn new() -> RcSlice<T> {
RcSlice {
rc: ManuallyDrop::new(Rc::new([])),
capacity: 0,
displacement: 0,
}
}
}
Expand All @@ -494,7 +496,8 @@ impl<T> Drop for RcSlice<T> {
fn drop(&mut self) {
if let Some(this) = Rc::get_mut(&mut self.rc) {
// last reference, we can drop.
let (layout, offset) = RcSliceBuilder::<T>::layout_for_size(self.capacity);
let (layout, offset) =
RcSliceBuilder::<T>::layout_for_size(self.capacity + self.displacement);
unsafe {
ptr::drop_in_place(this);
dealloc_keep((this.as_mut_ptr() as *mut u8).sub(offset), layout);
Expand All @@ -513,7 +516,7 @@ impl<T> Deref for RcSlice<T> {
type Target = [T];

fn deref(&self) -> &Self::Target {
&self.rc
&self.rc[self.displacement..]
}
}

Expand All @@ -523,6 +526,7 @@ pub struct RcSliceBuilder<T> {
ptr: NonNull<T>,
len: usize,
capacity: usize,
displacement: usize,
marker: PhantomData<T>,
}

Expand All @@ -532,6 +536,7 @@ impl<T> RcSliceBuilder<T> {
ptr: NonNull::dangling(),
len: 0,
capacity: 0,
displacement: 0,
marker: PhantomData,
}
}
Expand All @@ -546,10 +551,11 @@ impl<T> RcSliceBuilder<T> {

pub fn into_rc(self) -> RcSlice<T> {
if self.len != 0 {
let (_layout, offset) = Self::layout_for_size(self.capacity);
let (_layout, offset) = Self::layout_for_size(self.capacity + self.displacement);
let ptr = self.ptr;
let len = self.len;
let capacity = self.capacity;
let displacement = self.displacement;
mem::forget(self);
unsafe {
ptr::write(
Expand All @@ -558,9 +564,10 @@ impl<T> RcSliceBuilder<T> {
);
RcSlice {
rc: ManuallyDrop::new(Rc::from_raw(
NonNull::slice_from_raw_parts(ptr, len).as_ptr(),
NonNull::slice_from_raw_parts(ptr, len + displacement).as_ptr(),
)),
capacity,
displacement,
}
}
} else {
Expand All @@ -581,17 +588,20 @@ impl<T> RcSliceBuilder<T> {
let next_pow2 = size.next_power_of_two();
let gap = next_pow2 / 4 - 1;
let size = (size + gap) & !gap;
(Layout::from_size_align(size, align).unwrap(), offset)
(Layout::from_size_align(size, align).unwrap().align_to(64).unwrap(), offset)
}

#[inline(never)]
fn grow_to(&mut self, needed_len: usize) {
let (layout, offset) = Self::layout_for_size(needed_len);
if self.capacity == 0 {
self.displacement = (64 - 16) + (rand::random::<u8>() as usize / 4) * 64;
}
let (layout, offset) = Self::layout_for_size(needed_len + self.displacement);
unsafe {
let (ptr, capacity) = if self.capacity == 0 {
alloc_recycle(layout)
} else {
let (current_layout, _) = Self::layout_for_size(self.capacity);
let (current_layout, _) = Self::layout_for_size(self.capacity + self.displacement);
(
std::alloc::realloc(
self.ptr.cast::<u8>().as_ptr().sub(offset),
Expand All @@ -605,7 +615,7 @@ impl<T> RcSliceBuilder<T> {
panic!("Out of memory");
}
self.ptr = NonNull::new_unchecked(ptr.add(offset) as *mut T);
self.capacity = capacity - offset;
self.capacity = capacity - self.displacement - offset;
}
}

Expand All @@ -620,7 +630,7 @@ impl<T> RcSliceBuilder<T> {
pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
unsafe {
std::slice::from_raw_parts_mut(
self.ptr.as_ptr().add(self.len) as *mut MaybeUninit<T>,
self.ptr.as_ptr().add(self.displacement + self.len) as *mut MaybeUninit<T>,
self.capacity - self.len,
)
}
Expand All @@ -636,7 +646,11 @@ impl<T: Copy> RcSliceBuilder<T> {
pub fn extend_from_slice(&mut self, other: &[T]) {
self.reserve(other.len());
unsafe {
ptr::copy_nonoverlapping(other.as_ptr(), self.ptr.as_ptr().add(self.len), other.len());
ptr::copy_nonoverlapping(
other.as_ptr(),
self.ptr.as_ptr().add(self.displacement + self.len),
other.len(),
);
}
self.len += other.len();
}
Expand All @@ -646,22 +660,30 @@ impl<T> Deref for RcSliceBuilder<T> {
type Target = [T];

fn deref(&self) -> &Self::Target {
unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
unsafe { std::slice::from_raw_parts(self.ptr.as_ptr().add(self.displacement), self.len) }
}
}

impl<T> DerefMut for RcSliceBuilder<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { std::slice::from_raw_parts_mut(self.ptr.as_mut(), self.len) }
unsafe {
std::slice::from_raw_parts_mut(self.ptr.as_ptr().add(self.displacement), self.len)
}
}
}

impl<T> Drop for RcSliceBuilder<T> {
fn drop(&mut self) {
unsafe {
ptr::drop_in_place(NonNull::slice_from_raw_parts(self.ptr, self.len).as_ptr());
ptr::drop_in_place(
NonNull::slice_from_raw_parts(
NonNull::new_unchecked(self.ptr.as_ptr().add(self.displacement)),
self.len,
)
.as_ptr(),
);
if self.capacity > 0 {
let (layout, offset) = Self::layout_for_size(self.capacity);
let (layout, offset) = Self::layout_for_size(self.capacity + self.displacement);
dealloc_keep(self.ptr.cast::<u8>().as_ptr().sub(offset), layout);
}
}
Expand Down

0 comments on commit c4e4b69

Please sign in to comment.