diff --git a/common/ObjectAlloc.cpp b/common/ObjectAlloc.cpp index 2574abc..08f39e6 100644 --- a/common/ObjectAlloc.cpp +++ b/common/ObjectAlloc.cpp @@ -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(); +} diff --git a/common/ObjectAlloc.hpp b/common/ObjectAlloc.hpp index 5401739..22a3552 100644 --- a/common/ObjectAlloc.hpp +++ b/common/ObjectAlloc.hpp @@ -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 diff --git a/common/objectalloc/CObjectHeap.cpp b/common/objectalloc/CObjectHeap.cpp index f02dc3c..e8bf9ab 100644 --- a/common/objectalloc/CObjectHeap.cpp +++ b/common/objectalloc/CObjectHeap.cpp @@ -17,7 +17,6 @@ int32_t CObjectHeap::Allocate(uint32_t objSize, uint32_t heapObjects, const char void* indexStack = static_cast(this->m_obj) + heapObjects * objSize; this->m_indexStack = reinterpret_cast(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(this->m_obj) + objSize * index; } diff --git a/common/objectalloc/CObjectHeap.hpp b/common/objectalloc/CObjectHeap.hpp index 31d0185..b4b9486 100644 --- a/common/objectalloc/CObjectHeap.hpp +++ b/common/objectalloc/CObjectHeap.hpp @@ -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; diff --git a/common/objectalloc/CObjectHeapList.cpp b/common/objectalloc/CObjectHeapList.cpp index d7c416a..5cb7b70 100644 --- a/common/objectalloc/CObjectHeapList.cpp +++ b/common/objectalloc/CObjectHeapList.cpp @@ -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) { diff --git a/common/objectalloc/CObjectHeapList.hpp b/common/objectalloc/CObjectHeapList.hpp index 49e2a29..c05bd3e 100644 --- a/common/objectalloc/CObjectHeapList.hpp +++ b/common/objectalloc/CObjectHeapList.hpp @@ -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(); };