diff options
| author | Tim Diekmann <tim.diekmann@3dvision.de> | 2020-07-29 11:41:36 +0200 |
|---|---|---|
| committer | Tim Diekmann <tim.diekmann@3dvision.de> | 2020-07-29 11:41:36 +0200 |
| commit | b01fbc437eae177cd02e7798f2f1454c1c6ed6e5 (patch) | |
| tree | 85c9b547edca31684cd602bfb0777810b55ab65c /library/alloc/src/alloc.rs | |
| parent | 076ef66ba2f647a627806f376c23b332fb04d3ff (diff) | |
| download | rust-b01fbc437eae177cd02e7798f2f1454c1c6ed6e5.tar.gz rust-b01fbc437eae177cd02e7798f2f1454c1c6ed6e5.zip | |
Simplify implementations of `AllocRef` for `Global` and `System`
Diffstat (limited to 'library/alloc/src/alloc.rs')
| -rw-r--r-- | library/alloc/src/alloc.rs | 141 |
1 files changed, 70 insertions, 71 deletions
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 16f3f5d5745..111ef406c00 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -165,34 +165,33 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { unsafe impl AllocRef for Global { #[inline] fn alloc(&mut self, layout: Layout) -> Result<MemoryBlock, AllocErr> { - unsafe { - let size = layout.size(); - if size == 0 { - Ok(MemoryBlock { ptr: layout.dangling(), size: 0 }) - } else { - let raw_ptr = alloc(layout); - let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?; - Ok(MemoryBlock { ptr, size }) - } - } + let size = layout.size(); + let ptr = if size == 0 { + layout.dangling() + } else { + // SAFETY: `layout` is non-zero in size, + unsafe { NonNull::new(alloc(layout)).ok_or(AllocErr)? } + }; + Ok(MemoryBlock { ptr, size }) } + #[inline] fn alloc_zeroed(&mut self, layout: Layout) -> Result<MemoryBlock, AllocErr> { - unsafe { - let size = layout.size(); - if size == 0 { - Ok(MemoryBlock { ptr: layout.dangling(), size: 0 }) - } else { - let raw_ptr = alloc_zeroed(layout); - let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?; - Ok(MemoryBlock { ptr, size }) - } - } + let size = layout.size(); + let ptr = if size == 0 { + layout.dangling() + } else { + // SAFETY: `layout` is non-zero in size, + unsafe { NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr)? } + }; + Ok(MemoryBlock { ptr, size }) } #[inline] unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) { if layout.size() != 0 { + // SAFETY: `layout` is non-zero in size, + // other conditions must be upheld by the caller unsafe { dealloc(ptr.as_ptr(), layout) } } } @@ -204,59 +203,55 @@ unsafe impl AllocRef for Global { layout: Layout, new_size: usize, ) -> Result<MemoryBlock, AllocErr> { - let size = layout.size(); debug_assert!( - new_size >= size, - "`new_size` must be greater than or equal to `memory.size()`" + new_size >= layout.size(), + "`new_size` must be greater than or equal to `layout.size()`" ); - if size == new_size { - return Ok(MemoryBlock { ptr, size }); - } - - if layout.size() == 0 { - let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; - self.alloc(new_layout) - } else { - // `realloc` probably checks for `new_size > size` or something similar. - let ptr = unsafe { - intrinsics::assume(new_size > size); - realloc(ptr.as_ptr(), layout, new_size) - }; - Ok(MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size }) + // SAFETY: `new_size` must be non-zero, which is checked in the match expression. + // Other conditions must be upheld by the caller + unsafe { + match layout.size() { + old_size if old_size == new_size => Ok(MemoryBlock { ptr, size: new_size }), + 0 => self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())), + old_size => { + // `realloc` probably checks for `new_size > size` or something similar. + intrinsics::assume(new_size > old_size); + let raw_ptr = realloc(ptr.as_ptr(), layout, new_size); + let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?; + Ok(MemoryBlock { ptr, size: new_size }) + } + } } } + #[inline] unsafe fn grow_zeroed( &mut self, ptr: NonNull<u8>, layout: Layout, new_size: usize, ) -> Result<MemoryBlock, AllocErr> { - let size = layout.size(); debug_assert!( - new_size >= size, - "`new_size` must be greater than or equal to `memory.size()`" + new_size >= layout.size(), + "`new_size` must be greater than or equal to `layout.size()`" ); - if size == new_size { - return Ok(MemoryBlock { ptr, size }); - } - - if layout.size() == 0 { - let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; - self.alloc(new_layout) - } else { - // `realloc` probably checks for `new_size > size` or something similar. - let ptr = unsafe { - intrinsics::assume(new_size > size); - realloc(ptr.as_ptr(), layout, new_size) - }; - let memory = MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size }; - unsafe { - memory.ptr.as_ptr().add(size).write_bytes(0, memory.size - size); + // SAFETY: `new_size` must be non-zero, which is checked in the match expression. + // Other conditions must be upheld by the caller + unsafe { + match layout.size() { + old_size if old_size == new_size => Ok(MemoryBlock { ptr, size: new_size }), + 0 => self.alloc_zeroed(Layout::from_size_align_unchecked(new_size, layout.align())), + old_size => { + // `realloc` probably checks for `new_size > size` or something similar. + intrinsics::assume(new_size > old_size); + let raw_ptr = realloc(ptr.as_ptr(), layout, new_size); + raw_ptr.add(old_size).write_bytes(0, new_size - old_size); + let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?; + Ok(MemoryBlock { ptr, size: new_size }) + } } - Ok(memory) } } @@ -267,29 +262,33 @@ unsafe impl AllocRef for Global { layout: Layout, new_size: usize, ) -> Result<MemoryBlock, AllocErr> { - let size = layout.size(); + let old_size = layout.size(); debug_assert!( - new_size <= size, - "`new_size` must be smaller than or equal to `memory.size()`" + new_size <= old_size, + "`new_size` must be smaller than or equal to `layout.size()`" ); - if size == new_size { - return Ok(MemoryBlock { ptr, size }); - } - - if new_size == 0 { + let ptr = if new_size == old_size { + ptr + } else if new_size == 0 { + // SAFETY: `layout` is non-zero in size as `old_size` != `new_size` + // Other conditions must be upheld by the caller unsafe { self.dealloc(ptr, layout); } - Ok(MemoryBlock { ptr: layout.dangling(), size: 0 }) + layout.dangling() } else { - // `realloc` probably checks for `new_size < size` or something similar. - let ptr = unsafe { - intrinsics::assume(new_size < size); + // SAFETY: new_size is not zero, + // Other conditions must be upheld by the caller + let raw_ptr = unsafe { + // `realloc` probably checks for `new_size < old_size` or something similar. + intrinsics::assume(new_size < old_size); realloc(ptr.as_ptr(), layout, new_size) }; - Ok(MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size }) - } + NonNull::new(raw_ptr).ok_or(AllocErr)? + }; + + Ok(MemoryBlock { ptr, size: new_size }) } } |
