allocator_api2/alloc/
system.rs1use core::ptr::NonNull;
2pub use std::alloc::System;
3
4use crate::{assume, invalid_mut};
5
6use super::{AllocError, Allocator, GlobalAlloc as _, Layout};
7
8unsafe impl Allocator for System {
9 #[inline(always)]
10 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
11 alloc_impl(layout, false)
12 }
13
14 #[inline(always)]
15 fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
16 alloc_impl(layout, true)
17 }
18
19 #[inline(always)]
20 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
21 if layout.size() != 0 {
22 unsafe { System.dealloc(ptr.as_ptr(), layout) }
25 }
26 }
27
28 #[inline(always)]
29 unsafe fn grow(
30 &self,
31 ptr: NonNull<u8>,
32 old_layout: Layout,
33 new_layout: Layout,
34 ) -> Result<NonNull<[u8]>, AllocError> {
35 unsafe { grow_impl(ptr, old_layout, new_layout, false) }
37 }
38
39 #[inline(always)]
40 unsafe fn grow_zeroed(
41 &self,
42 ptr: NonNull<u8>,
43 old_layout: Layout,
44 new_layout: Layout,
45 ) -> Result<NonNull<[u8]>, AllocError> {
46 unsafe { grow_impl(ptr, old_layout, new_layout, true) }
48 }
49
50 #[inline(always)]
51 unsafe fn shrink(
52 &self,
53 ptr: NonNull<u8>,
54 old_layout: Layout,
55 new_layout: Layout,
56 ) -> Result<NonNull<[u8]>, AllocError> {
57 debug_assert!(
58 new_layout.size() <= old_layout.size(),
59 "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
60 );
61
62 match new_layout.size() {
63 0 => unsafe {
65 self.deallocate(ptr, old_layout);
66 Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
67 invalid_mut(new_layout.align()),
68 0,
69 )))
70 },
71
72 new_size if old_layout.align() == new_layout.align() => unsafe {
74 assume(new_size <= old_layout.size());
76
77 let raw_ptr = System.realloc(ptr.as_ptr(), old_layout, new_size);
78 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
79 Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
80 ptr.as_ptr(),
81 new_size,
82 )))
83 },
84
85 new_size => unsafe {
91 let new_ptr = self.allocate(new_layout)?;
92 core::ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr().cast(), new_size);
93 self.deallocate(ptr, old_layout);
94 Ok(new_ptr)
95 },
96 }
97 }
98}
99
100#[inline(always)]
101fn alloc_impl(layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
102 match layout.size() {
103 0 => Ok(unsafe {
104 NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
105 invalid_mut(layout.align()),
106 0,
107 ))
108 }),
109 size => unsafe {
111 let raw_ptr = if zeroed {
112 System.alloc_zeroed(layout)
113 } else {
114 System.alloc(layout)
115 };
116 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
117 Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
118 ptr.as_ptr(),
119 size,
120 )))
121 },
122 }
123}
124
125#[inline(always)]
127unsafe fn grow_impl(
128 ptr: NonNull<u8>,
129 old_layout: Layout,
130 new_layout: Layout,
131 zeroed: bool,
132) -> Result<NonNull<[u8]>, AllocError> {
133 debug_assert!(
134 new_layout.size() >= old_layout.size(),
135 "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
136 );
137
138 match old_layout.size() {
139 0 => alloc_impl(new_layout, zeroed),
140
141 old_size if old_layout.align() == new_layout.align() => unsafe {
144 let new_size = new_layout.size();
145
146 assume(new_size >= old_layout.size());
148
149 let raw_ptr = System.realloc(ptr.as_ptr(), old_layout, new_size);
150 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
151 if zeroed {
152 raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
153 }
154 Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
155 ptr.as_ptr(),
156 new_size,
157 )))
158 },
159
160 old_size => unsafe {
166 let new_ptr = alloc_impl(new_layout, zeroed)?;
167 core::ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr().cast(), old_size);
168 System.deallocate(ptr, old_layout);
169 Ok(new_ptr)
170 },
171 }
172}