22
33#![ stable( feature = "alloc_module" , since = "1.28.0" ) ]
44
5- use core:: intrinsics:: { min_align_of_val, size_of_val} ;
5+ use core:: intrinsics:: { self , min_align_of_val, size_of_val} ;
66use core:: ptr:: { NonNull , Unique } ;
77use core:: usize;
88
@@ -165,11 +165,19 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
165165#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
166166unsafe impl AllocRef for Global {
167167 #[ inline]
168- fn alloc ( & mut self , layout : Layout ) -> Result < ( NonNull < u8 > , usize ) , AllocErr > {
169- if layout. size ( ) == 0 {
168+ fn alloc ( & mut self , layout : Layout , init : AllocInit ) -> Result < ( NonNull < u8 > , usize ) , AllocErr > {
169+ let new_size = layout. size ( ) ;
170+ if new_size == 0 {
170171 Ok ( ( layout. dangling ( ) , 0 ) )
171172 } else {
172- unsafe { NonNull :: new ( alloc ( layout) ) . ok_or ( AllocErr ) . map ( |p| ( p, layout. size ( ) ) ) }
173+ unsafe {
174+ let raw_ptr = match init {
175+ AllocInit :: Uninitialized => alloc ( layout) ,
176+ AllocInit :: Zeroed => alloc_zeroed ( layout) ,
177+ } ;
178+ let ptr = NonNull :: new ( raw_ptr) . ok_or ( AllocErr ) ?;
179+ Ok ( ( ptr, new_size) )
180+ }
173181 }
174182 }
175183
@@ -181,33 +189,77 @@ unsafe impl AllocRef for Global {
181189 }
182190
183191 #[ inline]
184- unsafe fn realloc (
192+ unsafe fn grow (
185193 & mut self ,
186194 ptr : NonNull < u8 > ,
187195 layout : Layout ,
188196 new_size : usize ,
197+ placement : ReallocPlacement ,
198+ init : AllocInit ,
189199 ) -> Result < ( NonNull < u8 > , usize ) , AllocErr > {
190- match ( layout. size ( ) , new_size) {
191- ( 0 , 0 ) => Ok ( ( layout. dangling ( ) , 0 ) ) ,
192- ( 0 , _) => self . alloc ( Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ) ,
193- ( _, 0 ) => {
194- self . dealloc ( ptr, layout) ;
195- Ok ( ( layout. dangling ( ) , 0 ) )
200+ let old_size = layout. size ( ) ;
201+ debug_assert ! (
202+ new_size >= old_size,
203+ "`new_size` must be greater than or equal to `layout.size()`"
204+ ) ;
205+
206+ if old_size == new_size {
207+ return Ok ( ( ptr, new_size) ) ;
208+ }
209+
210+ match placement {
211+ ReallocPlacement :: MayMove => {
212+ if old_size == 0 {
213+ self . alloc ( Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) , init)
214+ } else {
215+ // `realloc` probably checks for `new_size > old_size` or something similar.
216+ // `new_size` must be greater than or equal to `old_size` due to the safety constraint,
217+ // and `new_size` == `old_size` was caught before
218+ intrinsics:: assume ( new_size > old_size) ;
219+ let ptr =
220+ NonNull :: new ( realloc ( ptr. as_ptr ( ) , layout, new_size) ) . ok_or ( AllocErr ) ?;
221+ let new_layout = Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ;
222+ init. initialize_offset ( ptr, new_layout, old_size) ;
223+ Ok ( ( ptr, new_size) )
224+ }
196225 }
197- ( _, _) => NonNull :: new ( realloc ( ptr. as_ptr ( ) , layout, new_size) )
198- . ok_or ( AllocErr )
199- . map ( |p| ( p, new_size) ) ,
226+ ReallocPlacement :: InPlace => Err ( AllocErr ) ,
200227 }
201228 }
202229
203230 #[ inline]
204- fn alloc_zeroed ( & mut self , layout : Layout ) -> Result < ( NonNull < u8 > , usize ) , AllocErr > {
205- if layout. size ( ) == 0 {
206- Ok ( ( layout. dangling ( ) , 0 ) )
207- } else {
208- unsafe {
209- NonNull :: new ( alloc_zeroed ( layout) ) . ok_or ( AllocErr ) . map ( |p| ( p, layout. size ( ) ) )
231+ unsafe fn shrink (
232+ & mut self ,
233+ ptr : NonNull < u8 > ,
234+ layout : Layout ,
235+ new_size : usize ,
236+ placement : ReallocPlacement ,
237+ ) -> Result < ( NonNull < u8 > , usize ) , AllocErr > {
238+ let old_size = layout. size ( ) ;
239+ debug_assert ! (
240+ new_size <= old_size,
241+ "`new_size` must be smaller than or equal to `layout.size()`"
242+ ) ;
243+
244+ if old_size == new_size {
245+ return Ok ( ( ptr, new_size) ) ;
246+ }
247+
248+ match placement {
249+ ReallocPlacement :: MayMove => {
250+ let ptr = if new_size == 0 {
251+ self . dealloc ( ptr, layout) ;
252+ layout. dangling ( )
253+ } else {
254+ // `realloc` probably checks for `new_size > old_size` or something similar.
255+ // `new_size` must be smaller than or equal to `old_size` due to the safety constraint,
256+ // and `new_size` == `old_size` was caught before
257+ intrinsics:: assume ( new_size < old_size) ;
258+ NonNull :: new ( realloc ( ptr. as_ptr ( ) , layout, new_size) ) . ok_or ( AllocErr ) ?
259+ } ;
260+ Ok ( ( ptr, new_size) )
210261 }
262+ ReallocPlacement :: InPlace => Err ( AllocErr ) ,
211263 }
212264 }
213265}
@@ -218,14 +270,10 @@ unsafe impl AllocRef for Global {
218270#[ lang = "exchange_malloc" ]
219271#[ inline]
220272unsafe fn exchange_malloc ( size : usize , align : usize ) -> * mut u8 {
221- if size == 0 {
222- align as * mut u8
223- } else {
224- let layout = Layout :: from_size_align_unchecked ( size, align) ;
225- match Global . alloc ( layout) {
226- Ok ( ( ptr, _) ) => ptr. as_ptr ( ) ,
227- Err ( _) => handle_alloc_error ( layout) ,
228- }
273+ let layout = Layout :: from_size_align_unchecked ( size, align) ;
274+ match Global . alloc ( layout, AllocInit :: Uninitialized ) {
275+ Ok ( ( ptr, _) ) => ptr. as_ptr ( ) ,
276+ Err ( _) => handle_alloc_error ( layout) ,
229277 }
230278}
231279
@@ -239,11 +287,8 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
239287pub ( crate ) unsafe fn box_free < T : ?Sized > ( ptr : Unique < T > ) {
240288 let size = size_of_val ( ptr. as_ref ( ) ) ;
241289 let align = min_align_of_val ( ptr. as_ref ( ) ) ;
242- // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
243- if size != 0 {
244- let layout = Layout :: from_size_align_unchecked ( size, align) ;
245- Global . dealloc ( ptr. cast ( ) . into ( ) , layout) ;
246- }
290+ let layout = Layout :: from_size_align_unchecked ( size, align) ;
291+ Global . dealloc ( ptr. cast ( ) . into ( ) , layout)
247292}
248293
249294/// Abort on memory allocation error or failure.
0 commit comments