realloc with a new size only, not a full new layout.
Changing the alignment with realloc is not supported.
This commit is contained in:
parent
b017742136
commit
c957e99b30
5 changed files with 73 additions and 101 deletions
|
@ -91,24 +91,20 @@ unsafe impl Alloc for Global {
|
||||||
unsafe fn realloc(&mut self,
|
unsafe fn realloc(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout)
|
new_size: usize)
|
||||||
-> Result<*mut u8, AllocErr>
|
-> Result<*mut u8, AllocErr>
|
||||||
{
|
{
|
||||||
if layout.align() == new_layout.align() {
|
|
||||||
#[cfg(not(stage0))]
|
#[cfg(not(stage0))]
|
||||||
let ptr = __rust_realloc(ptr, layout.size(), layout.align(), new_layout.size());
|
let ptr = __rust_realloc(ptr, layout.size(), layout.align(), new_size);
|
||||||
#[cfg(stage0)]
|
#[cfg(stage0)]
|
||||||
let ptr = __rust_realloc(ptr, layout.size(), layout.align(),
|
let ptr = __rust_realloc(ptr, layout.size(), layout.align(),
|
||||||
new_layout.size(), new_layout.align(), &mut 0);
|
new_size, layout.align(), &mut 0);
|
||||||
|
|
||||||
if !ptr.is_null() {
|
if !ptr.is_null() {
|
||||||
Ok(ptr)
|
Ok(ptr)
|
||||||
} else {
|
} else {
|
||||||
Err(AllocErr)
|
Err(AllocErr)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Err(AllocErr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -64,7 +64,7 @@ unsafe impl<T> Alloc for T where T: CoreAlloc {
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout) -> Result<*mut u8, AllocErr> {
|
new_layout: Layout) -> Result<*mut u8, AllocErr> {
|
||||||
CoreAlloc::realloc(self, ptr, layout, new_layout)
|
CoreAlloc::realloc(self, ptr, layout, new_layout.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
|
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
|
||||||
|
@ -79,20 +79,20 @@ unsafe impl<T> Alloc for T where T: CoreAlloc {
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout) -> Result<Excess, AllocErr> {
|
new_layout: Layout) -> Result<Excess, AllocErr> {
|
||||||
CoreAlloc::realloc_excess(self, ptr, layout, new_layout)
|
CoreAlloc::realloc_excess(self, ptr, layout, new_layout.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn grow_in_place(&mut self,
|
unsafe fn grow_in_place(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout) -> Result<(), CannotReallocInPlace> {
|
new_layout: Layout) -> Result<(), CannotReallocInPlace> {
|
||||||
CoreAlloc::grow_in_place(self, ptr, layout, new_layout)
|
CoreAlloc::grow_in_place(self, ptr, layout, new_layout.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn shrink_in_place(&mut self,
|
unsafe fn shrink_in_place(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout) -> Result<(), CannotReallocInPlace> {
|
new_layout: Layout) -> Result<(), CannotReallocInPlace> {
|
||||||
CoreAlloc::shrink_in_place(self, ptr, layout, new_layout)
|
CoreAlloc::shrink_in_place(self, ptr, layout, new_layout.size())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -309,11 +309,10 @@ impl<T, A: Alloc> RawVec<T, A> {
|
||||||
// `from_size_align_unchecked`.
|
// `from_size_align_unchecked`.
|
||||||
let new_cap = 2 * self.cap;
|
let new_cap = 2 * self.cap;
|
||||||
let new_size = new_cap * elem_size;
|
let new_size = new_cap * elem_size;
|
||||||
let new_layout = Layout::from_size_align_unchecked(new_size, cur.align());
|
|
||||||
alloc_guard(new_size).expect("capacity overflow");
|
alloc_guard(new_size).expect("capacity overflow");
|
||||||
let ptr_res = self.a.realloc(self.ptr.as_ptr() as *mut u8,
|
let ptr_res = self.a.realloc(self.ptr.as_ptr() as *mut u8,
|
||||||
cur,
|
cur,
|
||||||
new_layout);
|
new_size);
|
||||||
match ptr_res {
|
match ptr_res {
|
||||||
Ok(ptr) => (new_cap, Unique::new_unchecked(ptr as *mut T)),
|
Ok(ptr) => (new_cap, Unique::new_unchecked(ptr as *mut T)),
|
||||||
Err(_) => self.a.oom(),
|
Err(_) => self.a.oom(),
|
||||||
|
@ -371,8 +370,7 @@ impl<T, A: Alloc> RawVec<T, A> {
|
||||||
let new_size = new_cap * elem_size;
|
let new_size = new_cap * elem_size;
|
||||||
alloc_guard(new_size).expect("capacity overflow");
|
alloc_guard(new_size).expect("capacity overflow");
|
||||||
let ptr = self.ptr() as *mut _;
|
let ptr = self.ptr() as *mut _;
|
||||||
let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
|
match self.a.grow_in_place(ptr, old_layout, new_size) {
|
||||||
match self.a.grow_in_place(ptr, old_layout, new_layout) {
|
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
// We can't directly divide `size`.
|
// We can't directly divide `size`.
|
||||||
self.cap = new_cap;
|
self.cap = new_cap;
|
||||||
|
@ -428,8 +426,9 @@ impl<T, A: Alloc> RawVec<T, A> {
|
||||||
|
|
||||||
let res = match self.current_layout() {
|
let res = match self.current_layout() {
|
||||||
Some(layout) => {
|
Some(layout) => {
|
||||||
|
debug_assert!(new_layout.align() == layout.align());
|
||||||
let old_ptr = self.ptr.as_ptr() as *mut u8;
|
let old_ptr = self.ptr.as_ptr() as *mut u8;
|
||||||
self.a.realloc(old_ptr, layout, new_layout)
|
self.a.realloc(old_ptr, layout, new_layout.size())
|
||||||
}
|
}
|
||||||
None => self.a.alloc(new_layout),
|
None => self.a.alloc(new_layout),
|
||||||
};
|
};
|
||||||
|
@ -537,8 +536,9 @@ impl<T, A: Alloc> RawVec<T, A> {
|
||||||
|
|
||||||
let res = match self.current_layout() {
|
let res = match self.current_layout() {
|
||||||
Some(layout) => {
|
Some(layout) => {
|
||||||
|
debug_assert!(new_layout.align() == layout.align());
|
||||||
let old_ptr = self.ptr.as_ptr() as *mut u8;
|
let old_ptr = self.ptr.as_ptr() as *mut u8;
|
||||||
self.a.realloc(old_ptr, layout, new_layout)
|
self.a.realloc(old_ptr, layout, new_layout.size())
|
||||||
}
|
}
|
||||||
None => self.a.alloc(new_layout),
|
None => self.a.alloc(new_layout),
|
||||||
};
|
};
|
||||||
|
@ -604,7 +604,7 @@ impl<T, A: Alloc> RawVec<T, A> {
|
||||||
let new_layout = Layout::new::<T>().repeat(new_cap).unwrap().0;
|
let new_layout = Layout::new::<T>().repeat(new_cap).unwrap().0;
|
||||||
// FIXME: may crash and burn on over-reserve
|
// FIXME: may crash and burn on over-reserve
|
||||||
alloc_guard(new_layout.size()).expect("capacity overflow");
|
alloc_guard(new_layout.size()).expect("capacity overflow");
|
||||||
match self.a.grow_in_place(ptr, old_layout, new_layout) {
|
match self.a.grow_in_place(ptr, old_layout, new_layout.size()) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
self.cap = new_cap;
|
self.cap = new_cap;
|
||||||
true
|
true
|
||||||
|
@ -664,10 +664,9 @@ impl<T, A: Alloc> RawVec<T, A> {
|
||||||
let new_size = elem_size * amount;
|
let new_size = elem_size * amount;
|
||||||
let align = mem::align_of::<T>();
|
let align = mem::align_of::<T>();
|
||||||
let old_layout = Layout::from_size_align_unchecked(old_size, align);
|
let old_layout = Layout::from_size_align_unchecked(old_size, align);
|
||||||
let new_layout = Layout::from_size_align_unchecked(new_size, align);
|
|
||||||
match self.a.realloc(self.ptr.as_ptr() as *mut u8,
|
match self.a.realloc(self.ptr.as_ptr() as *mut u8,
|
||||||
old_layout,
|
old_layout,
|
||||||
new_layout) {
|
new_size) {
|
||||||
Ok(p) => self.ptr = Unique::new_unchecked(p as *mut T),
|
Ok(p) => self.ptr = Unique::new_unchecked(p as *mut T),
|
||||||
Err(_) => self.a.oom(),
|
Err(_) => self.a.oom(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,8 +69,8 @@ unsafe impl Alloc for System {
|
||||||
unsafe fn realloc(&mut self,
|
unsafe fn realloc(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
old_layout: Layout,
|
old_layout: Layout,
|
||||||
new_layout: Layout) -> Result<*mut u8, AllocErr> {
|
new_size: usize) -> Result<*mut u8, AllocErr> {
|
||||||
Alloc::realloc(&mut &*self, ptr, old_layout, new_layout)
|
Alloc::realloc(&mut &*self, ptr, old_layout, new_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn oom(&mut self) -> ! {
|
fn oom(&mut self) -> ! {
|
||||||
|
@ -91,24 +91,24 @@ unsafe impl Alloc for System {
|
||||||
unsafe fn realloc_excess(&mut self,
|
unsafe fn realloc_excess(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout) -> Result<Excess, AllocErr> {
|
new_size: usize) -> Result<Excess, AllocErr> {
|
||||||
Alloc::realloc_excess(&mut &*self, ptr, layout, new_layout)
|
Alloc::realloc_excess(&mut &*self, ptr, layout, new_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn grow_in_place(&mut self,
|
unsafe fn grow_in_place(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout) -> Result<(), CannotReallocInPlace> {
|
new_size: usize) -> Result<(), CannotReallocInPlace> {
|
||||||
Alloc::grow_in_place(&mut &*self, ptr, layout, new_layout)
|
Alloc::grow_in_place(&mut &*self, ptr, layout, new_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn shrink_in_place(&mut self,
|
unsafe fn shrink_in_place(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout) -> Result<(), CannotReallocInPlace> {
|
new_size: usize) -> Result<(), CannotReallocInPlace> {
|
||||||
Alloc::shrink_in_place(&mut &*self, ptr, layout, new_layout)
|
Alloc::shrink_in_place(&mut &*self, ptr, layout, new_size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,12 +166,8 @@ macro_rules! alloc_methods_based_on_global_alloc {
|
||||||
unsafe fn realloc(&mut self,
|
unsafe fn realloc(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
old_layout: Layout,
|
old_layout: Layout,
|
||||||
new_layout: Layout) -> Result<*mut u8, AllocErr> {
|
new_size: usize) -> Result<*mut u8, AllocErr> {
|
||||||
if old_layout.align() != new_layout.align() {
|
let ptr = GlobalAlloc::realloc(*self, ptr as *mut Void, old_layout, new_size);
|
||||||
return Err(AllocErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
let ptr = GlobalAlloc::realloc(*self, ptr as *mut Void, old_layout, new_layout.size());
|
|
||||||
if !ptr.is_null() {
|
if !ptr.is_null() {
|
||||||
Ok(ptr as *mut u8)
|
Ok(ptr as *mut u8)
|
||||||
} else {
|
} else {
|
||||||
|
@ -428,30 +424,26 @@ mod platform {
|
||||||
unsafe fn grow_in_place(&mut self,
|
unsafe fn grow_in_place(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout) -> Result<(), CannotReallocInPlace> {
|
new_size: usize) -> Result<(), CannotReallocInPlace> {
|
||||||
self.shrink_in_place(ptr, layout, new_layout)
|
self.shrink_in_place(ptr, layout, new_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn shrink_in_place(&mut self,
|
unsafe fn shrink_in_place(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
old_layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout) -> Result<(), CannotReallocInPlace> {
|
new_size: usize) -> Result<(), CannotReallocInPlace> {
|
||||||
if old_layout.align() != new_layout.align() {
|
let new = if layout.align() <= MIN_ALIGN {
|
||||||
return Err(CannotReallocInPlace)
|
|
||||||
}
|
|
||||||
|
|
||||||
let new = if new_layout.align() <= MIN_ALIGN {
|
|
||||||
HeapReAlloc(GetProcessHeap(),
|
HeapReAlloc(GetProcessHeap(),
|
||||||
HEAP_REALLOC_IN_PLACE_ONLY,
|
HEAP_REALLOC_IN_PLACE_ONLY,
|
||||||
ptr as LPVOID,
|
ptr as LPVOID,
|
||||||
new_layout.size())
|
new_size)
|
||||||
} else {
|
} else {
|
||||||
let header = get_header(ptr);
|
let header = get_header(ptr);
|
||||||
HeapReAlloc(GetProcessHeap(),
|
HeapReAlloc(GetProcessHeap(),
|
||||||
HEAP_REALLOC_IN_PLACE_ONLY,
|
HEAP_REALLOC_IN_PLACE_ONLY,
|
||||||
header.0 as LPVOID,
|
header.0 as LPVOID,
|
||||||
new_layout.size() + new_layout.align())
|
new_size + layout.align())
|
||||||
};
|
};
|
||||||
if new.is_null() {
|
if new.is_null() {
|
||||||
Err(CannotReallocInPlace)
|
Err(CannotReallocInPlace)
|
||||||
|
|
|
@ -633,9 +633,10 @@ pub unsafe trait Alloc {
|
||||||
// realloc. alloc_excess, realloc_excess
|
// realloc. alloc_excess, realloc_excess
|
||||||
|
|
||||||
/// Returns a pointer suitable for holding data described by
|
/// Returns a pointer suitable for holding data described by
|
||||||
/// `new_layout`, meeting its size and alignment guarantees. To
|
/// a new layout with `layout`’s alginment and a size given
|
||||||
|
/// by `new_size`. To
|
||||||
/// accomplish this, this may extend or shrink the allocation
|
/// accomplish this, this may extend or shrink the allocation
|
||||||
/// referenced by `ptr` to fit `new_layout`.
|
/// referenced by `ptr` to fit the new layout.
|
||||||
///
|
///
|
||||||
/// If this returns `Ok`, then ownership of the memory block
|
/// If this returns `Ok`, then ownership of the memory block
|
||||||
/// referenced by `ptr` has been transferred to this
|
/// referenced by `ptr` has been transferred to this
|
||||||
|
@ -648,12 +649,6 @@ pub unsafe trait Alloc {
|
||||||
/// block has not been transferred to this allocator, and the
|
/// block has not been transferred to this allocator, and the
|
||||||
/// contents of the memory block are unaltered.
|
/// contents of the memory block are unaltered.
|
||||||
///
|
///
|
||||||
/// For best results, `new_layout` should not impose a different
|
|
||||||
/// alignment constraint than `layout`. (In other words,
|
|
||||||
/// `new_layout.align()` should equal `layout.align()`.) However,
|
|
||||||
/// behavior is well-defined (though underspecified) when this
|
|
||||||
/// constraint is violated; further discussion below.
|
|
||||||
///
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// This function is unsafe because undefined behavior can result
|
/// This function is unsafe because undefined behavior can result
|
||||||
|
@ -661,12 +656,13 @@ pub unsafe trait Alloc {
|
||||||
///
|
///
|
||||||
/// * `ptr` must be currently allocated via this allocator,
|
/// * `ptr` must be currently allocated via this allocator,
|
||||||
///
|
///
|
||||||
/// * `layout` must *fit* the `ptr` (see above). (The `new_layout`
|
/// * `layout` must *fit* the `ptr` (see above). (The `new_size`
|
||||||
/// argument need not fit it.)
|
/// argument need not fit it.)
|
||||||
///
|
///
|
||||||
/// * `new_layout` must have size greater than zero.
|
/// * `new_size` must be greater than zero.
|
||||||
///
|
///
|
||||||
/// * the alignment of `new_layout` is non-zero.
|
/// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
|
||||||
|
/// must not overflow (i.e. the rounded value must be less than `usize::MAX`).
|
||||||
///
|
///
|
||||||
/// (Extension subtraits might provide more specific bounds on
|
/// (Extension subtraits might provide more specific bounds on
|
||||||
/// behavior, e.g. guarantee a sentinel address or a null pointer
|
/// behavior, e.g. guarantee a sentinel address or a null pointer
|
||||||
|
@ -674,18 +670,11 @@ pub unsafe trait Alloc {
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// Returns `Err` only if `new_layout` does not match the
|
/// Returns `Err` only if the new layout
|
||||||
/// alignment of `layout`, or does not meet the allocator's size
|
/// does not meet the allocator's size
|
||||||
/// and alignment constraints of the allocator, or if reallocation
|
/// and alignment constraints of the allocator, or if reallocation
|
||||||
/// otherwise fails.
|
/// otherwise fails.
|
||||||
///
|
///
|
||||||
/// (Note the previous sentence did not say "if and only if" -- in
|
|
||||||
/// particular, an implementation of this method *can* return `Ok`
|
|
||||||
/// if `new_layout.align() != old_layout.align()`; or it can
|
|
||||||
/// return `Err` in that scenario, depending on whether this
|
|
||||||
/// allocator can dynamically adjust the alignment constraint for
|
|
||||||
/// the block.)
|
|
||||||
///
|
|
||||||
/// Implementations are encouraged to return `Err` on memory
|
/// Implementations are encouraged to return `Err` on memory
|
||||||
/// exhaustion rather than panicking or aborting, but this is not
|
/// exhaustion rather than panicking or aborting, but this is not
|
||||||
/// a strict requirement. (Specifically: it is *legal* to
|
/// a strict requirement. (Specifically: it is *legal* to
|
||||||
|
@ -698,22 +687,21 @@ pub unsafe trait Alloc {
|
||||||
unsafe fn realloc(&mut self,
|
unsafe fn realloc(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout) -> Result<*mut u8, AllocErr> {
|
new_size: usize) -> Result<*mut u8, AllocErr> {
|
||||||
let new_size = new_layout.size();
|
|
||||||
let old_size = layout.size();
|
let old_size = layout.size();
|
||||||
let aligns_match = layout.align == new_layout.align;
|
|
||||||
|
|
||||||
if new_size >= old_size && aligns_match {
|
if new_size >= old_size {
|
||||||
if let Ok(()) = self.grow_in_place(ptr, layout.clone(), new_layout.clone()) {
|
if let Ok(()) = self.grow_in_place(ptr, layout.clone(), new_size) {
|
||||||
return Ok(ptr);
|
return Ok(ptr);
|
||||||
}
|
}
|
||||||
} else if new_size < old_size && aligns_match {
|
} else if new_size < old_size {
|
||||||
if let Ok(()) = self.shrink_in_place(ptr, layout.clone(), new_layout.clone()) {
|
if let Ok(()) = self.shrink_in_place(ptr, layout.clone(), new_size) {
|
||||||
return Ok(ptr);
|
return Ok(ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, fall back on alloc + copy + dealloc.
|
// otherwise, fall back on alloc + copy + dealloc.
|
||||||
|
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
|
||||||
let result = self.alloc(new_layout);
|
let result = self.alloc(new_layout);
|
||||||
if let Ok(new_ptr) = result {
|
if let Ok(new_ptr) = result {
|
||||||
ptr::copy_nonoverlapping(ptr as *const u8, new_ptr, cmp::min(old_size, new_size));
|
ptr::copy_nonoverlapping(ptr as *const u8, new_ptr, cmp::min(old_size, new_size));
|
||||||
|
@ -789,17 +777,19 @@ pub unsafe trait Alloc {
|
||||||
unsafe fn realloc_excess(&mut self,
|
unsafe fn realloc_excess(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout) -> Result<Excess, AllocErr> {
|
new_size: usize) -> Result<Excess, AllocErr> {
|
||||||
|
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
|
||||||
let usable_size = self.usable_size(&new_layout);
|
let usable_size = self.usable_size(&new_layout);
|
||||||
self.realloc(ptr, layout, new_layout)
|
self.realloc(ptr, layout, new_size)
|
||||||
.map(|p| Excess(p, usable_size.1))
|
.map(|p| Excess(p, usable_size.1))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to extend the allocation referenced by `ptr` to fit `new_layout`.
|
/// Attempts to extend the allocation referenced by `ptr` to fit `new_size`.
|
||||||
///
|
///
|
||||||
/// If this returns `Ok`, then the allocator has asserted that the
|
/// If this returns `Ok`, then the allocator has asserted that the
|
||||||
/// memory block referenced by `ptr` now fits `new_layout`, and thus can
|
/// memory block referenced by `ptr` now fits `new_size`, and thus can
|
||||||
/// be used to carry data of that layout. (The allocator is allowed to
|
/// be used to carry data of a layout of that size and same alignment as
|
||||||
|
/// `layout`. (The allocator is allowed to
|
||||||
/// expend effort to accomplish this, such as extending the memory block to
|
/// expend effort to accomplish this, such as extending the memory block to
|
||||||
/// include successor blocks, or virtual memory tricks.)
|
/// include successor blocks, or virtual memory tricks.)
|
||||||
///
|
///
|
||||||
|
@ -815,11 +805,9 @@ pub unsafe trait Alloc {
|
||||||
/// * `ptr` must be currently allocated via this allocator,
|
/// * `ptr` must be currently allocated via this allocator,
|
||||||
///
|
///
|
||||||
/// * `layout` must *fit* the `ptr` (see above); note the
|
/// * `layout` must *fit* the `ptr` (see above); note the
|
||||||
/// `new_layout` argument need not fit it,
|
/// `new_size` argument need not fit it,
|
||||||
///
|
///
|
||||||
/// * `new_layout.size()` must not be less than `layout.size()`,
|
/// * `new_size` must not be less than `layout.size()`,
|
||||||
///
|
|
||||||
/// * `new_layout.align()` must equal `layout.align()`.
|
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
|
@ -834,24 +822,23 @@ pub unsafe trait Alloc {
|
||||||
unsafe fn grow_in_place(&mut self,
|
unsafe fn grow_in_place(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout) -> Result<(), CannotReallocInPlace> {
|
new_size: usize) -> Result<(), CannotReallocInPlace> {
|
||||||
let _ = ptr; // this default implementation doesn't care about the actual address.
|
let _ = ptr; // this default implementation doesn't care about the actual address.
|
||||||
debug_assert!(new_layout.size >= layout.size);
|
debug_assert!(new_size >= layout.size);
|
||||||
debug_assert!(new_layout.align == layout.align);
|
|
||||||
let (_l, u) = self.usable_size(&layout);
|
let (_l, u) = self.usable_size(&layout);
|
||||||
// _l <= layout.size() [guaranteed by usable_size()]
|
// _l <= layout.size() [guaranteed by usable_size()]
|
||||||
// layout.size() <= new_layout.size() [required by this method]
|
// layout.size() <= new_layout.size() [required by this method]
|
||||||
if new_layout.size <= u {
|
if new_size <= u {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} else {
|
||||||
return Err(CannotReallocInPlace);
|
return Err(CannotReallocInPlace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to shrink the allocation referenced by `ptr` to fit `new_layout`.
|
/// Attempts to shrink the allocation referenced by `ptr` to fit `new_size`.
|
||||||
///
|
///
|
||||||
/// If this returns `Ok`, then the allocator has asserted that the
|
/// If this returns `Ok`, then the allocator has asserted that the
|
||||||
/// memory block referenced by `ptr` now fits `new_layout`, and
|
/// memory block referenced by `ptr` now fits `new_size`, and
|
||||||
/// thus can only be used to carry data of that smaller
|
/// thus can only be used to carry data of that smaller
|
||||||
/// layout. (The allocator is allowed to take advantage of this,
|
/// layout. (The allocator is allowed to take advantage of this,
|
||||||
/// carving off portions of the block for reuse elsewhere.) The
|
/// carving off portions of the block for reuse elsewhere.) The
|
||||||
|
@ -872,13 +859,11 @@ pub unsafe trait Alloc {
|
||||||
/// * `ptr` must be currently allocated via this allocator,
|
/// * `ptr` must be currently allocated via this allocator,
|
||||||
///
|
///
|
||||||
/// * `layout` must *fit* the `ptr` (see above); note the
|
/// * `layout` must *fit* the `ptr` (see above); note the
|
||||||
/// `new_layout` argument need not fit it,
|
/// `new_size` argument need not fit it,
|
||||||
///
|
///
|
||||||
/// * `new_layout.size()` must not be greater than `layout.size()`
|
/// * `new_size` must not be greater than `layout.size()`
|
||||||
/// (and must be greater than zero),
|
/// (and must be greater than zero),
|
||||||
///
|
///
|
||||||
/// * `new_layout.align()` must equal `layout.align()`.
|
|
||||||
///
|
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// Returns `Err(CannotReallocInPlace)` when the allocator is
|
/// Returns `Err(CannotReallocInPlace)` when the allocator is
|
||||||
|
@ -892,14 +877,13 @@ pub unsafe trait Alloc {
|
||||||
unsafe fn shrink_in_place(&mut self,
|
unsafe fn shrink_in_place(&mut self,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
new_layout: Layout) -> Result<(), CannotReallocInPlace> {
|
new_size: usize) -> Result<(), CannotReallocInPlace> {
|
||||||
let _ = ptr; // this default implementation doesn't care about the actual address.
|
let _ = ptr; // this default implementation doesn't care about the actual address.
|
||||||
debug_assert!(new_layout.size <= layout.size);
|
debug_assert!(new_size <= layout.size);
|
||||||
debug_assert!(new_layout.align == layout.align);
|
|
||||||
let (l, _u) = self.usable_size(&layout);
|
let (l, _u) = self.usable_size(&layout);
|
||||||
// layout.size() <= _u [guaranteed by usable_size()]
|
// layout.size() <= _u [guaranteed by usable_size()]
|
||||||
// new_layout.size() <= layout.size() [required by this method]
|
// new_layout.size() <= layout.size() [required by this method]
|
||||||
if l <= new_layout.size {
|
if l <= new_size {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} else {
|
||||||
return Err(CannotReallocInPlace);
|
return Err(CannotReallocInPlace);
|
||||||
|
@ -1061,7 +1045,8 @@ pub unsafe trait Alloc {
|
||||||
{
|
{
|
||||||
match (Layout::array::<T>(n_old), Layout::array::<T>(n_new), ptr.as_ptr()) {
|
match (Layout::array::<T>(n_old), Layout::array::<T>(n_new), ptr.as_ptr()) {
|
||||||
(Ok(ref k_old), Ok(ref k_new), ptr) if k_old.size() > 0 && k_new.size() > 0 => {
|
(Ok(ref k_old), Ok(ref k_new), ptr) if k_old.size() > 0 && k_new.size() > 0 => {
|
||||||
self.realloc(ptr as *mut u8, k_old.clone(), k_new.clone())
|
debug_assert!(k_old.align() == k_new.align());
|
||||||
|
self.realloc(ptr as *mut u8, k_old.clone(), k_new.size())
|
||||||
.map(|p| NonNull::new_unchecked(p as *mut T))
|
.map(|p| NonNull::new_unchecked(p as *mut T))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue