diff options
| author | Murarth <murarth@gmail.com> | 2018-11-07 10:59:25 -0700 |
|---|---|---|
| committer | Murarth <murarth@gmail.com> | 2018-11-08 11:50:02 -0700 |
| commit | 317f494c72aead3fecd73788569983fd2f8ea8a3 (patch) | |
| tree | 9ff610a28d4e52ba1301f8472d3aa7dc403aaeaf /src | |
| parent | 653da4fd006c97625247acd7e076d0782cdc149b (diff) | |
| download | rust-317f494c72aead3fecd73788569983fd2f8ea8a3.tar.gz rust-317f494c72aead3fecd73788569983fd2f8ea8a3.zip | |
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
Diffstat (limited to 'src')
| -rw-r--r-- | src/liballoc/rc.rs | 6 | ||||
| -rw-r--r-- | src/liballoc/sync.rs | 6 | ||||
| -rw-r--r-- | src/libcore/alloc.rs | 17 |
3 files changed, 25 insertions, 4 deletions
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 45f035ad04f..bb52d7990ff 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -672,14 +672,16 @@ impl<T: ?Sized> Rc<T> { // Previously, layout was calculated on the expression // `&*(ptr as *const RcBox<T>)`, but this created a misaligned // reference (see #54908). - let (layout, _) = Layout::new::<RcBox<()>>() - .extend(Layout::for_value(&*ptr)).unwrap(); + let layout = Layout::new::<RcBox<()>>() + .extend(Layout::for_value(&*ptr)).unwrap().0 + .pad_to_align().unwrap(); let mem = Global.alloc(layout) .unwrap_or_else(|_| handle_alloc_error(layout)); // Initialize the RcBox 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).weak, Cell::new(1)); diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 2c396b3b06b..b63b3684964 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -575,14 +575,16 @@ impl<T: ?Sized> Arc<T> { // Previously, layout was calculated on the expression // `&*(ptr as *const ArcInner<T>)`, but this created a misaligned // reference (see #54908). - let (layout, _) = Layout::new::<ArcInner<()>>() - .extend(Layout::for_value(&*ptr)).unwrap(); + let layout = Layout::new::<ArcInner<()>>() + .extend(Layout::for_value(&*ptr)).unwrap().0 + .pad_to_align().unwrap(); let mem = Global.alloc(layout) .unwrap_or_else(|_| handle_alloc_error(layout)); // Initialize the ArcInner 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).weak, atomic::AtomicUsize::new(1)); diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 113a85abecb..dd3e8da18a9 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -218,6 +218,23 @@ impl Layout { 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 /// `self`, with a suitable amount of padding between each to /// ensure that each instance is given its requested size and |
