A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
Heap.cc
1#include "egg/core/ExpHeap.hh"
2
3using namespace Kinoko;
4using namespace Abstract::Memory;
5
6namespace Kinoko::EGG {
7
9Heap::Heap(MEMiHeapHead *handle) : m_handle(handle), m_children(Disposer::getLinkOffset()) {
10 m_block = nullptr;
11 m_parentHeap = nullptr;
12 m_name = "NoName";
13 m_flags.makeAllZero();
14
15 s_heapList.append(this);
16}
17
19Heap::~Heap() {
20 s_heapList.remove(this);
21}
22
24void Heap::dispose() {
25 Disposer *node = nullptr;
26 while ((node = reinterpret_cast<Disposer *>(m_children.getFirst()))) {
27 node->~Disposer();
28 }
29
30 ASSERT(!m_children.m_headObject && !m_children.m_tailObject);
31}
32
33Heap *Heap::becomeAllocatableHeap() {
34 Heap *oldHeap = s_allocatableHeap;
35 s_allocatableHeap = this;
36 return oldHeap;
37}
38
40Heap *Heap::becomeCurrentHeap() {
41 Heap *oldHeap = s_currentHeap;
42 s_currentHeap = this;
43 return oldHeap;
44}
45
47void *Heap::alloc(size_t size, int align, Heap *pHeap) {
48 Heap *currentHeap = s_currentHeap;
49
50 if (s_allocatableHeap) {
51 if (currentHeap && !pHeap) {
52 pHeap = currentHeap;
53 }
54
55 if (pHeap != s_allocatableHeap) {
56 WARN("HEAP ALLOC FAIL (%p, %s): Allocatable heap is %p (%s)", pHeap, pHeap->getName(),
57 s_allocatableHeap, s_allocatableHeap->getName());
58
59 return nullptr;
60 }
61 }
62
63 if (pHeap) {
64 return pHeap->alloc(size, align);
65 }
66
67 if (currentHeap) {
68 void *block = currentHeap->alloc(size, align);
69
70 if (!block) {
71 u32 heapFreeSize = currentHeap->getAllocatableSize(0x4);
72 s32 heapSize = GetAddrNum(currentHeap->getEndAddress()) -
73 GetAddrNum(currentHeap->getStartAddress());
74
75 constexpr f32 BYTES_TO_MBYTES = 1024.0f * 1024.0f;
76 f32 heapSizeMB = static_cast<f32>(heapSize) / BYTES_TO_MBYTES;
77 f32 heapFreeSizeMB = static_cast<f32>(heapFreeSize) / BYTES_TO_MBYTES;
78 f32 sizeMB = static_cast<f32>(size) / BYTES_TO_MBYTES;
79
80 WARN("HEAP ALLOC FAIL (%p, %s):\nTotal bytes: %d (%.1fMBytes)\nFree bytes: %d "
81 "(%.1fMBytes)\nAlloc bytes: %zu "
82 "(%.1fMBytes)\nAlign: %d",
83 currentHeap, currentHeap->getName(), heapSize, static_cast<f64>(heapSizeMB),
84 heapFreeSize, static_cast<f64>(heapFreeSizeMB), size, static_cast<f64>(sizeMB),
85 align);
86 }
87
88 return block;
89 }
90
91 WARN("HEAP ALLOC FAIL: Cannot allocate %zu from heap %p", size, pHeap);
92 return nullptr;
93}
94
96void Heap::free(void *block, Heap *pHeap) {
97 // Deleting nullptr should be no-op
98 if (!block) {
99 return;
100 }
101
102 if (!pHeap) {
103 MEMiHeapHead *handle = MEMiHeapHead::findContainHeap(block);
104 if (!handle) {
105 return;
106 }
107
108 pHeap = findHeap(handle);
109 if (!pHeap) {
110 return;
111 }
112 }
113
114 pHeap->free(block);
115}
116
117Heap *Heap::findHeap(MEMiHeapHead *handle) {
118 Heap *node = nullptr;
119 while ((node = reinterpret_cast<Heap *>(s_heapList.getNext(node)))) {
120 if (node->m_handle == handle) {
121 return node;
122 }
123 }
124
125 return nullptr;
126}
127
129Heap *Heap::findContainHeap(const void *block) {
130 MEMiHeapHead *handle = MEMiHeapHead::findContainHeap(block);
131 return handle ? findHeap(handle) : nullptr;
132}
133
134} // namespace Kinoko::EGG
135
137void *operator new(size_t size) {
138 return EGG::Heap::alloc(size, 4, nullptr);
139}
140
142void *operator new(size_t size, int align) {
143 return EGG::Heap::alloc(size, align, nullptr);
144}
145
147void *operator new(size_t size, EGG::Heap *heap, int align) {
148 return EGG::Heap::alloc(size, align, heap);
149}
150
152void *operator new[](size_t size) {
153 return EGG::Heap::alloc(size, 4, nullptr);
154}
155
157void *operator new[](size_t size, int align) {
158 return EGG::Heap::alloc(size, align, nullptr);
159}
160
162void *operator new[](size_t size, EGG::Heap *heap, int align) {
163 return EGG::Heap::alloc(size, align, heap);
164}
165
167void operator delete(void *block) noexcept {
168 EGG::Heap::free(block, nullptr);
169}
170
171void operator delete(void *block, size_t /* size */) noexcept {
172 EGG::Heap::free(block, nullptr);
173}
174
176void operator delete[](void *block) noexcept {
177 EGG::Heap::free(block, nullptr);
178}
179
180void operator delete[](void *block, size_t /* size */) noexcept {
181 EGG::Heap::free(block, nullptr);
182}
183
184MEMList EGG::Heap::s_heapList = MEMList(EGG::Heap::getOffset());
185
186EGG::Heap *EGG::Heap::s_currentHeap = nullptr;
187EGG::Heap *EGG::Heap::s_allocatableHeap = nullptr;
A low-level representation of a memory heap for managing dynamic memory allocation....
Definition HeapCommon.hh:21
A high-level representation of a memory heap for managing dynamic memory allocation....
Definition Heap.hh:24
EGG core library.
Definition Archive.cc:6
Intrusive doubly-linked list. Links are placed within the corresponding object.
Definition List.hh:14