@@ -161,30 +161,68 @@ 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
+ #[inline]
179
+ fn grow_impl(
180
+ &mut self,
181
+ ptr: NonNull<u8>,
182
+ layout: Layout,
183
+ new_size: usize,
184
+ zeroed: bool,
185
+ ) -> Result<NonNull<[u8]>, AllocErr> {
186
+ debug_assert!(
187
+ new_size >= layout.size(),
188
+ "`new_size` must be greater than or equal to `layout.size()`"
189
+ );
190
+
191
+ match layout.size() {
192
+ // SAFETY: the caller must ensure that the `new_size` does not overflow.
193
+ // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
194
+ 0 => unsafe {
195
+ let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
196
+ self.alloc_impl(new_layout, zeroed)
197
+ },
198
+
199
+ // SAFETY: `new_size` is non-zero as `old_size` is greater than or equal to `new_size`
200
+ // as required by safety conditions. Other conditions must be upheld by the caller
201
+ old_size => unsafe {
202
+ // `realloc` probably checks for `new_size >= size` or something similar.
203
+ intrinsics::assume(new_size >= layout.size());
204
+
205
+ let raw_ptr = realloc(ptr.as_ptr(), layout, new_size);
206
+ let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?;
207
+ if zeroed {
208
+ raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
209
+ }
210
+ Ok(NonNull::slice_from_raw_parts(ptr, new_size))
211
+ },
212
+ }
213
+ }
214
+ }
215
+
164
216
#[unstable(feature = "allocator_api", issue = "32838")]
165
217
unsafe impl AllocRef for Global {
166
218
#[inline]
167
219
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))
220
+ self.alloc_impl(layout, false)
176
221
}
177
222
178
223
#[inline]
179
224
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))
225
+ self.alloc_impl(layout, true)
188
226
}
189
227
190
228
#[inline]
@@ -203,26 +241,7 @@ unsafe impl AllocRef for Global {
203
241
layout: Layout,
204
242
new_size: usize,
205
243
) -> 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
- }
244
+ self.grow_impl(ptr, layout, new_size, false)
226
245
}
227
246
228
247
#[inline]
@@ -232,27 +251,7 @@ unsafe impl AllocRef for Global {
232
251
layout: Layout,
233
252
new_size: usize,
234
253
) -> 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
- }
254
+ self.grow_impl(ptr, layout, new_size, true)
256
255
}
257
256
258
257
#[inline]
@@ -262,30 +261,28 @@ unsafe impl AllocRef for Global {
262
261
layout: Layout,
263
262
new_size: usize,
264
263
) -> Result<NonNull<[u8]>, AllocErr> {
265
- let old_size = layout.size();
266
264
debug_assert!(
267
- new_size <= old_size ,
265
+ new_size <= layout.size() ,
268
266
"`new_size` must be smaller than or equal to `layout.size()`"
269
267
);
270
268
271
- let ptr = if new_size == 0 {
269
+ match new_size {
272
270
// SAFETY: conditions must be upheld by the caller
273
- unsafe {
271
+ 0 => unsafe {
274
272
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
- };
273
+ Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0))
274
+ },
287
275
288
- Ok(NonNull::slice_from_raw_parts(ptr, new_size))
276
+ // SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller
277
+ new_size => unsafe {
278
+ // `realloc` probably checks for `new_size <= size` or something similar.
279
+ intrinsics::assume(new_size <= layout.size());
280
+
281
+ let raw_ptr = realloc(ptr.as_ptr(), layout, new_size);
282
+ let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?;
283
+ Ok(NonNull::slice_from_raw_parts(ptr, new_size))
284
+ },
285
+ }
289
286
}
290
287
}
291
288
0 commit comments