diff options
| author | bors <bors@rust-lang.org> | 2020-08-18 18:43:50 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-08-18 18:43:50 +0000 |
| commit | be97d13ffc41961c018c313e909f76ba3bbdc958 (patch) | |
| tree | 122ed2e56e07d8b63ec5e7ea280fd9565f1b3dd7 /library/alloc/src/alloc.rs | |
| parent | b287b56f97288cc4605329f76e31cb7604474aef (diff) | |
| parent | 63d241a7b78f129477d980bf5a6baa818f47b4f8 (diff) | |
Auto merge of #75657 - TimDiekmann:allocref-cleanup, r=Amanieu
Clean up AllocRef implementation and documentation r? @Amanieu
Diffstat (limited to 'library/alloc/src/alloc.rs')
| -rw-r--r-- | library/alloc/src/alloc.rs | 148 |
1 files changed, 74 insertions, 74 deletions
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index fb9bee60202..fa5eb1823f1 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -161,30 +161,69 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { unsafe { __rust_alloc_zeroed(layout.size(), layout.align()) } } +impl Global { + #[inline] + fn alloc_impl(&mut self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocErr> { + match layout.size() { + 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), + // SAFETY: `layout` is non-zero in size, + size => unsafe { + let raw_ptr = if zeroed { alloc_zeroed(layout) } else { alloc(layout) }; + let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?; + Ok(NonNull::slice_from_raw_parts(ptr, size)) + }, + } + } + + // Safety: Same as `AllocRef::grow` + #[inline] + unsafe fn grow_impl( + &mut self, + ptr: NonNull<u8>, + layout: Layout, + new_size: usize, + zeroed: bool, + ) -> Result<NonNull<[u8]>, AllocErr> { + debug_assert!( + new_size >= layout.size(), + "`new_size` must be greater than or equal to `layout.size()`" + ); + + match layout.size() { + // SAFETY: the caller must ensure that the `new_size` does not overflow. + // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout. + 0 => unsafe { + let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); + self.alloc_impl(new_layout, zeroed) + }, + + // SAFETY: `new_size` is non-zero as `old_size` is greater than or equal to `new_size` + // as required by safety conditions. Other conditions must be upheld by the caller + old_size => unsafe { + // `realloc` probably checks for `new_size >= size` or something similar. + intrinsics::assume(new_size >= layout.size()); + + let raw_ptr = realloc(ptr.as_ptr(), layout, new_size); + let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?; + if zeroed { + raw_ptr.add(old_size).write_bytes(0, new_size - old_size); + } + Ok(NonNull::slice_from_raw_parts(ptr, new_size)) + }, + } + } +} + #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl AllocRef for Global { #[inline] fn alloc(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> { - 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(NonNull::slice_from_raw_parts(ptr, size)) + self.alloc_impl(layout, false) } #[inline] fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> { - 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(NonNull::slice_from_raw_parts(ptr, size)) + self.alloc_impl(layout, true) } #[inline] @@ -203,26 +242,8 @@ unsafe impl AllocRef for Global { layout: Layout, new_size: usize, ) -> Result<NonNull<[u8]>, AllocErr> { - debug_assert!( - new_size >= layout.size(), - "`new_size` must be greater than or equal to `layout.size()`" - ); - - // SAFETY: `new_size` must be non-zero, which is checked in the match expression. - // If `new_size` is zero, then `old_size` has to be zero as well. - // Other conditions must be upheld by the caller - unsafe { - match layout.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(NonNull::slice_from_raw_parts(ptr, new_size)) - } - } - } + // SAFETY: all conditions must be upheld by the caller + unsafe { self.grow_impl(ptr, layout, new_size, false) } } #[inline] @@ -232,27 +253,8 @@ unsafe impl AllocRef for Global { layout: Layout, new_size: usize, ) -> Result<NonNull<[u8]>, AllocErr> { - debug_assert!( - new_size >= layout.size(), - "`new_size` must be greater than or equal to `layout.size()`" - ); - - // SAFETY: `new_size` must be non-zero, which is checked in the match expression. - // If `new_size` is zero, then `old_size` has to be zero as well. - // Other conditions must be upheld by the caller - unsafe { - match layout.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(NonNull::slice_from_raw_parts(ptr, new_size)) - } - } - } + // SAFETY: all conditions must be upheld by the caller + unsafe { self.grow_impl(ptr, layout, new_size, true) } } #[inline] @@ -262,30 +264,28 @@ unsafe impl AllocRef for Global { layout: Layout, new_size: usize, ) -> Result<NonNull<[u8]>, AllocErr> { - let old_size = layout.size(); debug_assert!( - new_size <= old_size, + new_size <= layout.size(), "`new_size` must be smaller than or equal to `layout.size()`" ); - let ptr = if new_size == 0 { + match new_size { // SAFETY: conditions must be upheld by the caller - unsafe { + 0 => unsafe { self.dealloc(ptr, layout); - } - layout.dangling() - } else { - // 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) - }; - NonNull::new(raw_ptr).ok_or(AllocErr)? - }; + Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)) + }, - Ok(NonNull::slice_from_raw_parts(ptr, new_size)) + // SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller + new_size => unsafe { + // `realloc` probably checks for `new_size <= size` or something similar. + intrinsics::assume(new_size <= layout.size()); + + let raw_ptr = realloc(ptr.as_ptr(), layout, new_size); + let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?; + Ok(NonNull::slice_from_raw_parts(ptr, new_size)) + }, + } } } |
