@@ -161,30 +161,69 @@ 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+ // Safety: Same as `AllocRef::grow`
179+ #[ inline]
180+ unsafe fn grow_impl (
181+ & mut self ,
182+ ptr : NonNull < u8 > ,
183+ layout : Layout ,
184+ new_size : usize ,
185+ zeroed : bool ,
186+ ) -> Result < NonNull < [ u8 ] > , AllocErr > {
187+ debug_assert ! (
188+ new_size >= layout. size( ) ,
189+ "`new_size` must be greater than or equal to `layout.size()`"
190+ ) ;
191+
192+ match layout. size ( ) {
193+ // SAFETY: the caller must ensure that the `new_size` does not overflow.
194+ // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
195+ 0 => unsafe {
196+ let new_layout = Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ;
197+ self . alloc_impl ( new_layout, zeroed)
198+ } ,
199+
200+ // SAFETY: `new_size` is non-zero as `old_size` is greater than or equal to `new_size`
201+ // as required by safety conditions. Other conditions must be upheld by the caller
202+ old_size => unsafe {
203+ // `realloc` probably checks for `new_size >= size` or something similar.
204+ intrinsics:: assume ( new_size >= layout. size ( ) ) ;
205+
206+ let raw_ptr = realloc ( ptr. as_ptr ( ) , layout, new_size) ;
207+ let ptr = NonNull :: new ( raw_ptr) . ok_or ( AllocErr ) ?;
208+ if zeroed {
209+ raw_ptr. add ( old_size) . write_bytes ( 0 , new_size - old_size) ;
210+ }
211+ Ok ( NonNull :: slice_from_raw_parts ( ptr, new_size) )
212+ } ,
213+ }
214+ }
215+ }
216+
164217#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
165218unsafe impl AllocRef for Global {
166219 #[ inline]
167220 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) )
221+ self . alloc_impl ( layout, false )
176222 }
177223
178224 #[ inline]
179225 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) )
226+ self . alloc_impl ( layout, true )
188227 }
189228
190229 #[ inline]
@@ -203,26 +242,8 @@ unsafe impl AllocRef for Global {
203242 layout : Layout ,
204243 new_size : usize ,
205244 ) -> 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- }
245+ // SAFETY: all conditions must be upheld by the caller
246+ unsafe { self . grow_impl ( ptr, layout, new_size, false ) }
226247 }
227248
228249 #[ inline]
@@ -232,27 +253,8 @@ unsafe impl AllocRef for Global {
232253 layout : Layout ,
233254 new_size : usize ,
234255 ) -> 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- }
256+ // SAFETY: all conditions must be upheld by the caller
257+ unsafe { self . grow_impl ( ptr, layout, new_size, true ) }
256258 }
257259
258260 #[ inline]
@@ -262,30 +264,28 @@ unsafe impl AllocRef for Global {
262264 layout : Layout ,
263265 new_size : usize ,
264266 ) -> Result < NonNull < [ u8 ] > , AllocErr > {
265- let old_size = layout. size ( ) ;
266267 debug_assert ! (
267- new_size <= old_size ,
268+ new_size <= layout . size ( ) ,
268269 "`new_size` must be smaller than or equal to `layout.size()`"
269270 ) ;
270271
271- let ptr = if new_size == 0 {
272+ match new_size {
272273 // SAFETY: conditions must be upheld by the caller
273- unsafe {
274+ 0 => unsafe {
274275 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- } ;
276+ Ok ( NonNull :: slice_from_raw_parts ( layout. dangling ( ) , 0 ) )
277+ } ,
287278
288- Ok ( NonNull :: slice_from_raw_parts ( ptr, new_size) )
279+ // SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller
280+ new_size => unsafe {
281+ // `realloc` probably checks for `new_size <= size` or something similar.
282+ intrinsics:: assume ( new_size <= layout. size ( ) ) ;
283+
284+ let raw_ptr = realloc ( ptr. as_ptr ( ) , layout, new_size) ;
285+ let ptr = NonNull :: new ( raw_ptr) . ok_or ( AllocErr ) ?;
286+ Ok ( NonNull :: slice_from_raw_parts ( ptr, new_size) )
287+ } ,
288+ }
289289 }
290290}
291291
0 commit comments