allocator_api2/stable/alloc/
global.rs1use core::ptr::NonNull;
2
3use alloc_crate::alloc::{alloc, alloc_zeroed, dealloc, realloc};
4
5use crate::stable::{assume, invalid_mut};
6
7use super::{AllocError, Allocator, Layout};
8
9#[derive(Copy, Clone, Default, Debug)]
18pub struct Global;
19
20impl Global {
21 #[inline(always)]
22 fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
23 match layout.size() {
24 0 => Ok(unsafe {
25 NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
26 invalid_mut(layout.align()),
27 0,
28 ))
29 }),
30 size => unsafe {
32 let raw_ptr = if zeroed {
33 alloc_zeroed(layout)
34 } else {
35 alloc(layout)
36 };
37 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
38 Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
39 ptr.as_ptr(),
40 size,
41 )))
42 },
43 }
44 }
45
46 #[inline(always)]
48 unsafe fn grow_impl(
49 &self,
50 ptr: NonNull<u8>,
51 old_layout: Layout,
52 new_layout: Layout,
53 zeroed: bool,
54 ) -> Result<NonNull<[u8]>, AllocError> {
55 debug_assert!(
56 new_layout.size() >= old_layout.size(),
57 "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
58 );
59
60 match old_layout.size() {
61 0 => self.alloc_impl(new_layout, zeroed),
62
63 old_size if old_layout.align() == new_layout.align() => unsafe {
66 let new_size = new_layout.size();
67
68 assume(new_size >= old_layout.size());
70
71 let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size);
72 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
73 if zeroed {
74 raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
75 }
76 Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
77 ptr.as_ptr(),
78 new_size,
79 )))
80 },
81
82 old_size => unsafe {
88 let new_ptr = self.alloc_impl(new_layout, zeroed)?;
89 core::ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr().cast(), old_size);
90 self.deallocate(ptr, old_layout);
91 Ok(new_ptr)
92 },
93 }
94 }
95}
96
97unsafe impl Allocator for Global {
98 #[inline(always)]
99 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
100 self.alloc_impl(layout, false)
101 }
102
103 #[inline(always)]
104 fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
105 self.alloc_impl(layout, true)
106 }
107
108 #[inline(always)]
109 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
110 if layout.size() != 0 {
111 unsafe { dealloc(ptr.as_ptr(), layout) }
114 }
115 }
116
117 #[inline(always)]
118 unsafe fn grow(
119 &self,
120 ptr: NonNull<u8>,
121 old_layout: Layout,
122 new_layout: Layout,
123 ) -> Result<NonNull<[u8]>, AllocError> {
124 unsafe { self.grow_impl(ptr, old_layout, new_layout, false) }
126 }
127
128 #[inline(always)]
129 unsafe fn grow_zeroed(
130 &self,
131 ptr: NonNull<u8>,
132 old_layout: Layout,
133 new_layout: Layout,
134 ) -> Result<NonNull<[u8]>, AllocError> {
135 unsafe { self.grow_impl(ptr, old_layout, new_layout, true) }
137 }
138
139 #[inline(always)]
140 unsafe fn shrink(
141 &self,
142 ptr: NonNull<u8>,
143 old_layout: Layout,
144 new_layout: Layout,
145 ) -> Result<NonNull<[u8]>, AllocError> {
146 debug_assert!(
147 new_layout.size() <= old_layout.size(),
148 "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
149 );
150
151 match new_layout.size() {
152 0 => unsafe {
154 self.deallocate(ptr, old_layout);
155 Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
156 invalid_mut(new_layout.align()),
157 0,
158 )))
159 },
160
161 new_size if old_layout.align() == new_layout.align() => unsafe {
163 assume(new_size <= old_layout.size());
165
166 let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size);
167 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
168 Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
169 ptr.as_ptr(),
170 new_size,
171 )))
172 },
173
174 new_size => unsafe {
180 let new_ptr = self.allocate(new_layout)?;
181 core::ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr().cast(), new_size);
182 self.deallocate(ptr, old_layout);
183 Ok(new_ptr)
184 },
185 }
186 }
187}