commonlibsse_ng\re\m\MemoryManager\alloc\tes_global/
impl_selfless.rs1use core::ptr;
7use core::{alloc::Layout, hint, ptr::NonNull};
8
9use stdx::alloc::{AllocError, non_null_empty_slice};
10
11use crate::re::MemoryManager::{
12 TESGlobalAlloc,
13 alloc::{alloc, alloc_zeroed, dealloc, realloc},
14};
15
16use std_fork::alloc::SelflessAllocator;
17
18impl TESGlobalAlloc {
19 #[inline]
20 #[cfg_attr(miri, track_caller)] pub(crate) fn alloc_impl(layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
22 match layout.size() {
23 0 => Ok(non_null_empty_slice(layout)),
24 size => unsafe {
26 let raw_ptr = if zeroed { alloc_zeroed(layout) } else { alloc(layout) };
27 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
28 Ok(NonNull::slice_from_raw_parts(ptr, size))
29 },
30 }
31 }
32
33 #[inline]
35 #[cfg_attr(miri, track_caller)] pub(crate) unsafe fn grow_impl(
37 ptr: NonNull<u8>,
38 old_layout: Layout,
39 new_layout: Layout,
40 zeroed: bool,
41 ) -> Result<NonNull<[u8]>, AllocError> {
42 debug_assert!(
43 new_layout.size() >= old_layout.size(),
44 "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
45 );
46
47 match old_layout.size() {
48 0 => Self::alloc_impl(new_layout, zeroed),
49
50 old_size if old_layout.align() == new_layout.align() => unsafe {
53 let new_size = new_layout.size();
54
55 hint::assert_unchecked(new_size >= old_layout.size());
57
58 let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size);
59 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
60 if zeroed {
61 raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
62 }
63 Ok(NonNull::slice_from_raw_parts(ptr, new_size))
64 },
65
66 old_size => unsafe {
72 let new_ptr = Self::alloc_impl(new_layout, zeroed)?;
73 ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.cast().as_ptr(), old_size);
74 Self::deallocate(ptr, old_layout);
75 Ok(new_ptr)
76 },
77 }
78 }
79}
80
81unsafe impl SelflessAllocator for TESGlobalAlloc {
82 #[inline]
83 #[cfg_attr(miri, track_caller)] fn allocate(layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
85 Self::alloc_impl(layout, false)
86 }
87
88 #[inline]
89 #[cfg_attr(miri, track_caller)] fn allocate_zeroed(layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
91 Self::alloc_impl(layout, true)
92 }
93
94 #[inline]
95 #[cfg_attr(miri, track_caller)] unsafe fn deallocate(ptr: NonNull<u8>, layout: Layout) {
97 if layout.size() != 0 {
98 unsafe { dealloc(ptr.as_ptr(), layout) }
101 }
102 }
103
104 #[inline]
105 #[cfg_attr(miri, track_caller)] unsafe fn grow(
107 ptr: NonNull<u8>,
108 old_layout: Layout,
109 new_layout: Layout,
110 ) -> Result<NonNull<[u8]>, AllocError> {
111 unsafe { Self::grow_impl(ptr, old_layout, new_layout, false) }
113 }
114
115 #[inline]
116 #[cfg_attr(miri, track_caller)] unsafe fn grow_zeroed(
118 ptr: NonNull<u8>,
119 old_layout: Layout,
120 new_layout: Layout,
121 ) -> Result<NonNull<[u8]>, AllocError> {
122 unsafe { Self::grow_impl(ptr, old_layout, new_layout, true) }
124 }
125
126 #[inline]
127 #[cfg_attr(miri, track_caller)] unsafe fn shrink(
129 ptr: NonNull<u8>,
130 old_layout: Layout,
131 new_layout: Layout,
132 ) -> Result<NonNull<[u8]>, AllocError> {
133 debug_assert!(
134 new_layout.size() <= old_layout.size(),
135 "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
136 );
137
138 match new_layout.size() {
139 0 => {
141 unsafe { Self::deallocate(ptr, old_layout) };
142 Ok(non_null_empty_slice(new_layout))
143 }
144
145 new_size if old_layout.align() == new_layout.align() => unsafe {
147 hint::assert_unchecked(new_size <= old_layout.size());
149
150 let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size);
151 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
152 Ok(NonNull::slice_from_raw_parts(ptr, new_size))
153 },
154
155 new_size => unsafe {
161 let new_ptr = Self::allocate(new_layout)?;
162 ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.cast().as_ptr(), new_size);
163 Self::deallocate(ptr, old_layout);
164 Ok(new_ptr)
165 },
166 }
167 }
168}