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 ;
55use core:: cmp;
66use core:: mem:: { self , ManuallyDrop , MaybeUninit } ;
77use core:: ops:: Drop ;
@@ -172,7 +172,7 @@ impl<T, A: AllocRef> RawVec<T, A> {
172172 } else {
173173 // We avoid `unwrap_or_else` here because it bloats the amount of
174174 // LLVM IR generated.
175- let layout = match Layout :: array :: < T > ( capacity) {
175+ let layout = match array_layout ( Layout :: new :: < T > ( ) , capacity) {
176176 Ok ( layout) => layout,
177177 Err ( _) => capacity_overflow ( ) ,
178178 } ;
@@ -423,10 +423,10 @@ impl<T, A: AllocRef> RawVec<T, A> {
423423 } ;
424424 let cap = cmp:: max ( min_non_zero_cap, cap) ;
425425
426- let new_layout = Layout :: array :: < T > ( cap ) ;
426+ let elem_layout = Layout :: new :: < T > ( ) ;
427427
428428 // `finish_grow` is non-generic over `T`.
429- let memory = finish_grow ( new_layout , self . current_memory ( ) , & mut self . alloc ) ?;
429+ let memory = finish_grow ( cap , elem_layout , self . current_memory ( ) , & mut self . alloc ) ?;
430430 self . set_memory ( memory) ;
431431 Ok ( ( ) )
432432 }
@@ -442,10 +442,11 @@ impl<T, A: AllocRef> RawVec<T, A> {
442442 }
443443
444444 let cap = len. checked_add ( additional) . ok_or ( CapacityOverflow ) ?;
445- let new_layout = Layout :: array :: < T > ( cap) ;
445+
446+ let elem_layout = Layout :: new :: < T > ( ) ;
446447
447448 // `finish_grow` is non-generic over `T`.
448- let memory = finish_grow ( new_layout , self . current_memory ( ) , & mut self . alloc ) ?;
449+ let memory = finish_grow ( cap , elem_layout , self . current_memory ( ) , & mut self . alloc ) ?;
449450 self . set_memory ( memory) ;
450451 Ok ( ( ) )
451452 }
@@ -478,15 +479,16 @@ impl<T, A: AllocRef> RawVec<T, A> {
478479// significant, because the number of different `A` types seen in practice is
479480// much smaller than the number of `T` types.)
480481fn finish_grow < A > (
481- new_layout : Result < Layout , LayoutErr > ,
482+ cap : usize ,
483+ elem_layout : Layout ,
482484 current_memory : Option < ( NonNull < u8 > , Layout ) > ,
483485 alloc : & mut A ,
484486) -> Result < MemoryBlock , TryReserveError >
485487where
486488 A : AllocRef ,
487489{
488490 // Check for the error here to minimize the size of `RawVec::grow_*`.
489- let new_layout = new_layout . map_err ( |_| CapacityOverflow ) ?;
491+ let new_layout = array_layout ( elem_layout , cap ) ?;
490492
491493 alloc_guard ( new_layout. size ( ) ) ?;
492494
@@ -501,6 +503,15 @@ where
501503 Ok ( memory)
502504}
503505
506+ // This is equivalent to Layout::array, but is non-generic and has a different
507+ // error type in its result. It helps reduce the amount of LLVM IR generated.
508+ #[ inline]
509+ fn array_layout ( elem_layout : Layout , n : usize ) -> Result < Layout , TryReserveError > {
510+ let ( new_layout, offset) = elem_layout. repeat ( n) . map_err ( |_| CapacityOverflow ) ?;
511+ debug_assert_eq ! ( offset, elem_layout. size( ) ) ;
512+ Ok ( new_layout. pad_to_align ( ) )
513+ }
514+
504515unsafe impl < #[ may_dangle] T , A : AllocRef > Drop for RawVec < T , A > {
505516 /// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
506517 fn drop ( & mut self ) {
0 commit comments