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 {
170- Ok ( ( layout. dangling ( ) , 0 ) )
171- } else {
172- unsafe { NonNull :: new ( alloc ( layout) ) . ok_or ( AllocErr ) . map ( |p| ( p, layout. size ( ) ) ) }
168+ fn alloc ( & mut self , layout : Layout , init : AllocInit ) -> Result < MemoryBlock , AllocErr > {
169+ unsafe {
170+ let size = layout. size ( ) ;
171+ if size == 0 {
172+ Ok ( MemoryBlock { ptr : layout. dangling ( ) , size : 0 } )
173+ } else {
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 ( MemoryBlock { ptr, size } )
180+ }
173181 }
174182 }
175183
@@ -181,32 +189,71 @@ 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 ,
189- ) -> 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 ) )
197+ placement : ReallocPlacement ,
198+ init : AllocInit ,
199+ ) -> Result < MemoryBlock , AllocErr > {
200+ let size = layout. size ( ) ;
201+ debug_assert ! (
202+ new_size >= size,
203+ "`new_size` must be greater than or equal to `memory.size()`"
204+ ) ;
205+
206+ if size == new_size {
207+ return Ok ( MemoryBlock { ptr, size } ) ;
208+ }
209+
210+ match placement {
211+ ReallocPlacement :: InPlace => Err ( AllocErr ) ,
212+ ReallocPlacement :: MayMove if layout. size ( ) == 0 => {
213+ let new_layout = Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ;
214+ self . alloc ( new_layout, init)
215+ }
216+ ReallocPlacement :: MayMove => {
217+ // `realloc` probably checks for `new_size > size` or something similar.
218+ intrinsics:: assume ( new_size > size) ;
219+ let ptr = realloc ( ptr. as_ptr ( ) , layout, new_size) ;
220+ let memory =
221+ MemoryBlock { ptr : NonNull :: new ( ptr) . ok_or ( AllocErr ) ?, size : new_size } ;
222+ init. init_offset ( memory, size) ;
223+ Ok ( memory)
196224 }
197- ( _, _) => NonNull :: new ( realloc ( ptr. as_ptr ( ) , layout, new_size) )
198- . ok_or ( AllocErr )
199- . map ( |p| ( p, new_size) ) ,
200225 }
201226 }
202227
203228 #[ 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 ( ) ) )
229+ unsafe fn shrink (
230+ & mut self ,
231+ ptr : NonNull < u8 > ,
232+ layout : Layout ,
233+ new_size : usize ,
234+ placement : ReallocPlacement ,
235+ ) -> Result < MemoryBlock , AllocErr > {
236+ let size = layout. size ( ) ;
237+ debug_assert ! (
238+ new_size <= size,
239+ "`new_size` must be smaller than or equal to `memory.size()`"
240+ ) ;
241+
242+ if size == new_size {
243+ return Ok ( MemoryBlock { ptr, size } ) ;
244+ }
245+
246+ match placement {
247+ ReallocPlacement :: InPlace => Err ( AllocErr ) ,
248+ ReallocPlacement :: MayMove if new_size == 0 => {
249+ self . dealloc ( ptr, layout) ;
250+ Ok ( MemoryBlock { ptr : layout. dangling ( ) , size : 0 } )
251+ }
252+ ReallocPlacement :: MayMove => {
253+ // `realloc` probably checks for `new_size < size` or something similar.
254+ intrinsics:: assume ( new_size < size) ;
255+ let ptr = realloc ( ptr. as_ptr ( ) , layout, new_size) ;
256+ Ok ( MemoryBlock { ptr : NonNull :: new ( ptr) . ok_or ( AllocErr ) ?, size : new_size } )
210257 }
211258 }
212259 }
@@ -218,14 +265,10 @@ unsafe impl AllocRef for Global {
218265#[ lang = "exchange_malloc" ]
219266#[ inline]
220267unsafe 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- }
268+ let layout = Layout :: from_size_align_unchecked ( size, align) ;
269+ match Global . alloc ( layout, AllocInit :: Uninitialized ) {
270+ Ok ( memory) => memory. ptr . as_ptr ( ) ,
271+ Err ( _) => handle_alloc_error ( layout) ,
229272 }
230273}
231274
@@ -239,11 +282,8 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
239282pub ( crate ) unsafe fn box_free < T : ?Sized > ( ptr : Unique < T > ) {
240283 let size = size_of_val ( ptr. as_ref ( ) ) ;
241284 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- }
285+ let layout = Layout :: from_size_align_unchecked ( size, align) ;
286+ Global . dealloc ( ptr. cast ( ) . into ( ) , layout)
247287}
248288
249289/// Abort on memory allocation error or failure.
0 commit comments