Skip to content

Commit 08c2168

Browse files
committed
Make shrink_in_place implementation accurate
1 parent 7d5b0eb commit 08c2168

File tree

1 file changed

+25
-17
lines changed

1 file changed

+25
-17
lines changed

src/lib.rs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -200,28 +200,36 @@ unsafe impl Alloc for Jemalloc {
200200
layout: Layout,
201201
new_size: usize,
202202
) -> Result<(), CannotReallocInPlace> {
203-
if new_size == layout.size() { return Ok(()); }
203+
if new_size == layout.size() {
204+
return Ok(());
205+
}
204206
let flags = layout_to_flags(layout.align(), new_size);
205207
let usable_size = ffi::xallocx(ptr.cast().as_ptr(), new_size, 0, flags);
208+
206209
if usable_size < layout.size() {
207-
// `shrink_in_place` succeeds if the usable size of the shrunk
208-
// allocation is smaller than that of the current allocation (and
209-
// therefore, than the originally requested size). This means that:
210-
//
211-
// * the size-class of the allocation was changed to the size-class
212-
// of `new_size`, therefore the allocation can be deallocated with
213-
// `new_size`
214-
//
215-
// * if `new_size` lies in the same size class as `layout.size()`,
216-
// and `new_size != layout.size()` then `shrink_in_place` will error
217-
// even though technically the allocation can be deallocated
218-
// properly with `new_size` - the problem is that `xallocx` will
219-
// return `layout.size()` if shrinking failed, and we cannot detect
220-
// whether that means that shrinking failed or that `new_size` is
221-
// part of the same size-class efficiently.
222-
//
210+
// If `usable_size` is smaller than the original size, the
211+
// size-class of the allocation was shrunk to the size-class of
212+
// `new_size`, and it is safe to deallocate the allocation with
213+
// `new_size`:
214+
Ok(())
215+
} else if usable_size == ffi::nallocx(new_size, flags) {
216+
// If the allocation was not shrunk and the size class of `new_size`
217+
// is the same as the size-class of `layout.size()`, then the
218+
// allocation can be properly deallocated using `new_size` (and also
219+
// using `layout.size()` because the allocation did not change)
220+
221+
// note: when the allocation is not shrunk, `xallocx` returns the
222+
// usable size of the original allocation, which in this case matches
223+
// that of the requested allocation:
224+
debug_assert_eq!(
225+
ffi::nallocx(new_size, flags),
226+
ffi::nallocx(layout.size(), flags)
227+
);
223228
Ok(())
224229
} else {
230+
// If the allocation was not shrunk, but the size-class of
231+
// `new_size` is not the same as that of the original allocation,
232+
// then shrinking the allocation failed:
225233
Err(CannotReallocInPlace)
226234
}
227235
}

0 commit comments

Comments
 (0)