@@ -161,30 +161,68 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
161161 unsafe { __rust_alloc_zeroed ( layout. size ( ) , layout. align ( ) ) }
162162}
163163
164+ impl Global {
165+ #[ inline]
166+ fn alloc_impl ( & mut self , layout : Layout , zeroed : bool ) -> Result < NonNull < [ u8 ] > , AllocErr > {
167+ match layout. size ( ) {
168+ 0 => Ok ( NonNull :: slice_from_raw_parts ( layout. dangling ( ) , 0 ) ) ,
169+ // SAFETY: `layout` is non-zero in size,
170+ size => unsafe {
171+ let raw_ptr = if zeroed { alloc_zeroed ( layout) } else { alloc ( layout) } ;
172+ let ptr = NonNull :: new ( raw_ptr) . ok_or ( AllocErr ) ?;
173+ Ok ( NonNull :: slice_from_raw_parts ( ptr, size) )
174+ } ,
175+ }
176+ }
177+
178+ #[ inline]
179+ fn grow_impl (
180+ & mut self ,
181+ ptr : NonNull < u8 > ,
182+ layout : Layout ,
183+ new_size : usize ,
184+ zeroed : bool ,
185+ ) -> Result < NonNull < [ u8 ] > , AllocErr > {
186+ debug_assert ! (
187+ new_size >= layout. size( ) ,
188+ "`new_size` must be greater than or equal to `layout.size()`"
189+ ) ;
190+
191+ match layout. size ( ) {
192+ // SAFETY: the caller must ensure that the `new_size` does not overflow.
193+ // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
194+ 0 => unsafe {
195+ let new_layout = Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ;
196+ self . alloc_impl ( new_layout, zeroed)
197+ } ,
198+
199+ // SAFETY: `new_size` is non-zero as `old_size` is greater than or equal to `new_size`
200+ // as required by safety conditions. Other conditions must be upheld by the caller
201+ old_size => unsafe {
202+ // `realloc` probably checks for `new_size >= size` or something similar.
203+ intrinsics:: assume ( new_size >= layout. size ( ) ) ;
204+
205+ let raw_ptr = realloc ( ptr. as_ptr ( ) , layout, new_size) ;
206+ let ptr = NonNull :: new ( raw_ptr) . ok_or ( AllocErr ) ?;
207+ if zeroed {
208+ raw_ptr. add ( old_size) . write_bytes ( 0 , new_size - old_size) ;
209+ }
210+ Ok ( NonNull :: slice_from_raw_parts ( ptr, new_size) )
211+ } ,
212+ }
213+ }
214+ }
215+
164216#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
165217unsafe impl AllocRef for Global {
166218 #[ inline]
167219 fn alloc ( & mut self , layout : Layout ) -> Result < NonNull < [ u8 ] > , 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 ( NonNull :: slice_from_raw_parts ( ptr, size) )
220+ self . alloc_impl ( layout, false )
176221 }
177222
178223 #[ inline]
179224 fn alloc_zeroed ( & mut self , layout : Layout ) -> Result < NonNull < [ u8 ] > , 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 ( NonNull :: slice_from_raw_parts ( ptr, size) )
225+ self . alloc_impl ( layout, true )
188226 }
189227
190228 #[ inline]
@@ -203,26 +241,7 @@ unsafe impl AllocRef for Global {
203241 layout : Layout ,
204242 new_size : usize ,
205243 ) -> Result < NonNull < [ u8 ] > , AllocErr > {
206- debug_assert ! (
207- new_size >= layout. size( ) ,
208- "`new_size` must be greater than or equal to `layout.size()`"
209- ) ;
210-
211- // SAFETY: `new_size` must be non-zero, which is checked in the match expression.
212- // If `new_size` is zero, then `old_size` has to be zero as well.
213- // Other conditions must be upheld by the caller
214- unsafe {
215- match layout. 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 ( NonNull :: slice_from_raw_parts ( ptr, new_size) )
223- }
224- }
225- }
244+ self . grow_impl ( ptr, layout, new_size, false )
226245 }
227246
228247 #[ inline]
@@ -232,27 +251,7 @@ unsafe impl AllocRef for Global {
232251 layout : Layout ,
233252 new_size : usize ,
234253 ) -> Result < NonNull < [ u8 ] > , 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- // If `new_size` is zero, then `old_size` has to be zero as well.
242- // Other conditions must be upheld by the caller
243- unsafe {
244- match layout. 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 ( NonNull :: slice_from_raw_parts ( ptr, new_size) )
253- }
254- }
255- }
254+ self . grow_impl ( ptr, layout, new_size, true )
256255 }
257256
258257 #[ inline]
@@ -262,30 +261,28 @@ unsafe impl AllocRef for Global {
262261 layout : Layout ,
263262 new_size : usize ,
264263 ) -> Result < NonNull < [ u8 ] > , AllocErr > {
265- let old_size = layout. size ( ) ;
266264 debug_assert ! (
267- new_size <= old_size ,
265+ new_size <= layout . size ( ) ,
268266 "`new_size` must be smaller than or equal to `layout.size()`"
269267 ) ;
270268
271- let ptr = if new_size == 0 {
269+ match new_size {
272270 // SAFETY: conditions must be upheld by the caller
273- unsafe {
271+ 0 => unsafe {
274272 self . dealloc ( ptr, layout) ;
275- }
276- layout. dangling ( )
277- } else {
278- // SAFETY: new_size is not zero,
279- // Other conditions must be upheld by the caller
280- let raw_ptr = unsafe {
281- // `realloc` probably checks for `new_size <= old_size` or something similar.
282- intrinsics:: assume ( new_size <= old_size) ;
283- realloc ( ptr. as_ptr ( ) , layout, new_size)
284- } ;
285- NonNull :: new ( raw_ptr) . ok_or ( AllocErr ) ?
286- } ;
273+ Ok ( NonNull :: slice_from_raw_parts ( layout. dangling ( ) , 0 ) )
274+ } ,
287275
288- Ok ( NonNull :: slice_from_raw_parts ( ptr, new_size) )
276+ // SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller
277+ new_size => unsafe {
278+ // `realloc` probably checks for `new_size <= size` or something similar.
279+ intrinsics:: assume ( new_size <= layout. size ( ) ) ;
280+
281+ let raw_ptr = realloc ( ptr. as_ptr ( ) , layout, new_size) ;
282+ let ptr = NonNull :: new ( raw_ptr) . ok_or ( AllocErr ) ?;
283+ Ok ( NonNull :: slice_from_raw_parts ( ptr, new_size) )
284+ } ,
285+ }
289286 }
290287}
291288
0 commit comments