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 {
170
- Ok ( ( layout. dangling ( ) , 0 ) )
171
- } else {
172
- unsafe { NonNull :: new ( alloc ( layout) ) . ok_or ( AllocErr ) . map ( |p| ( p, layout. size ( ) ) ) }
168
+ fn alloc ( & mut self , layout : Layout , init : AllocInit ) -> Result < MemoryBlock , AllocErr > {
169
+ unsafe {
170
+ let size = layout. size ( ) ;
171
+ if size == 0 {
172
+ Ok ( MemoryBlock { ptr : layout. dangling ( ) , size : 0 } )
173
+ } else {
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 ( MemoryBlock { ptr, size } )
180
+ }
173
181
}
174
182
}
175
183
@@ -181,32 +189,71 @@ 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 ,
189
- ) -> 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 ) )
197
+ placement : ReallocPlacement ,
198
+ init : AllocInit ,
199
+ ) -> Result < MemoryBlock , AllocErr > {
200
+ let size = layout. size ( ) ;
201
+ debug_assert ! (
202
+ new_size >= size,
203
+ "`new_size` must be greater than or equal to `memory.size()`"
204
+ ) ;
205
+
206
+ if size == new_size {
207
+ return Ok ( MemoryBlock { ptr, size } ) ;
208
+ }
209
+
210
+ match placement {
211
+ ReallocPlacement :: InPlace => Err ( AllocErr ) ,
212
+ ReallocPlacement :: MayMove if layout. size ( ) == 0 => {
213
+ let new_layout = 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
+ intrinsics:: assume ( new_size > size) ;
219
+ let ptr = realloc ( ptr. as_ptr ( ) , layout, new_size) ;
220
+ let memory =
221
+ MemoryBlock { ptr : NonNull :: new ( ptr) . ok_or ( AllocErr ) ?, size : new_size } ;
222
+ init. init_offset ( memory, size) ;
223
+ Ok ( memory)
196
224
}
197
- ( _, _) => NonNull :: new ( realloc ( ptr. as_ptr ( ) , layout, new_size) )
198
- . ok_or ( AllocErr )
199
- . map ( |p| ( p, new_size) ) ,
200
225
}
201
226
}
202
227
203
228
#[ 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 ( ) ) )
229
+ unsafe fn shrink (
230
+ & mut self ,
231
+ ptr : NonNull < u8 > ,
232
+ layout : Layout ,
233
+ new_size : usize ,
234
+ placement : ReallocPlacement ,
235
+ ) -> Result < MemoryBlock , AllocErr > {
236
+ let size = layout. size ( ) ;
237
+ debug_assert ! (
238
+ new_size <= size,
239
+ "`new_size` must be smaller than or equal to `memory.size()`"
240
+ ) ;
241
+
242
+ if size == new_size {
243
+ return Ok ( MemoryBlock { ptr, size } ) ;
244
+ }
245
+
246
+ match placement {
247
+ ReallocPlacement :: InPlace => Err ( AllocErr ) ,
248
+ ReallocPlacement :: MayMove if new_size == 0 => {
249
+ self . dealloc ( ptr, layout) ;
250
+ Ok ( MemoryBlock { ptr : layout. dangling ( ) , size : 0 } )
251
+ }
252
+ ReallocPlacement :: MayMove => {
253
+ // `realloc` probably checks for `new_size < size` or something similar.
254
+ intrinsics:: assume ( new_size < size) ;
255
+ let ptr = realloc ( ptr. as_ptr ( ) , layout, new_size) ;
256
+ Ok ( MemoryBlock { ptr : NonNull :: new ( ptr) . ok_or ( AllocErr ) ?, size : new_size } )
210
257
}
211
258
}
212
259
}
@@ -218,14 +265,10 @@ unsafe impl AllocRef for Global {
218
265
#[ lang = "exchange_malloc" ]
219
266
#[ inline]
220
267
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
- }
268
+ let layout = Layout :: from_size_align_unchecked ( size, align) ;
269
+ match Global . alloc ( layout, AllocInit :: Uninitialized ) {
270
+ Ok ( memory) => memory. ptr . as_ptr ( ) ,
271
+ Err ( _) => handle_alloc_error ( layout) ,
229
272
}
230
273
}
231
274
@@ -239,11 +282,8 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
239
282
pub ( crate ) unsafe fn box_free < T : ?Sized > ( ptr : Unique < T > ) {
240
283
let size = size_of_val ( ptr. as_ref ( ) ) ;
241
284
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
- }
285
+ let layout = Layout :: from_size_align_unchecked ( size, align) ;
286
+ Global . dealloc ( ptr. cast ( ) . into ( ) , layout)
247
287
}
248
288
249
289
/// Abort on memory allocation error or failure.
0 commit comments