Fix shrink_in_place implementation

This commit is contained in:
gnzlbg 2018-11-06 13:18:30 +01:00 committed by gnzlbg
parent d32993869a
commit 7d5b0ebafd
2 changed files with 23 additions and 4 deletions

View File

@ -200,10 +200,30 @@ unsafe impl Alloc for Jemalloc {
layout: Layout,
new_size: usize,
) -> Result<(), CannotReallocInPlace> {
if new_size == layout.size() { return Ok(()); }
let flags = layout_to_flags(layout.align(), new_size);
let shrunk_size = ffi::xallocx(ptr.cast().as_ptr(), new_size, 0, flags);
debug_assert!(shrunk_size >= new_size);
Ok(())
let usable_size = ffi::xallocx(ptr.cast().as_ptr(), new_size, 0, flags);
if usable_size < layout.size() {
// `shrink_in_place` succeeds if the usable size of the shrunk
// allocation is smaller than that of the current allocation (and
// therefore, than the originally requested size). This means that:
//
// * the size-class of the allocation was changed to the size-class
// of `new_size`, therefore the allocation can be deallocated with
// `new_size`
//
// * if `new_size` lies in the same size class as `layout.size()`,
// and `new_size != layout.size()` then `shrink_in_place` will error
// even though technically the allocation can be deallocated
// properly with `new_size` - the problem is that `xallocx` will
// return `layout.size()` if shrinking failed, and we cannot detect
// whether that means that shrinking failed or that `new_size` is
// part of the same size-class efficiently.
//
Ok(())
} else {
Err(CannotReallocInPlace)
}
}
}

View File

@ -27,7 +27,6 @@ fn shrink_in_place() {
let new_l = Layout::from_size_align(new_sz, 1).unwrap();
Jemalloc.dealloc(ptr, new_l);
} else {
assert!(false);
// if shrink in place failed - deallocate with the old layout
Jemalloc.dealloc(ptr, orig_l);
}