2
2
3
3
#![ stable( feature = "alloc_module" , since = "1.28.0" ) ]
4
4
5
- use core:: intrinsics:: { min_align_of_val, size_of_val} ;
5
+ use core:: intrinsics:: { self , min_align_of_val, size_of_val} ;
6
6
use core:: ptr:: { NonNull , Unique } ;
7
7
use core:: usize;
8
8
@@ -165,11 +165,19 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
165
165
#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
166
166
unsafe impl AllocRef for Global {
167
167
#[ inline]
168
- fn alloc ( & mut self , layout : Layout ) -> Result < ( NonNull < u8 > , usize ) , AllocErr > {
169
- if layout. size ( ) == 0 {
168
+ fn alloc ( & mut self , layout : Layout , init : AllocInit ) -> Result < ( NonNull < u8 > , usize ) , AllocErr > {
169
+ let new_size = layout. size ( ) ;
170
+ if new_size == 0 {
170
171
Ok ( ( layout. dangling ( ) , 0 ) )
171
172
} else {
172
- unsafe { NonNull :: new ( alloc ( layout) ) . ok_or ( AllocErr ) . map ( |p| ( p, layout. size ( ) ) ) }
173
+ unsafe {
174
+ let raw_ptr = match init {
175
+ AllocInit :: Uninitialized => alloc ( layout) ,
176
+ AllocInit :: Zeroed => alloc_zeroed ( layout) ,
177
+ } ;
178
+ let ptr = NonNull :: new ( raw_ptr) . ok_or ( AllocErr ) ?;
179
+ Ok ( ( ptr, new_size) )
180
+ }
173
181
}
174
182
}
175
183
@@ -181,33 +189,77 @@ unsafe impl AllocRef for Global {
181
189
}
182
190
183
191
#[ inline]
184
- unsafe fn realloc (
192
+ unsafe fn grow (
185
193
& mut self ,
186
194
ptr : NonNull < u8 > ,
187
195
layout : Layout ,
188
196
new_size : usize ,
197
+ placement : ReallocPlacement ,
198
+ init : AllocInit ,
189
199
) -> Result < ( NonNull < u8 > , usize ) , AllocErr > {
190
- match ( layout. size ( ) , new_size) {
191
- ( 0 , 0 ) => Ok ( ( layout. dangling ( ) , 0 ) ) ,
192
- ( 0 , _) => self . alloc ( Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ) ,
193
- ( _, 0 ) => {
194
- self . dealloc ( ptr, layout) ;
195
- Ok ( ( layout. dangling ( ) , 0 ) )
200
+ let old_size = layout. size ( ) ;
201
+ debug_assert ! (
202
+ new_size >= old_size,
203
+ "`new_size` must be greater than or equal to `layout.size()`"
204
+ ) ;
205
+
206
+ if old_size == new_size {
207
+ return Ok ( ( ptr, new_size) ) ;
208
+ }
209
+
210
+ match placement {
211
+ ReallocPlacement :: MayMove => {
212
+ if old_size == 0 {
213
+ self . alloc ( Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) , init)
214
+ } else {
215
+ // `realloc` probably checks for `new_size > old_size` or something similar.
216
+ // `new_size` must be greater than or equal to `old_size` due to the safety constraint,
217
+ // and `new_size` == `old_size` was caught before
218
+ intrinsics:: assume ( new_size > old_size) ;
219
+ let ptr =
220
+ NonNull :: new ( realloc ( ptr. as_ptr ( ) , layout, new_size) ) . ok_or ( AllocErr ) ?;
221
+ let new_layout = Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ;
222
+ init. initialize_offset ( ptr, new_layout, old_size) ;
223
+ Ok ( ( ptr, new_size) )
224
+ }
196
225
}
197
- ( _, _) => NonNull :: new ( realloc ( ptr. as_ptr ( ) , layout, new_size) )
198
- . ok_or ( AllocErr )
199
- . map ( |p| ( p, new_size) ) ,
226
+ ReallocPlacement :: InPlace => Err ( AllocErr ) ,
200
227
}
201
228
}
202
229
203
230
#[ inline]
204
- fn alloc_zeroed ( & mut self , layout : Layout ) -> Result < ( NonNull < u8 > , usize ) , AllocErr > {
205
- if layout. size ( ) == 0 {
206
- Ok ( ( layout. dangling ( ) , 0 ) )
207
- } else {
208
- unsafe {
209
- NonNull :: new ( alloc_zeroed ( layout) ) . ok_or ( AllocErr ) . map ( |p| ( p, layout. size ( ) ) )
231
+ unsafe fn shrink (
232
+ & mut self ,
233
+ ptr : NonNull < u8 > ,
234
+ layout : Layout ,
235
+ new_size : usize ,
236
+ placement : ReallocPlacement ,
237
+ ) -> Result < ( NonNull < u8 > , usize ) , AllocErr > {
238
+ let old_size = layout. size ( ) ;
239
+ debug_assert ! (
240
+ new_size <= old_size,
241
+ "`new_size` must be smaller than or equal to `layout.size()`"
242
+ ) ;
243
+
244
+ if old_size == new_size {
245
+ return Ok ( ( ptr, new_size) ) ;
246
+ }
247
+
248
+ match placement {
249
+ ReallocPlacement :: MayMove => {
250
+ let ptr = if new_size == 0 {
251
+ self . dealloc ( ptr, layout) ;
252
+ layout. dangling ( )
253
+ } else {
254
+ // `realloc` probably checks for `new_size > old_size` or something similar.
255
+ // `new_size` must be smaller than or equal to `old_size` due to the safety constraint,
256
+ // and `new_size` == `old_size` was caught before
257
+ intrinsics:: assume ( new_size < old_size) ;
258
+ NonNull :: new ( realloc ( ptr. as_ptr ( ) , layout, new_size) ) . ok_or ( AllocErr ) ?
259
+ } ;
260
+ Ok ( ( ptr, new_size) )
210
261
}
262
+ ReallocPlacement :: InPlace => Err ( AllocErr ) ,
211
263
}
212
264
}
213
265
}
@@ -218,14 +270,10 @@ unsafe impl AllocRef for Global {
218
270
#[ lang = "exchange_malloc" ]
219
271
#[ inline]
220
272
unsafe fn exchange_malloc ( size : usize , align : usize ) -> * mut u8 {
221
- if size == 0 {
222
- align as * mut u8
223
- } else {
224
- let layout = Layout :: from_size_align_unchecked ( size, align) ;
225
- match Global . alloc ( layout) {
226
- Ok ( ( ptr, _) ) => ptr. as_ptr ( ) ,
227
- Err ( _) => handle_alloc_error ( layout) ,
228
- }
273
+ let layout = Layout :: from_size_align_unchecked ( size, align) ;
274
+ match Global . alloc ( layout, AllocInit :: Uninitialized ) {
275
+ Ok ( ( ptr, _) ) => ptr. as_ptr ( ) ,
276
+ Err ( _) => handle_alloc_error ( layout) ,
229
277
}
230
278
}
231
279
@@ -239,11 +287,8 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
239
287
pub ( crate ) unsafe fn box_free < T : ?Sized > ( ptr : Unique < T > ) {
240
288
let size = size_of_val ( ptr. as_ref ( ) ) ;
241
289
let align = min_align_of_val ( ptr. as_ref ( ) ) ;
242
- // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
243
- if size != 0 {
244
- let layout = Layout :: from_size_align_unchecked ( size, align) ;
245
- Global . dealloc ( ptr. cast ( ) . into ( ) , layout) ;
246
- }
290
+ let layout = Layout :: from_size_align_unchecked ( size, align) ;
291
+ Global . dealloc ( ptr. cast ( ) . into ( ) , layout)
247
292
}
248
293
249
294
/// Abort on memory allocation error or failure.
0 commit comments