1
1
#![ unstable( feature = "raw_vec_internals" , reason = "implementation detail" , issue = "none" ) ]
2
2
#![ doc( hidden) ]
3
3
4
- use core:: alloc:: { LayoutErr , MemoryBlock } ;
4
+ use core:: alloc:: MemoryBlock ;
5
5
use core:: cmp;
6
6
use core:: mem:: { self , ManuallyDrop , MaybeUninit } ;
7
7
use core:: ops:: Drop ;
@@ -172,7 +172,8 @@ impl<T, A: AllocRef> RawVec<T, A> {
172
172
if mem:: size_of :: < T > ( ) == 0 {
173
173
Self :: new_in ( alloc)
174
174
} 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 ( ) ) ;
176
177
alloc_guard ( layout. size ( ) ) . unwrap_or_else ( |_| capacity_overflow ( ) ) ;
177
178
178
179
let memory = alloc. alloc ( layout, init) . unwrap_or_else ( |_| handle_alloc_error ( layout) ) ;
@@ -418,10 +419,10 @@ impl<T, A: AllocRef> RawVec<T, A> {
418
419
} ;
419
420
let cap = cmp:: max ( min_non_zero_cap, cap) ;
420
421
421
- let new_layout = Layout :: array :: < T > ( cap ) ;
422
+ let elem_layout = Layout :: new :: < T > ( ) ;
422
423
423
424
// `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 ) ?;
425
426
self . set_memory ( memory) ;
426
427
Ok ( ( ) )
427
428
}
@@ -437,10 +438,11 @@ impl<T, A: AllocRef> RawVec<T, A> {
437
438
}
438
439
439
440
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 > ( ) ;
441
443
442
444
// `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 ) ?;
444
446
self . set_memory ( memory) ;
445
447
Ok ( ( ) )
446
448
}
@@ -472,16 +474,17 @@ impl<T, A: AllocRef> RawVec<T, A> {
472
474
// above `RawVec::grow_amortized` for details. (The `A` parameter isn't
473
475
// significant, because the number of different `A` types seen in practice is
474
476
// much smaller than the number of `T` types.)
477
+ #[ inline]
475
478
fn finish_grow < A > (
476
- new_layout : Result < Layout , LayoutErr > ,
479
+ cap : usize ,
480
+ elem_layout : Layout ,
477
481
current_memory : Option < ( NonNull < u8 > , Layout ) > ,
478
482
alloc : & mut A ,
479
483
) -> Result < MemoryBlock , TryReserveError >
480
484
where
481
485
A : AllocRef ,
482
486
{
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) ?;
485
488
486
489
alloc_guard ( new_layout. size ( ) ) ?;
487
490
@@ -496,6 +499,15 @@ where
496
499
Ok ( memory)
497
500
}
498
501
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
+
499
511
unsafe impl < #[ may_dangle] T , A : AllocRef > Drop for RawVec < T , A > {
500
512
/// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
501
513
fn drop ( & mut self ) {
0 commit comments