Rollup merge of #55764 - murarth:fix-rc-alloc, r=RalfJung
Fix Rc/Arc allocation layout * Rounds allocation layout up to a multiple of alignment * Adds a convenience method `Layout::pad_to_align` to perform rounding Closes #55747 cc #55724
This commit is contained in:
commit
d2aeef06f2
3 changed files with 25 additions and 4 deletions
|
@ -672,14 +672,16 @@ impl<T: ?Sized> Rc<T> {
|
||||||
// Previously, layout was calculated on the expression
|
// Previously, layout was calculated on the expression
|
||||||
// `&*(ptr as *const RcBox<T>)`, but this created a misaligned
|
// `&*(ptr as *const RcBox<T>)`, but this created a misaligned
|
||||||
// reference (see #54908).
|
// reference (see #54908).
|
||||||
let (layout, _) = Layout::new::<RcBox<()>>()
|
let layout = Layout::new::<RcBox<()>>()
|
||||||
.extend(Layout::for_value(&*ptr)).unwrap();
|
.extend(Layout::for_value(&*ptr)).unwrap().0
|
||||||
|
.pad_to_align().unwrap();
|
||||||
|
|
||||||
let mem = Global.alloc(layout)
|
let mem = Global.alloc(layout)
|
||||||
.unwrap_or_else(|_| handle_alloc_error(layout));
|
.unwrap_or_else(|_| handle_alloc_error(layout));
|
||||||
|
|
||||||
// Initialize the RcBox
|
// Initialize the RcBox
|
||||||
let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>;
|
let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>;
|
||||||
|
debug_assert_eq!(Layout::for_value(&*inner), layout);
|
||||||
|
|
||||||
ptr::write(&mut (*inner).strong, Cell::new(1));
|
ptr::write(&mut (*inner).strong, Cell::new(1));
|
||||||
ptr::write(&mut (*inner).weak, Cell::new(1));
|
ptr::write(&mut (*inner).weak, Cell::new(1));
|
||||||
|
|
|
@ -575,14 +575,16 @@ impl<T: ?Sized> Arc<T> {
|
||||||
// Previously, layout was calculated on the expression
|
// Previously, layout was calculated on the expression
|
||||||
// `&*(ptr as *const ArcInner<T>)`, but this created a misaligned
|
// `&*(ptr as *const ArcInner<T>)`, but this created a misaligned
|
||||||
// reference (see #54908).
|
// reference (see #54908).
|
||||||
let (layout, _) = Layout::new::<ArcInner<()>>()
|
let layout = Layout::new::<ArcInner<()>>()
|
||||||
.extend(Layout::for_value(&*ptr)).unwrap();
|
.extend(Layout::for_value(&*ptr)).unwrap().0
|
||||||
|
.pad_to_align().unwrap();
|
||||||
|
|
||||||
let mem = Global.alloc(layout)
|
let mem = Global.alloc(layout)
|
||||||
.unwrap_or_else(|_| handle_alloc_error(layout));
|
.unwrap_or_else(|_| handle_alloc_error(layout));
|
||||||
|
|
||||||
// Initialize the ArcInner
|
// Initialize the ArcInner
|
||||||
let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>;
|
let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>;
|
||||||
|
debug_assert_eq!(Layout::for_value(&*inner), layout);
|
||||||
|
|
||||||
ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1));
|
ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1));
|
||||||
ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));
|
ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));
|
||||||
|
|
|
@ -218,6 +218,23 @@ impl Layout {
|
||||||
len_rounded_up.wrapping_sub(len)
|
len_rounded_up.wrapping_sub(len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a layout by rounding the size of this layout up to a multiple
|
||||||
|
/// of the layout's alignment.
|
||||||
|
///
|
||||||
|
/// Returns `Err` if the padded size would overflow.
|
||||||
|
///
|
||||||
|
/// This is equivalent to adding the result of `padding_needed_for`
|
||||||
|
/// to the layout's current size.
|
||||||
|
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||||
|
#[inline]
|
||||||
|
pub fn pad_to_align(&self) -> Result<Layout, LayoutErr> {
|
||||||
|
let pad = self.padding_needed_for(self.align());
|
||||||
|
let new_size = self.size().checked_add(pad)
|
||||||
|
.ok_or(LayoutErr { private: () })?;
|
||||||
|
|
||||||
|
Layout::from_size_align(new_size, self.align())
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a layout describing the record for `n` instances of
|
/// Creates a layout describing the record for `n` instances of
|
||||||
/// `self`, with a suitable amount of padding between each to
|
/// `self`, with a suitable amount of padding between each to
|
||||||
/// ensure that each instance is given its requested size and
|
/// ensure that each instance is given its requested size and
|
||||||
|
|
Loading…
Add table
Reference in a new issue