Skip to content

Commit 515c9fa

Browse files
committed
Auto merge of rust-lang#75621 - TimDiekmann:no-fast-realloc, r=Amanieu
Remove fast path in reallocation for same layout sizes r? @Amanieu Before merging a perf-run should be done. Closes rust-lang/wg-allocators#70
2 parents b97e9b5 + c48f784 commit 515c9fa

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, then `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, then `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
@@ -181,16 +181,14 @@ unsafe impl AllocRef for System {
181181
);
182182

183183
// SAFETY: `new_size` must be non-zero, which is checked in the match expression.
184+
// If `new_size` is zero, then `old_size` has to be zero as well.
184185
// Other conditions must be upheld by the caller
185186
unsafe {
186187
match layout.size() {
187-
old_size if old_size == new_size => {
188-
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
189-
}
190188
0 => self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())),
191189
old_size => {
192-
// `realloc` probably checks for `new_size > size` or something similar.
193-
intrinsics::assume(new_size > old_size);
190+
// `realloc` probably checks for `new_size >= size` or something similar.
191+
intrinsics::assume(new_size >= old_size);
194192
let raw_ptr = GlobalAlloc::realloc(&System, ptr.as_ptr(), layout, new_size);
195193
let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?;
196194
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
@@ -212,16 +210,14 @@ unsafe impl AllocRef for System {
212210
);
213211

214212
// SAFETY: `new_size` must be non-zero, which is checked in the match expression.
213+
// If `new_size` is zero, then `old_size` has to be zero as well.
215214
// Other conditions must be upheld by the caller
216215
unsafe {
217216
match layout.size() {
218-
old_size if old_size == new_size => {
219-
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
220-
}
221217
0 => self.alloc_zeroed(Layout::from_size_align_unchecked(new_size, layout.align())),
222218
old_size => {
223-
// `realloc` probably checks for `new_size > size` or something similar.
224-
intrinsics::assume(new_size > old_size);
219+
// `realloc` probably checks for `new_size >= size` or something similar.
220+
intrinsics::assume(new_size >= old_size);
225221
let raw_ptr = GlobalAlloc::realloc(&System, ptr.as_ptr(), layout, new_size);
226222
raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
227223
let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?;
@@ -244,11 +240,8 @@ unsafe impl AllocRef for System {
244240
"`new_size` must be smaller than or equal to `layout.size()`"
245241
);
246242

247-
let ptr = if new_size == old_size {
248-
ptr
249-
} else if new_size == 0 {
250-
// SAFETY: `layout` is non-zero in size as `old_size` != `new_size`
251-
// Other conditions must be upheld by the caller
243+
let ptr = if new_size == 0 {
244+
// SAFETY: conditions must be upheld by the caller
252245
unsafe {
253246
self.dealloc(ptr, layout);
254247
}
@@ -257,8 +250,8 @@ unsafe impl AllocRef for System {
257250
// SAFETY: new_size is not zero,
258251
// Other conditions must be upheld by the caller
259252
let raw_ptr = unsafe {
260-
// `realloc` probably checks for `new_size < old_size` or something similar.
261-
intrinsics::assume(new_size < old_size);
253+
// `realloc` probably checks for `new_size <= old_size` or something similar.
254+
intrinsics::assume(new_size <= old_size);
262255
GlobalAlloc::realloc(&System, ptr.as_ptr(), layout, new_size)
263256
};
264257
NonNull::new(raw_ptr).ok_or(AllocErr)?

0 commit comments

Comments
 (0)