@@ -164,25 +164,34 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
164164#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
165165unsafe impl AllocRef for Global {
166166 #[ inline]
167- fn alloc ( & mut self , layout : Layout , init : AllocInit ) -> Result < MemoryBlock , AllocErr > {
168- unsafe {
169- let size = layout. size ( ) ;
170- if size == 0 {
171- Ok ( MemoryBlock { ptr : layout. dangling ( ) , size : 0 } )
172- } else {
173- let raw_ptr = match init {
174- AllocInit :: Uninitialized => alloc ( layout) ,
175- AllocInit :: Zeroed => alloc_zeroed ( layout) ,
176- } ;
177- let ptr = NonNull :: new ( raw_ptr) . ok_or ( AllocErr ) ?;
178- Ok ( MemoryBlock { ptr, size } )
179- }
180- }
167+ fn alloc ( & mut self , layout : Layout ) -> Result < MemoryBlock , AllocErr > {
168+ let size = layout. size ( ) ;
169+ let ptr = if size == 0 {
170+ layout. dangling ( )
171+ } else {
172+ // SAFETY: `layout` is non-zero in size,
173+ unsafe { NonNull :: new ( alloc ( layout) ) . ok_or ( AllocErr ) ? }
174+ } ;
175+ Ok ( MemoryBlock { ptr, size } )
176+ }
177+
178+ #[ inline]
179+ fn alloc_zeroed ( & mut self , layout : Layout ) -> Result < MemoryBlock , AllocErr > {
180+ let size = layout. size ( ) ;
181+ let ptr = if size == 0 {
182+ layout. dangling ( )
183+ } else {
184+ // SAFETY: `layout` is non-zero in size,
185+ unsafe { NonNull :: new ( alloc_zeroed ( layout) ) . ok_or ( AllocErr ) ? }
186+ } ;
187+ Ok ( MemoryBlock { ptr, size } )
181188 }
182189
183190 #[ inline]
184191 unsafe fn dealloc ( & mut self , ptr : NonNull < u8 > , layout : Layout ) {
185192 if layout. size ( ) != 0 {
193+ // SAFETY: `layout` is non-zero in size,
194+ // other conditions must be upheld by the caller
186195 unsafe { dealloc ( ptr. as_ptr ( ) , layout) }
187196 }
188197 }
@@ -193,38 +202,55 @@ unsafe impl AllocRef for Global {
193202 ptr : NonNull < u8 > ,
194203 layout : Layout ,
195204 new_size : usize ,
196- placement : ReallocPlacement ,
197- init : AllocInit ,
198205 ) -> Result < MemoryBlock , AllocErr > {
199- let size = layout. size ( ) ;
200206 debug_assert ! (
201- new_size >= size,
202- "`new_size` must be greater than or equal to `memory .size()`"
207+ new_size >= layout . size( ) ,
208+ "`new_size` must be greater than or equal to `layout .size()`"
203209 ) ;
204210
205- if size == new_size {
206- return Ok ( MemoryBlock { ptr, size } ) ;
211+ // SAFETY: `new_size` must be non-zero, which is checked in the match expression.
212+ // Other conditions must be upheld by the caller
213+ unsafe {
214+ match layout. size ( ) {
215+ old_size if old_size == new_size => Ok ( MemoryBlock { ptr, size : new_size } ) ,
216+ 0 => self . alloc ( Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ) ,
217+ old_size => {
218+ // `realloc` probably checks for `new_size > size` or something similar.
219+ intrinsics:: assume ( new_size > old_size) ;
220+ let raw_ptr = realloc ( ptr. as_ptr ( ) , layout, new_size) ;
221+ let ptr = NonNull :: new ( raw_ptr) . ok_or ( AllocErr ) ?;
222+ Ok ( MemoryBlock { ptr, size : new_size } )
223+ }
224+ }
207225 }
226+ }
208227
209- match placement {
210- ReallocPlacement :: InPlace => Err ( AllocErr ) ,
211- ReallocPlacement :: MayMove if layout. size ( ) == 0 => {
212- let new_layout =
213- unsafe { 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- let ptr = unsafe {
219- intrinsics:: assume ( new_size > size) ;
220- realloc ( ptr. as_ptr ( ) , layout, new_size)
221- } ;
222- let memory =
223- MemoryBlock { ptr : NonNull :: new ( ptr) . ok_or ( AllocErr ) ?, size : new_size } ;
224- unsafe {
225- init. init_offset ( memory, size) ;
228+ #[ inline]
229+ unsafe fn grow_zeroed (
230+ & mut self ,
231+ ptr : NonNull < u8 > ,
232+ layout : Layout ,
233+ new_size : usize ,
234+ ) -> Result < MemoryBlock , AllocErr > {
235+ debug_assert ! (
236+ new_size >= layout. size( ) ,
237+ "`new_size` must be greater than or equal to `layout.size()`"
238+ ) ;
239+
240+ // SAFETY: `new_size` must be non-zero, which is checked in the match expression.
241+ // Other conditions must be upheld by the caller
242+ unsafe {
243+ match layout. size ( ) {
244+ old_size if old_size == new_size => Ok ( MemoryBlock { ptr, size : new_size } ) ,
245+ 0 => self . alloc_zeroed ( Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ) ,
246+ old_size => {
247+ // `realloc` probably checks for `new_size > size` or something similar.
248+ intrinsics:: assume ( new_size > old_size) ;
249+ let raw_ptr = realloc ( ptr. as_ptr ( ) , layout, new_size) ;
250+ raw_ptr. add ( old_size) . write_bytes ( 0 , new_size - old_size) ;
251+ let ptr = NonNull :: new ( raw_ptr) . ok_or ( AllocErr ) ?;
252+ Ok ( MemoryBlock { ptr, size : new_size } )
226253 }
227- Ok ( memory)
228254 }
229255 }
230256 }
@@ -235,35 +261,34 @@ unsafe impl AllocRef for Global {
235261 ptr : NonNull < u8 > ,
236262 layout : Layout ,
237263 new_size : usize ,
238- placement : ReallocPlacement ,
239264 ) -> Result < MemoryBlock , AllocErr > {
240- let size = layout. size ( ) ;
265+ let old_size = layout. size ( ) ;
241266 debug_assert ! (
242- new_size <= size ,
243- "`new_size` must be smaller than or equal to `memory .size()`"
267+ new_size <= old_size ,
268+ "`new_size` must be smaller than or equal to `layout .size()`"
244269 ) ;
245270
246- if size == new_size {
247- return Ok ( MemoryBlock { ptr, size } ) ;
248- }
249-
250- match placement {
251- ReallocPlacement :: InPlace => Err ( AllocErr ) ,
252- ReallocPlacement :: MayMove if new_size == 0 => {
253- unsafe {
254- self . dealloc ( ptr, layout) ;
255- }
256- Ok ( MemoryBlock { ptr : layout. dangling ( ) , size : 0 } )
271+ let ptr = if new_size == old_size {
272+ ptr
273+ } else if new_size == 0 {
274+ // SAFETY: `layout` is non-zero in size as `old_size` != `new_size`
275+ // Other conditions must be upheld by the caller
276+ unsafe {
277+ self . dealloc ( ptr, layout) ;
257278 }
258- ReallocPlacement :: MayMove => {
259- // `realloc` probably checks for `new_size < size` or something similar.
260- let ptr = unsafe {
261- intrinsics:: assume ( new_size < size) ;
262- realloc ( ptr. as_ptr ( ) , layout, new_size)
263- } ;
264- Ok ( MemoryBlock { ptr : NonNull :: new ( ptr) . ok_or ( AllocErr ) ?, size : new_size } )
265- }
266- }
279+ layout. dangling ( )
280+ } else {
281+ // SAFETY: new_size is not zero,
282+ // Other conditions must be upheld by the caller
283+ let raw_ptr = unsafe {
284+ // `realloc` probably checks for `new_size < old_size` or something similar.
285+ intrinsics:: assume ( new_size < old_size) ;
286+ realloc ( ptr. as_ptr ( ) , layout, new_size)
287+ } ;
288+ NonNull :: new ( raw_ptr) . ok_or ( AllocErr ) ?
289+ } ;
290+
291+ Ok ( MemoryBlock { ptr, size : new_size } )
267292 }
268293}
269294
@@ -274,7 +299,7 @@ unsafe impl AllocRef for Global {
274299#[ inline]
275300unsafe fn exchange_malloc ( size : usize , align : usize ) -> * mut u8 {
276301 let layout = unsafe { Layout :: from_size_align_unchecked ( size, align) } ;
277- match Global . alloc ( layout, AllocInit :: Uninitialized ) {
302+ match Global . alloc ( layout) {
278303 Ok ( memory) => memory. ptr . as_ptr ( ) ,
279304 Err ( _) => handle_alloc_error ( layout) ,
280305 }
0 commit comments