@@ -164,25 +164,34 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
164
164
#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
165
165
unsafe impl AllocRef for Global {
166
166
#[ 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 } )
181
188
}
182
189
183
190
#[ inline]
184
191
unsafe fn dealloc ( & mut self , ptr : NonNull < u8 > , layout : Layout ) {
185
192
if layout. size ( ) != 0 {
193
+ // SAFETY: `layout` is non-zero in size,
194
+ // other conditions must be upheld by the caller
186
195
unsafe { dealloc ( ptr. as_ptr ( ) , layout) }
187
196
}
188
197
}
@@ -193,38 +202,55 @@ unsafe impl AllocRef for Global {
193
202
ptr : NonNull < u8 > ,
194
203
layout : Layout ,
195
204
new_size : usize ,
196
- placement : ReallocPlacement ,
197
- init : AllocInit ,
198
205
) -> Result < MemoryBlock , AllocErr > {
199
- let size = layout. size ( ) ;
200
206
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()`"
203
209
) ;
204
210
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
+ }
207
225
}
226
+ }
208
227
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 } )
226
253
}
227
- Ok ( memory)
228
254
}
229
255
}
230
256
}
@@ -235,35 +261,34 @@ unsafe impl AllocRef for Global {
235
261
ptr : NonNull < u8 > ,
236
262
layout : Layout ,
237
263
new_size : usize ,
238
- placement : ReallocPlacement ,
239
264
) -> Result < MemoryBlock , AllocErr > {
240
- let size = layout. size ( ) ;
265
+ let old_size = layout. size ( ) ;
241
266
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()`"
244
269
) ;
245
270
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) ;
257
278
}
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 } )
267
292
}
268
293
}
269
294
@@ -274,7 +299,7 @@ unsafe impl AllocRef for Global {
274
299
#[ inline]
275
300
unsafe fn exchange_malloc ( size : usize , align : usize ) -> * mut u8 {
276
301
let layout = unsafe { Layout :: from_size_align_unchecked ( size, align) } ;
277
- match Global . alloc ( layout, AllocInit :: Uninitialized ) {
302
+ match Global . alloc ( layout) {
278
303
Ok ( memory) => memory. ptr . as_ptr ( ) ,
279
304
Err ( _) => handle_alloc_error ( layout) ,
280
305
}
0 commit comments