Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit c619b36

Browse files
committed
Remove fast path in reallocation for same layout sizes
1 parent 67e7b9b commit c619b36

File tree

3 files changed

+20
-52
lines changed

3 files changed

+20
-52
lines changed

library/alloc/src/alloc.rs

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -209,16 +209,14 @@ unsafe impl AllocRef for Global {
209209
);
210210

211211
// SAFETY: `new_size` must be non-zero, which is checked in the match expression.
212+
// If `new_size` is zero, than `old_size` has to be zero as well.
212213
// Other conditions must be upheld by the caller
213214
unsafe {
214215
match layout.size() {
215-
old_size if old_size == new_size => {
216-
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
217-
}
218216
0 => self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())),
219217
old_size => {
220-
// `realloc` probably checks for `new_size > size` or something similar.
221-
intrinsics::assume(new_size > old_size);
218+
// `realloc` probably checks for `new_size >= size` or something similar.
219+
intrinsics::assume(new_size >= old_size);
222220
let raw_ptr = realloc(ptr.as_ptr(), layout, new_size);
223221
let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?;
224222
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
@@ -240,16 +238,14 @@ unsafe impl AllocRef for Global {
240238
);
241239

242240
// SAFETY: `new_size` must be non-zero, which is checked in the match expression.
241+
// If `new_size` is zero, than `old_size` has to be zero as well.
243242
// Other conditions must be upheld by the caller
244243
unsafe {
245244
match layout.size() {
246-
old_size if old_size == new_size => {
247-
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
248-
}
249245
0 => self.alloc_zeroed(Layout::from_size_align_unchecked(new_size, layout.align())),
250246
old_size => {
251-
// `realloc` probably checks for `new_size > size` or something similar.
252-
intrinsics::assume(new_size > old_size);
247+
// `realloc` probably checks for `new_size >= size` or something similar.
248+
intrinsics::assume(new_size >= old_size);
253249
let raw_ptr = realloc(ptr.as_ptr(), layout, new_size);
254250
raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
255251
let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?;
@@ -272,11 +268,8 @@ unsafe impl AllocRef for Global {
272268
"`new_size` must be smaller than or equal to `layout.size()`"
273269
);
274270

275-
let ptr = if new_size == old_size {
276-
ptr
277-
} else if new_size == 0 {
278-
// SAFETY: `layout` is non-zero in size as `old_size` != `new_size`
279-
// Other conditions must be upheld by the caller
271+
let ptr = if new_size == 0 {
272+
// SAFETY: conditions must be upheld by the caller
280273
unsafe {
281274
self.dealloc(ptr, layout);
282275
}
@@ -285,8 +278,8 @@ unsafe impl AllocRef for Global {
285278
// SAFETY: new_size is not zero,
286279
// Other conditions must be upheld by the caller
287280
let raw_ptr = unsafe {
288-
// `realloc` probably checks for `new_size < old_size` or something similar.
289-
intrinsics::assume(new_size < old_size);
281+
// `realloc` probably checks for `new_size <= old_size` or something similar.
282+
intrinsics::assume(new_size <= old_size);
290283
realloc(ptr.as_ptr(), layout, new_size)
291284
};
292285
NonNull::new(raw_ptr).ok_or(AllocErr)?

library/core/src/alloc/mod.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,6 @@ pub unsafe trait AllocRef {
163163
/// * `new_size` must be greater than or equal to `layout.size()`, and
164164
/// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, must not overflow
165165
/// (i.e., the rounded value must be less than or equal to `usize::MAX`).
166-
// Note: We can't require that `new_size` is strictly greater than `layout.size()` because of ZSTs.
167-
// alternative: `new_size` must be strictly greater than `layout.size()` or both are zero
168166
///
169167
/// [*currently allocated*]: #currently-allocated-memory
170168
/// [*fit*]: #memory-fitting
@@ -194,10 +192,6 @@ pub unsafe trait AllocRef {
194192
"`new_size` must be greater than or equal to `layout.size()`"
195193
);
196194

197-
if size == new_size {
198-
return Ok(NonNull::slice_from_raw_parts(ptr, size));
199-
}
200-
201195
let new_layout =
202196
// SAFETY: the caller must ensure that the `new_size` does not overflow.
203197
// `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
@@ -238,8 +232,6 @@ pub unsafe trait AllocRef {
238232
/// * `new_size` must be greater than or equal to `layout.size()`, and
239233
/// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, must not overflow
240234
/// (i.e., the rounded value must be less than or equal to `usize::MAX`).
241-
// Note: We can't require that `new_size` is strictly greater than `layout.size()` because of ZSTs.
242-
// alternative: `new_size` must be strictly greater than `layout.size()` or both are zero
243235
///
244236
/// [*currently allocated*]: #currently-allocated-memory
245237
/// [*fit*]: #memory-fitting
@@ -269,10 +261,6 @@ pub unsafe trait AllocRef {
269261
"`new_size` must be greater than or equal to `layout.size()`"
270262
);
271263

272-
if size == new_size {
273-
return Ok(NonNull::slice_from_raw_parts(ptr, size));
274-
}
275-
276264
let new_layout =
277265
// SAFETY: the caller must ensure that the `new_size` does not overflow.
278266
// `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
@@ -315,8 +303,6 @@ pub unsafe trait AllocRef {
315303
/// * `ptr` must denote a block of memory [*currently allocated*] via this allocator,
316304
/// * `layout` must [*fit*] that block of memory (The `new_size` argument need not fit it.), and
317305
/// * `new_size` must be smaller than or equal to `layout.size()`.
318-
// Note: We can't require that `new_size` is strictly smaller than `layout.size()` because of ZSTs.
319-
// alternative: `new_size` must be smaller than `layout.size()` or both are zero
320306
///
321307
/// [*currently allocated*]: #currently-allocated-memory
322308
/// [*fit*]: #memory-fitting
@@ -346,10 +332,6 @@ pub unsafe trait AllocRef {
346332
"`new_size` must be smaller than or equal to `layout.size()`"
347333
);
348334

349-
if size == new_size {
350-
return Ok(NonNull::slice_from_raw_parts(ptr, size));
351-
}
352-
353335
let new_layout =
354336
// SAFETY: the caller must ensure that the `new_size` does not overflow.
355337
// `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.

library/std/src/alloc.rs

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -185,16 +185,14 @@ unsafe impl AllocRef for System {
185185
);
186186

187187
// SAFETY: `new_size` must be non-zero, which is checked in the match expression.
188+
// If `new_size` is zero, than `old_size` has to be zero as well.
188189
// Other conditions must be upheld by the caller
189190
unsafe {
190191
match layout.size() {
191-
old_size if old_size == new_size => {
192-
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
193-
}
194192
0 => self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())),
195193
old_size => {
196-
// `realloc` probably checks for `new_size > size` or something similar.
197-
intrinsics::assume(new_size > old_size);
194+
// `realloc` probably checks for `new_size >= size` or something similar.
195+
intrinsics::assume(new_size >= old_size);
198196
let raw_ptr = GlobalAlloc::realloc(&System, ptr.as_ptr(), layout, new_size);
199197
let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?;
200198
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
@@ -216,16 +214,14 @@ unsafe impl AllocRef for System {
216214
);
217215

218216
// SAFETY: `new_size` must be non-zero, which is checked in the match expression.
217+
// If `new_size` is zero, than `old_size` has to be zero as well.
219218
// Other conditions must be upheld by the caller
220219
unsafe {
221220
match layout.size() {
222-
old_size if old_size == new_size => {
223-
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
224-
}
225221
0 => self.alloc_zeroed(Layout::from_size_align_unchecked(new_size, layout.align())),
226222
old_size => {
227-
// `realloc` probably checks for `new_size > size` or something similar.
228-
intrinsics::assume(new_size > old_size);
223+
// `realloc` probably checks for `new_size >= size` or something similar.
224+
intrinsics::assume(new_size >= old_size);
229225
let raw_ptr = GlobalAlloc::realloc(&System, ptr.as_ptr(), layout, new_size);
230226
raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
231227
let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?;
@@ -248,11 +244,8 @@ unsafe impl AllocRef for System {
248244
"`new_size` must be smaller than or equal to `layout.size()`"
249245
);
250246

251-
let ptr = if new_size == old_size {
252-
ptr
253-
} else if new_size == 0 {
254-
// SAFETY: `layout` is non-zero in size as `old_size` != `new_size`
255-
// Other conditions must be upheld by the caller
247+
let ptr = if new_size == 0 {
248+
// SAFETY: conditions must be upheld by the caller
256249
unsafe {
257250
self.dealloc(ptr, layout);
258251
}
@@ -261,8 +254,8 @@ unsafe impl AllocRef for System {
261254
// SAFETY: new_size is not zero,
262255
// Other conditions must be upheld by the caller
263256
let raw_ptr = unsafe {
264-
// `realloc` probably checks for `new_size < old_size` or something similar.
265-
intrinsics::assume(new_size < old_size);
257+
// `realloc` probably checks for `new_size <= old_size` or something similar.
258+
intrinsics::assume(new_size <= old_size);
266259
GlobalAlloc::realloc(&System, ptr.as_ptr(), layout, new_size)
267260
};
268261
NonNull::new(raw_ptr).ok_or(AllocErr)?

0 commit comments

Comments
 (0)