Skip to content

Commit 6057361

Browse files
committed
Introduce array_layout.
As a non-generic alternative to `Layout::array`.
1 parent c977b87 commit 6057361

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

src/liballoc/raw_vec.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![unstable(feature = "raw_vec_internals", reason = "implementation detail", issue = "none")]
22
#![doc(hidden)]
33

4-
use core::alloc::{LayoutErr, MemoryBlock};
4+
use core::alloc::MemoryBlock;
55
use core::cmp;
66
use core::mem::{self, ManuallyDrop, MaybeUninit};
77
use core::ops::Drop;
@@ -172,7 +172,8 @@ impl<T, A: AllocRef> RawVec<T, A> {
172172
if mem::size_of::<T>() == 0 {
173173
Self::new_in(alloc)
174174
} else {
175-
let layout = Layout::array::<T>(capacity).unwrap_or_else(|_| capacity_overflow());
175+
let layout =
176+
array_layout(Layout::new::<T>(), capacity).unwrap_or_else(|_| capacity_overflow());
176177
alloc_guard(layout.size()).unwrap_or_else(|_| capacity_overflow());
177178

178179
let memory = alloc.alloc(layout, init).unwrap_or_else(|_| handle_alloc_error(layout));
@@ -418,10 +419,10 @@ impl<T, A: AllocRef> RawVec<T, A> {
418419
};
419420
let cap = cmp::max(min_non_zero_cap, cap);
420421

421-
let new_layout = Layout::array::<T>(cap);
422+
let elem_layout = Layout::new::<T>();
422423

423424
// `finish_grow` is non-generic over `T`.
424-
let memory = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?;
425+
let memory = finish_grow(cap, elem_layout, self.current_memory(), &mut self.alloc)?;
425426
self.set_memory(memory);
426427
Ok(())
427428
}
@@ -437,10 +438,11 @@ impl<T, A: AllocRef> RawVec<T, A> {
437438
}
438439

439440
let cap = len.checked_add(additional).ok_or(CapacityOverflow)?;
440-
let new_layout = Layout::array::<T>(cap);
441+
442+
let elem_layout = Layout::new::<T>();
441443

442444
// `finish_grow` is non-generic over `T`.
443-
let memory = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?;
445+
let memory = finish_grow(cap, elem_layout, self.current_memory(), &mut self.alloc)?;
444446
self.set_memory(memory);
445447
Ok(())
446448
}
@@ -472,16 +474,17 @@ impl<T, A: AllocRef> RawVec<T, A> {
472474
// above `RawVec::grow_amortized` for details. (The `A` parameter isn't
473475
// significant, because the number of different `A` types seen in practice is
474476
// much smaller than the number of `T` types.)
477+
#[inline]
475478
fn finish_grow<A>(
476-
new_layout: Result<Layout, LayoutErr>,
479+
cap: usize,
480+
elem_layout: Layout,
477481
current_memory: Option<(NonNull<u8>, Layout)>,
478482
alloc: &mut A,
479483
) -> Result<MemoryBlock, TryReserveError>
480484
where
481485
A: AllocRef,
482486
{
483-
// Check for the error here to minimize the size of `RawVec::grow_*`.
484-
let new_layout = new_layout.map_err(|_| CapacityOverflow)?;
487+
let new_layout = array_layout(elem_layout, cap)?;
485488

486489
alloc_guard(new_layout.size())?;
487490

@@ -496,6 +499,15 @@ where
496499
Ok(memory)
497500
}
498501

502+
// This is equivalent to Layout::array, but is non-generic and has a different
503+
// error type in its result. It helps reduce the amount of LLVM IR generated.
504+
#[inline]
505+
fn array_layout(elem_layout: Layout, n: usize) -> Result<Layout, TryReserveError> {
506+
let (new_layout, offset) = elem_layout.repeat(n).map_err(|_| CapacityOverflow)?;
507+
debug_assert_eq!(offset, elem_layout.size());
508+
Ok(new_layout.pad_to_align())
509+
}
510+
499511
unsafe impl<#[may_dangle] T, A: AllocRef> Drop for RawVec<T, A> {
500512
/// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
501513
fn drop(&mut self) {

0 commit comments

Comments
 (0)