@@ -161,30 +161,69 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
161
161
unsafe { __rust_alloc_zeroed ( layout. size ( ) , layout. align ( ) ) }
162
162
}
163
163
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
+
164
217
#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
165
218
unsafe impl AllocRef for Global {
166
219
#[ inline]
167
220
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 )
176
222
}
177
223
178
224
#[ inline]
179
225
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 )
188
227
}
189
228
190
229
#[ inline]
@@ -203,26 +242,8 @@ unsafe impl AllocRef for Global {
203
242
layout : Layout ,
204
243
new_size : usize ,
205
244
) -> 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 ) }
226
247
}
227
248
228
249
#[ inline]
@@ -232,27 +253,8 @@ unsafe impl AllocRef for Global {
232
253
layout : Layout ,
233
254
new_size : usize ,
234
255
) -> 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 ) }
256
258
}
257
259
258
260
#[ inline]
@@ -262,30 +264,28 @@ unsafe impl AllocRef for Global {
262
264
layout : Layout ,
263
265
new_size : usize ,
264
266
) -> Result < NonNull < [ u8 ] > , AllocErr > {
265
- let old_size = layout. size ( ) ;
266
267
debug_assert ! (
267
- new_size <= old_size ,
268
+ new_size <= layout . size ( ) ,
268
269
"`new_size` must be smaller than or equal to `layout.size()`"
269
270
) ;
270
271
271
- let ptr = if new_size == 0 {
272
+ match new_size {
272
273
// SAFETY: conditions must be upheld by the caller
273
- unsafe {
274
+ 0 => unsafe {
274
275
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
+ } ,
287
278
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
+ }
289
289
}
290
290
}
291
291
0 commit comments