CommonLibSSE (Parapets fork)
Loading...
Searching...
No Matches
MemoryManager.h
Go to the documentation of this file.
1#pragma once
2
3#include "RE/S/ScrapHeap.h"
4
5namespace RE
6{
7 namespace CompactingStore
8 {
9 class Store;
10 }
11
12 class BSSmallBlockAllocator;
13 class IMemoryHeap;
14
16 {
17 public:
19 {
20 public:
21 // members
24 std::uint32_t owningThread; // 98
25 std::uint32_t pad; // 9C
26 };
27 static_assert(sizeof(ThreadScrapHeap) == 0xA0);
28
29 [[nodiscard]] static MemoryManager* GetSingleton()
30 {
31 using func_t = decltype(&MemoryManager::GetSingleton);
33 return func();
34 }
35
36 [[nodiscard]] void* Allocate(std::size_t a_size, std::int32_t a_alignment, bool a_alignmentRequired)
37 {
38 using func_t = decltype(&MemoryManager::Allocate);
40 return func(this, a_size, a_alignment, a_alignmentRequired);
41 }
42
43 void Deallocate(void* a_mem, bool a_alignmentRequired)
44 {
45 using func_t = decltype(&MemoryManager::Deallocate);
47 return func(this, a_mem, a_alignmentRequired);
48 }
49
51 {
52 using func_t = decltype(&MemoryManager::GetThreadScrapHeap);
54 return func(this);
55 }
56
57 [[nodiscard]] void* Reallocate(void* a_oldMem, std::size_t a_newSize, std::int32_t a_alignment, bool a_aligned)
58 {
59 using func_t = decltype(&MemoryManager::Reallocate);
61 return func(this, a_oldMem, a_newSize, a_alignment, a_aligned);
62 }
63
65 {
66 using func_t = decltype(&MemoryManager::RegisterMemoryManager);
68 return func(this);
69 }
70
71 // members
72 bool initialized{ false }; // 000
73 std::uint16_t numHeaps{ 0 }; // 002
74 std::uint16_t numPhysicalHeaps{ 0 }; // 004
75 IMemoryHeap** heaps{ nullptr }; // 008
76 bool* allowOtherContextAllocs{ nullptr }; // 010
77 IMemoryHeap* heapsByContext[127]{ nullptr }; // 018
78 ThreadScrapHeap* threadScrapHeap{ nullptr }; // 410
79 IMemoryHeap** physicalHeaps{ nullptr }; // 418
80 IMemoryHeap* bigAllocHeap{ nullptr }; // 420
81 IMemoryHeap* emergencyHeap{ nullptr }; // 428
85 bool specialHeaps{ false }; // 448
86 bool allowPoolUse{ true }; // 449
87 std::uint32_t sysAllocBytes{ 0 }; // 44C
88 std::uint32_t mallocBytes{ 0 }; // 450
89 std::uint32_t alignmentForPools{ 4 }; // 450
90 std::uint32_t mainThreadMemoryProblemPassSignal{ 0 }; // 458
91 std::size_t failedAllocationSize{ 0 }; // 460
92 std::uint32_t numMemoryProblemPassesRun{ 0 }; // 468
93 std::size_t timeOfLastMemoryProblemPass{ 0 }; // 470
94 IMemoryHeap* defaultHeap{ nullptr }; // 478
95 };
96 static_assert(sizeof(MemoryManager) == 0x480);
97
98 inline void* malloc(std::size_t a_size)
99 {
100 auto heap = MemoryManager::GetSingleton();
101 return heap ?
102 heap->Allocate(a_size, 0, false) :
103 nullptr;
104 }
105
106 template <class T>
107 inline T* malloc(std::size_t a_size)
108 {
109 return static_cast<T*>(malloc(a_size));
110 }
111
112 template <class T>
113 inline T* malloc()
114 {
115 return malloc<T>(sizeof(T));
116 }
117
118 inline void* aligned_alloc(std::size_t a_alignment, std::size_t a_size)
119 {
120 auto heap = MemoryManager::GetSingleton();
121 return heap ?
122 heap->Allocate(a_size, static_cast<std::int32_t>(a_alignment), true) :
123 nullptr;
124 }
125
126 template <class T>
127 inline T* aligned_alloc(std::size_t a_alignment, std::size_t a_size)
128 {
129 return static_cast<T*>(aligned_alloc(a_alignment, a_size));
130 }
131
132 template <class T>
133 inline T* aligned_alloc()
134 {
135 return aligned_alloc<T>(alignof(T), sizeof(T));
136 }
137
138 inline void* calloc(std::size_t a_num, std::size_t a_size)
139 {
140 return malloc(a_num * a_size);
141 }
142
143 template <class T>
144 inline T* calloc(std::size_t a_num, std::size_t a_size)
145 {
146 return static_cast<T*>(calloc(a_num, a_size));
147 }
148
149 template <class T>
150 inline T* calloc(std::size_t a_num)
151 {
152 return calloc<T>(a_num, sizeof(T));
153 }
154
155 inline void* realloc(void* a_ptr, std::size_t a_newSize)
156 {
157 auto heap = MemoryManager::GetSingleton();
158 return heap ?
159 heap->Reallocate(a_ptr, a_newSize, 0, false) :
160 nullptr;
161 }
162
163 template <class T>
164 inline T* realloc(void* a_ptr, std::size_t a_newSize)
165 {
166 return static_cast<T*>(realloc(a_ptr, a_newSize));
167 }
168
169 inline void* aligned_realloc(void* a_ptr, std::size_t a_newSize, std::size_t a_alignment)
170 {
171 auto heap = MemoryManager::GetSingleton();
172 return heap ?
173 heap->Reallocate(a_ptr, a_newSize, static_cast<std::int32_t>(a_alignment), true) :
174 nullptr;
175 }
176
177 template <class T>
178 inline T* aligned_realloc(void* a_ptr, std::size_t a_newSize, std::size_t a_alignment)
179 {
180 return static_cast<T*>(aligned_realloc(a_ptr, a_newSize, a_alignment));
181 }
182
183 inline void free(void* a_ptr)
184 {
185 auto heap = MemoryManager::GetSingleton();
186 if (heap) {
187 heap->Deallocate(a_ptr, false);
188 }
189 }
190
191 inline void aligned_free(void* a_ptr)
192 {
193 auto heap = MemoryManager::GetSingleton();
194 if (heap) {
195 heap->Deallocate(a_ptr, true);
196 }
197 }
198}
199
200#define TES_HEAP_REDEFINE_NEW() \
201 [[nodiscard]] inline void* operator new(std::size_t a_count) \
202 { \
203 const auto mem = RE::malloc(a_count); \
204 if (mem) { \
205 return mem; \
206 } else { \
207 stl::report_and_fail("out of memory"sv); \
208 } \
209 } \
210 \
211 [[nodiscard]] inline void* operator new[](std::size_t a_count) \
212 { \
213 const auto mem = RE::malloc(a_count); \
214 if (mem) { \
215 return mem; \
216 } else { \
217 stl::report_and_fail("out of memory"sv); \
218 } \
219 } \
220 \
221 [[nodiscard]] constexpr void* operator new(std::size_t, void* a_ptr) noexcept { return a_ptr; } \
222 [[nodiscard]] constexpr void* operator new[](std::size_t, void* a_ptr) noexcept { return a_ptr; } \
223 [[nodiscard]] constexpr void* operator new(std::size_t, std::align_val_t, void* a_ptr) noexcept { return a_ptr; } \
224 [[nodiscard]] constexpr void* operator new[](std::size_t, std::align_val_t, void* a_ptr) noexcept { return a_ptr; } \
225 \
226 inline void operator delete(void* a_ptr) { RE::free(a_ptr); } \
227 inline void operator delete[](void* a_ptr) { RE::free(a_ptr); } \
228 inline void operator delete(void* a_ptr, std::align_val_t) { RE::aligned_free(a_ptr); } \
229 inline void operator delete[](void* a_ptr, std::align_val_t) { RE::aligned_free(a_ptr); } \
230 inline void operator delete(void* a_ptr, std::size_t) { RE::free(a_ptr); } \
231 inline void operator delete[](void* a_ptr, std::size_t) { RE::free(a_ptr); } \
232 inline void operator delete(void* a_ptr, std::size_t, std::align_val_t) { RE::aligned_free(a_ptr); } \
233 inline void operator delete[](void* a_ptr, std::size_t, std::align_val_t) { RE::aligned_free(a_ptr); }
234
235namespace RE
236{
237 // this class is an implementation detail of operator new[]/delete[]
238 template <class T>
240 {
241 public:
242 using value_type = T;
243 using size_type = std::size_t;
244 using difference_type = std::ptrdiff_t;
248 using const_pointer = const value_type*;
251
252 constexpr SimpleArray() noexcept = default;
253
254 explicit SimpleArray(size_type a_count) { resize(a_count); }
255
257 {
258 static_assert(!std::is_trivially_destructible_v<value_type>, "there's no allocation overhead for trivially destructible types");
259 clear();
260 }
261
263
264 [[nodiscard]] reference operator[](size_type a_pos) noexcept
265 {
266 assert(a_pos < size());
267 return _data[a_pos];
268 }
269
270 [[nodiscard]] const_reference operator[](size_type a_pos) const noexcept
271 {
272 assert(a_pos < size());
273 return _data[a_pos];
274 }
275
276 [[nodiscard]] reference front() noexcept { return operator[](0); }
277 [[nodiscard]] const_reference front() const noexcept { return operator[](0); }
278
279 [[nodiscard]] reference back() noexcept { return operator[](size() - 1); }
280 [[nodiscard]] const_reference back() const noexcept { return operator[](size() - 1); }
281
282 [[nodiscard]] pointer data() noexcept { return _data; }
283 [[nodiscard]] const_pointer data() const noexcept { return _data; }
284
285 [[nodiscard]] iterator begin() noexcept { return _data; }
286 [[nodiscard]] const_iterator begin() const noexcept { return _data; }
287 [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
288
289 [[nodiscard]] iterator end() noexcept { return _data ? _data + size() : nullptr; }
290 [[nodiscard]] const_iterator end() const noexcept { return _data ? _data + size() : nullptr; }
291 [[nodiscard]] const_iterator cend() const noexcept { return end(); }
292
293 [[nodiscard]] bool empty() const noexcept { return size() == 0; }
294
295 [[nodiscard]] size_type size() const noexcept { return _data ? *static_cast<const std::size_t*>(get_head()) : 0; }
296
297 void clear()
298 {
299 if (_data) {
300 std::destroy_n(data(), size());
301 free(get_head());
302 _data = nullptr;
303 }
304 }
305
306 void resize(size_type a_count)
307 {
308 const auto oldSize = size();
309 if (oldSize == a_count) {
310 return;
311 }
312
313 const auto newData = [=]() {
314 auto bytes = sizeof(value_type) * a_count;
315 if constexpr (alignof(value_type) > alignof(std::size_t)) {
316 bytes += sizeof(value_type);
317 } else {
318 bytes += sizeof(std::size_t);
319 }
320
321 const auto data = malloc<std::size_t>(bytes);
322 *data = a_count;
323
324 if constexpr (alignof(value_type) > alignof(std::size_t)) {
325 return reinterpret_cast<pointer>(data) + 1;
326 } else {
327 return reinterpret_cast<pointer>(data + 1);
328 }
329 }();
330
331 if (a_count < oldSize) { // shrink
332 std::uninitialized_move_n(data(), a_count, newData);
333 } else { // grow
334 std::uninitialized_move_n(data(), oldSize, newData);
335 std::uninitialized_default_construct_n(newData + oldSize, a_count - oldSize);
336 }
337
338 clear();
339 _data = newData;
340 }
341
342 protected:
343 [[nodiscard]] void* get_head() noexcept
344 {
345 assert(_data != nullptr);
346 if constexpr (alignof(value_type) > alignof(std::size_t)) {
347 return _data - 1;
348 } else {
349 return reinterpret_cast<std::size_t*>(_data) - 1;
350 }
351 }
352
353 [[nodiscard]] const void* get_head() const noexcept
354 {
355 assert(_data != nullptr);
356 if constexpr (alignof(value_type) > alignof(std::size_t)) {
357 return _data - 1;
358 } else {
359 return reinterpret_cast<const std::size_t*>(_data) - 1;
360 }
361 }
362
363 // members
364 pointer _data{ nullptr }; // 0
365 };
366}
Definition: BSSmallBlockAllocator.h:61
Definition: CompactingStore.h:15
Definition: IMemoryHeap.h:31
Definition: MemoryManager.h:16
std::uint16_t numHeaps
Definition: MemoryManager.h:73
BSSmallBlockAllocator * smallBlockAllocator
Definition: MemoryManager.h:82
std::uint32_t mallocBytes
Definition: MemoryManager.h:88
IMemoryHeap * defaultHeap
Definition: MemoryManager.h:94
std::uint32_t numMemoryProblemPassesRun
Definition: MemoryManager.h:92
std::uint16_t numPhysicalHeaps
Definition: MemoryManager.h:74
bool specialHeaps
Definition: MemoryManager.h:85
CompactingStore::Store * compactingStore
Definition: MemoryManager.h:83
std::uint32_t alignmentForPools
Definition: MemoryManager.h:89
void Deallocate(void *a_mem, bool a_alignmentRequired)
Definition: MemoryManager.h:43
static MemoryManager * GetSingleton()
Definition: MemoryManager.h:29
std::size_t failedAllocationSize
Definition: MemoryManager.h:91
void * Reallocate(void *a_oldMem, std::size_t a_newSize, std::int32_t a_alignment, bool a_aligned)
Definition: MemoryManager.h:57
ThreadScrapHeap * threadScrapHeap
Definition: MemoryManager.h:78
bool allowPoolUse
Definition: MemoryManager.h:86
std::uint32_t sysAllocBytes
Definition: MemoryManager.h:87
IMemoryHeap ** physicalHeaps
Definition: MemoryManager.h:79
IMemoryHeap ** heaps
Definition: MemoryManager.h:75
IMemoryHeap * bigAllocHeap
Definition: MemoryManager.h:80
ScrapHeap * GetThreadScrapHeap()
Definition: MemoryManager.h:50
std::uint32_t mainThreadMemoryProblemPassSignal
Definition: MemoryManager.h:90
IMemoryHeap * emergencyHeap
Definition: MemoryManager.h:81
std::size_t timeOfLastMemoryProblemPass
Definition: MemoryManager.h:93
void RegisterMemoryManager()
Definition: MemoryManager.h:64
IMemoryHeap * externalHavokAllocator
Definition: MemoryManager.h:84
IMemoryHeap * heapsByContext[127]
Definition: MemoryManager.h:77
bool * allowOtherContextAllocs
Definition: MemoryManager.h:76
bool initialized
Definition: MemoryManager.h:72
void * Allocate(std::size_t a_size, std::int32_t a_alignment, bool a_alignmentRequired)
Definition: MemoryManager.h:36
Definition: ScrapHeap.h:8
Definition: MemoryManager.h:240
const_iterator begin() const noexcept
Definition: MemoryManager.h:286
const_iterator end() const noexcept
Definition: MemoryManager.h:290
size_type size() const noexcept
Definition: MemoryManager.h:295
value_type & reference
Definition: MemoryManager.h:245
std::size_t size_type
Definition: MemoryManager.h:243
T value_type
Definition: MemoryManager.h:242
const_iterator cend() const noexcept
Definition: MemoryManager.h:291
pointer data() noexcept
Definition: MemoryManager.h:282
iterator begin() noexcept
Definition: MemoryManager.h:285
void clear()
Definition: MemoryManager.h:297
pointer _data
Definition: MemoryManager.h:364
iterator end() noexcept
Definition: MemoryManager.h:289
const value_type & const_reference
Definition: MemoryManager.h:246
~SimpleArray()
Definition: MemoryManager.h:256
reference back() noexcept
Definition: MemoryManager.h:279
void * get_head() noexcept
Definition: MemoryManager.h:343
value_type * iterator
Definition: MemoryManager.h:249
reference front() noexcept
Definition: MemoryManager.h:276
void resize(size_type a_count)
Definition: MemoryManager.h:306
value_type * pointer
Definition: MemoryManager.h:247
bool empty() const noexcept
Definition: MemoryManager.h:293
const value_type * const_iterator
Definition: MemoryManager.h:250
constexpr SimpleArray() noexcept=default
const_reference front() const noexcept
Definition: MemoryManager.h:277
const_reference operator[](size_type a_pos) const noexcept
Definition: MemoryManager.h:270
const_pointer data() const noexcept
Definition: MemoryManager.h:283
const_iterator cbegin() const noexcept
Definition: MemoryManager.h:287
const_reference back() const noexcept
Definition: MemoryManager.h:280
std::ptrdiff_t difference_type
Definition: MemoryManager.h:244
const void * get_head() const noexcept
Definition: MemoryManager.h:353
const value_type * const_pointer
Definition: MemoryManager.h:248
reference operator[](size_type a_pos) noexcept
Definition: MemoryManager.h:264
Definition: Relocation.h:858
constexpr REL::ID GetThreadScrapHeap(static_cast< std::uint64_t >(68088))
constexpr REL::ID Reallocate(static_cast< std::uint64_t >(68116))
constexpr REL::ID Allocate(static_cast< std::uint64_t >(68115))
constexpr REL::ID Deallocate(static_cast< std::uint64_t >(68117))
constexpr REL::ID GetSingleton(static_cast< std::uint64_t >(11141))
constexpr REL::ID RegisterMemoryManager(static_cast< std::uint64_t >(36091))
Definition: AbsorbEffect.h:6
void * realloc(void *a_ptr, std::size_t a_newSize)
Definition: MemoryManager.h:155
T * aligned_alloc()
Definition: MemoryManager.h:133
T * malloc()
Definition: MemoryManager.h:113
void * calloc(std::size_t a_num, std::size_t a_size)
Definition: MemoryManager.h:138
void * aligned_realloc(void *a_ptr, std::size_t a_newSize, std::size_t a_alignment)
Definition: MemoryManager.h:169
void free(void *a_ptr)
Definition: MemoryManager.h:183
void aligned_free(void *a_ptr)
Definition: MemoryManager.h:191
Definition: MemoryManager.h:19
ScrapHeap heap
Definition: MemoryManager.h:22
ThreadScrapHeap * next
Definition: MemoryManager.h:23
std::uint32_t owningThread
Definition: MemoryManager.h:24
std::uint32_t pad
Definition: MemoryManager.h:25