feat(objectalloc): update ObjectAlloc methods to support freeing of memory

This commit is contained in:
VDm 2025-08-20 00:50:31 +04:00
parent ab0b7965db
commit 94dcf8ca77
6 changed files with 81 additions and 12 deletions

View file

@ -32,7 +32,7 @@ int32_t ObjectAlloc(uint32_t heapId, uint32_t* memHandle, void** objectPtr, bool
return 0;
}
uint32_t ObjectAllocAddHeap(uint32_t objectSize, uint32_t objsPerBlock, const char* name, bool a4) {
uint32_t ObjectAllocAddHeap(uint32_t objectSize, uint32_t objsPerBlock, const char* name, bool freeEmptyHeaps) {
STORM_ASSERT(objectSize > 0);
auto globals = GetObjAllocGlobals();
@ -43,7 +43,7 @@ uint32_t ObjectAllocAddHeap(uint32_t objectSize, uint32_t objsPerBlock, const ch
heap->m_objSize = objectSize;
heap->m_objsPerBlock = objsPerBlock;
SStrCopy(heap->m_heapName, name, sizeof(heap->m_heapName));
heap->char84 = a4;
heap->m_freeEmptyHeaps = freeEmptyHeaps;
ReleaseObjAllocGlobals();
@ -61,3 +61,10 @@ uint32_t ObjectAllocUsage(uint32_t heapId) {
return result;
}
void ObjectAllocDestroy() {
// NOTICE: It seems like sub_4D2F90 does nothing useful
auto globals = GetObjAllocGlobals();
globals->objects.Clear();
ReleaseObjAllocGlobals();
}

View file

@ -5,8 +5,10 @@
int32_t ObjectAlloc(uint32_t heapId, uint32_t* memHandle, void** objectPtr, bool zero);
uint32_t ObjectAllocAddHeap(uint32_t objectSize, uint32_t objsPerBlock, const char* name, bool a4);
uint32_t ObjectAllocAddHeap(uint32_t objectSize, uint32_t objsPerBlock, const char* name, bool freeEmptyHeaps);
uint32_t ObjectAllocUsage(uint32_t heapId);
void ObjectAllocDestroy();
#endif

View file

@ -17,7 +17,6 @@ int32_t CObjectHeap::Allocate(uint32_t objSize, uint32_t heapObjects, const char
void* indexStack = static_cast<char*>(this->m_obj) + heapObjects * objSize;
this->m_indexStack = reinterpret_cast<uint32_t*>(indexStack);
this->m_bytes = heapObjects * objSize;
for (int32_t i = 0; i < heapObjects; i++) {
this->m_indexStack[i] = i;
@ -90,11 +89,6 @@ void* CObjectHeap::Ptr(uint32_t index, uint32_t objSize, uint32_t heapObjects) {
bytes[3]);
}
if (objSize * index >= this->m_bytes) {
SErrPrepareAppFatal(__FILE__, __LINE__);
SErrDisplayAppFatal("CObjectHeap::Ptr(): index(%u), objSize(%u), m_bytes(%u)", index, objSize, this->m_bytes);
}
return static_cast<char*>(this->m_obj) + objSize * index;
}

View file

@ -9,7 +9,6 @@ class CObjectHeap {
void* m_obj = nullptr;
uint32_t* m_indexStack = nullptr;
uint32_t m_allocated = 0;
uint32_t m_bytes = 0;
// Member functions
CObjectHeap() = default;

View file

@ -50,6 +50,71 @@ int32_t CObjectHeapList::New(uint32_t* index, void** obj, bool zero) {
return 1;
}
void CObjectHeapList::Delete(uint32_t index) {
uint32_t heapId = index / this->m_objsPerBlock;
uint32_t stackId = index % this->m_objsPerBlock;
auto& heap = this->m_heaps[heapId];
if (heap.m_allocated == this->m_objsPerBlock) {
this->m_numFullHeaps--;
}
heap.Delete(stackId, this->m_objSize, this->m_objsPerBlock);
if (this->m_freeEmptyHeaps) {
if (heap.m_obj && !heap.m_allocated) {
this->m_hasEmptyHeaps = 1;
}
if (this->m_hasEmptyHeaps) {
bool freeHeaps = (((this->m_objsPerBlock - 1) >> 2) & this->uint20) == 0;
this->uint20++;
if (freeHeaps) {
FreeEmptyHeaps();
}
}
}
}
void CObjectHeapList::FreeEmptyHeaps() {
if (!this->m_heaps.Count()) {
this->m_hasEmptyHeaps = 0;
return;
}
uint32_t totalAllocated = 0;
uint32_t totalObjsPerBlock = 0;
uint32_t totalEmptyHeaps = 0;
for (uint32_t i = 0; i < this->m_heaps.Count(); ++i) {
auto& heap = this->m_heaps[i];
if (heap.m_obj) {
totalObjsPerBlock += this->m_objsPerBlock;
if (heap.m_allocated) {
totalAllocated += heap.m_allocated;
} else {
totalEmptyHeaps++;
}
}
}
if (!totalEmptyHeaps) {
this->m_hasEmptyHeaps = 0;
return;
}
totalAllocated += ((3 * this->m_objsPerBlock) >> 1);
uint32_t count = this->m_heaps.Count();
while (count > 0 && totalAllocated < totalObjsPerBlock && !totalEmptyHeaps) {
// TODO: Remove last element from this->m_heaps
count--;
}
this->m_hasEmptyHeaps = totalEmptyHeaps != 0;
}
uint32_t CObjectHeapList::BlocksAllocated() {
uint32_t result = 0;
for (uint32_t i = 0; i < this->m_heaps.Count(); ++i) {

View file

@ -11,17 +11,19 @@ class CObjectHeapList {
uint32_t m_objSize = 0;
uint32_t m_objsPerBlock = 128;
uint32_t m_numFullHeaps = 0;
uint32_t uint1C = 0;
uint32_t m_hasEmptyHeaps = 0;
uint32_t uint20 = 0;
uint32_t m_fullestHeap = 0;
char m_heapName[80];
uint32_t uint78 = 0;
uint32_t uint7C = 0;
uint32_t uint80 = 0;
uint8_t char84 = 1;
uint8_t m_freeEmptyHeaps = 1;
// Member functions
int32_t New(uint32_t* index, void** obj, bool zero);
void Delete(uint32_t index);
void FreeEmptyHeaps();
uint32_t BlocksAllocated();
};