Skip to content

Commit 6c3ebcd

Browse files
committed
make Layout's align a NonZeroUsize
1 parent 74d0939 commit 6c3ebcd

File tree

1 file changed

+38
-36
lines changed

1 file changed

+38
-36
lines changed

src/libcore/alloc.rs

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use fmt;
2020
use mem;
2121
use usize;
2222
use ptr::{self, NonNull};
23+
use num::NonZeroUsize;
2324

2425
extern {
2526
/// An opaque, unsized type. Used for pointers to allocated memory.
@@ -66,7 +67,7 @@ fn size_align<T>() -> (usize, usize) {
6667
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
6768
pub struct Layout {
6869
// size of the requested block of memory, measured in bytes.
69-
size: usize,
70+
size_: usize,
7071

7172
// alignment of the requested block of memory, measured in bytes.
7273
// we ensure that this is always a power-of-two, because API's
@@ -75,17 +76,12 @@ pub struct Layout {
7576
//
7677
// (However, we do not analogously require `align >= sizeof(void*)`,
7778
// even though that is *also* a requirement of `posix_memalign`.)
78-
align: usize,
79+
align_: NonZeroUsize,
7980
}
8081

81-
82-
// FIXME: audit default implementations for overflow errors,
83-
// (potentially switching to overflowing_add and
84-
// overflowing_mul as necessary).
85-
8682
impl Layout {
8783
/// Constructs a `Layout` from a given `size` and `align`,
88-
/// or returns `None` if either of the following conditions
84+
/// or returns `LayoutErr` if either of the following conditions
8985
/// are not met:
9086
///
9187
/// * `align` must be a power of two,
@@ -126,23 +122,23 @@ impl Layout {
126122
///
127123
/// # Safety
128124
///
129-
/// This function is unsafe as it does not verify that `align` is
130-
/// a power-of-two nor `size` aligned to `align` fits within the
131-
/// address space (i.e. the `Layout::from_size_align` preconditions).
125+
/// This function is unsafe as it does not verify the preconditions from
126+
/// [`Layout::from_size_align`](#method.from_size_align).
132127
#[inline]
133128
pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
134-
Layout { size: size, align: align }
129+
Layout { size_: size, align_: NonZeroUsize::new_unchecked(align) }
135130
}
136131

137132
/// The minimum size in bytes for a memory block of this layout.
138133
#[inline]
139-
pub fn size(&self) -> usize { self.size }
134+
pub fn size(&self) -> usize { self.size_ }
140135

141136
/// The minimum byte alignment for a memory block of this layout.
142137
#[inline]
143-
pub fn align(&self) -> usize { self.align }
138+
pub fn align(&self) -> usize { self.align_.get() }
144139

145140
/// Constructs a `Layout` suitable for holding a value of type `T`.
141+
#[inline]
146142
pub fn new<T>() -> Self {
147143
let (size, align) = size_align::<T>();
148144
// Note that the align is guaranteed by rustc to be a power of two and
@@ -158,6 +154,7 @@ impl Layout {
158154
/// Produces layout describing a record that could be used to
159155
/// allocate backing structure for `T` (which could be a trait
160156
/// or other unsized type like a slice).
157+
#[inline]
161158
pub fn for_value<T: ?Sized>(t: &T) -> Self {
162159
let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
163160
// See rationale in `new` for why this us using an unsafe variant below
@@ -181,18 +178,19 @@ impl Layout {
181178
///
182179
/// # Panics
183180
///
184-
/// Panics if the combination of `self.size` and the given `align`
185-
/// violates the conditions listed in `from_size_align`.
181+
/// Panics if the combination of `self.size()` and the given `align`
182+
/// violates the conditions listed in
183+
/// [`Layout::from_size_align`](#method.from_size_align).
186184
#[inline]
187185
pub fn align_to(&self, align: usize) -> Self {
188-
Layout::from_size_align(self.size, cmp::max(self.align, align)).unwrap()
186+
Layout::from_size_align(self.size(), cmp::max(self.align(), align)).unwrap()
189187
}
190188

191189
/// Returns the amount of padding we must insert after `self`
192190
/// to ensure that the following address will satisfy `align`
193191
/// (measured in bytes).
194192
///
195-
/// E.g. if `self.size` is 9, then `self.padding_needed_for(4)`
193+
/// E.g. if `self.size()` is 9, then `self.padding_needed_for(4)`
196194
/// returns 3, because that is the minimum number of bytes of
197195
/// padding required to get a 4-aligned address (assuming that the
198196
/// corresponding memory block starts at a 4-aligned address).
@@ -203,9 +201,12 @@ impl Layout {
203201
/// Note that the utility of the returned value requires `align`
204202
/// to be less than or equal to the alignment of the starting
205203
/// address for the whole allocated block of memory. One way to
206-
/// satisfy this constraint is to ensure `align <= self.align`.
204+
/// satisfy this constraint is to ensure `align <= self.align()`.
207205
#[inline]
208206
pub fn padding_needed_for(&self, align: usize) -> usize {
207+
// **FIXME**: This function is only called with proper power-of-two
208+
// alignments. Maybe we should turn this into a real assert!.
209+
debug_assert!(align.is_power_of_two());
209210
let len = self.size();
210211

211212
// Rounded up value is:
@@ -227,7 +228,8 @@ impl Layout {
227228
// size and padding overflow in the above manner should cause
228229
// the allocator to yield an error anyway.)
229230

230-
let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1);
231+
let len_rounded_up = len.wrapping_add(align).wrapping_sub(1)
232+
& !align.wrapping_sub(1);
231233
return len_rounded_up.wrapping_sub(len);
232234
}
233235

@@ -238,14 +240,14 @@ impl Layout {
238240
/// layout of the array and `offs` is the distance between the start
239241
/// of each element in the array.
240242
///
241-
/// On arithmetic overflow, returns `None`.
243+
/// On arithmetic overflow, returns `LayoutErr`.
242244
#[inline]
243245
pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
244-
let padded_size = self.size.checked_add(self.padding_needed_for(self.align))
246+
let padded_size = self.size().checked_add(self.padding_needed_for(self.align()))
245247
.ok_or(LayoutErr { private: () })?;
246248
let alloc_size = padded_size.checked_mul(n)
247249
.ok_or(LayoutErr { private: () })?;
248-
Ok((Layout::from_size_align(alloc_size, self.align)?, padded_size))
250+
Ok((Layout::from_size_align(alloc_size, self.align())?, padded_size))
249251
}
250252

251253
/// Creates a layout describing the record for `self` followed by
@@ -258,16 +260,16 @@ impl Layout {
258260
/// start of the `next` embedded within the concatenated record
259261
/// (assuming that the record itself starts at offset 0).
260262
///
261-
/// On arithmetic overflow, returns `None`.
263+
/// On arithmetic overflow, returns `LayoutErr`.
262264
pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
263-
let new_align = cmp::max(self.align, next.align);
264-
let realigned = Layout::from_size_align(self.size, new_align)?;
265+
let new_align = cmp::max(self.align(), next.align());
266+
let realigned = Layout::from_size_align(self.size(), new_align)?;
265267

266-
let pad = realigned.padding_needed_for(next.align);
268+
let pad = realigned.padding_needed_for(next.align());
267269

268-
let offset = self.size.checked_add(pad)
270+
let offset = self.size().checked_add(pad)
269271
.ok_or(LayoutErr { private: () })?;
270-
let new_size = offset.checked_add(next.size)
272+
let new_size = offset.checked_add(next.size())
271273
.ok_or(LayoutErr { private: () })?;
272274

273275
let layout = Layout::from_size_align(new_size, new_align)?;
@@ -285,10 +287,10 @@ impl Layout {
285287
/// guaranteed that all elements in the array will be properly
286288
/// aligned.
287289
///
288-
/// On arithmetic overflow, returns `None`.
290+
/// On arithmetic overflow, returns `LayoutErr`.
289291
pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutErr> {
290292
let size = self.size().checked_mul(n).ok_or(LayoutErr { private: () })?;
291-
Layout::from_size_align(size, self.align)
293+
Layout::from_size_align(size, self.align())
292294
}
293295

294296
/// Creates a layout describing the record for `self` followed by
@@ -305,17 +307,17 @@ impl Layout {
305307
/// signature out of convenience in matching the signature of
306308
/// `extend`.)
307309
///
308-
/// On arithmetic overflow, returns `None`.
310+
/// On arithmetic overflow, returns `LayoutErr`.
309311
pub fn extend_packed(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
310312
let new_size = self.size().checked_add(next.size())
311313
.ok_or(LayoutErr { private: () })?;
312-
let layout = Layout::from_size_align(new_size, self.align)?;
314+
let layout = Layout::from_size_align(new_size, self.align())?;
313315
Ok((layout, self.size()))
314316
}
315317

316318
/// Creates a layout describing the record for a `[T; n]`.
317319
///
318-
/// On arithmetic overflow, returns `None`.
320+
/// On arithmetic overflow, returns `LayoutErr`.
319321
pub fn array<T>(n: usize) -> Result<Self, LayoutErr> {
320322
Layout::new::<T>()
321323
.repeat(n)
@@ -834,7 +836,7 @@ pub unsafe trait Alloc {
834836
layout: Layout,
835837
new_size: usize) -> Result<(), CannotReallocInPlace> {
836838
let _ = ptr; // this default implementation doesn't care about the actual address.
837-
debug_assert!(new_size >= layout.size);
839+
debug_assert!(new_size >= layout.size());
838840
let (_l, u) = self.usable_size(&layout);
839841
// _l <= layout.size() [guaranteed by usable_size()]
840842
// layout.size() <= new_layout.size() [required by this method]
@@ -889,7 +891,7 @@ pub unsafe trait Alloc {
889891
layout: Layout,
890892
new_size: usize) -> Result<(), CannotReallocInPlace> {
891893
let _ = ptr; // this default implementation doesn't care about the actual address.
892-
debug_assert!(new_size <= layout.size);
894+
debug_assert!(new_size <= layout.size());
893895
let (l, _u) = self.usable_size(&layout);
894896
// layout.size() <= _u [guaranteed by usable_size()]
895897
// new_layout.size() <= layout.size() [required by this method]

0 commit comments

Comments
 (0)