summaryrefslogtreecommitdiff
path: root/Runtime/Allocator/UnityDefaultAllocator.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-14 22:50:43 +0800
committerchai <chaifix@163.com>2019-08-14 22:50:43 +0800
commit15740faf9fe9fe4be08965098bbf2947e096aeeb (patch)
treea730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Allocator/UnityDefaultAllocator.cpp
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Allocator/UnityDefaultAllocator.cpp')
-rw-r--r--Runtime/Allocator/UnityDefaultAllocator.cpp284
1 files changed, 284 insertions, 0 deletions
diff --git a/Runtime/Allocator/UnityDefaultAllocator.cpp b/Runtime/Allocator/UnityDefaultAllocator.cpp
new file mode 100644
index 0000000..a2ec30c
--- /dev/null
+++ b/Runtime/Allocator/UnityDefaultAllocator.cpp
@@ -0,0 +1,284 @@
+#include "UnityPrefix.h"
+#include "UnityDefaultAllocator.h"
+
+#if ENABLE_MEMORY_MANAGER
+
+#include "Runtime/Allocator/AllocationHeader.h"
+#include "Runtime/Profiler/MemoryProfiler.h"
+#include "Runtime/Utilities/BitUtility.h"
+#include "Runtime/Allocator/MemoryManager.h"
+
+template<class LLAlloctor>
+UnityDefaultAllocator<LLAlloctor>::UnityDefaultAllocator(const char* name)
+: BaseAllocator(name)
+{
+ memset(m_PageAllocationList,0,sizeof(m_PageAllocationList));
+}
+
+template<class LLAlloctor>
+void* UnityDefaultAllocator<LLAlloctor>::Allocate (size_t size, int align)
+{
+ size_t realSize = AllocationHeader::CalculateNeededAllocationSize(size, align);
+ void* rawPtr = LLAlloctor::Malloc( realSize );
+ if(rawPtr == NULL)
+ return NULL;
+
+ void* realPtr = AddHeaderAndFooter(rawPtr, size, align);
+ RegisterAllocation(realPtr);
+
+ return realPtr;
+}
+
+template<class LLAlloctor>
+void* UnityDefaultAllocator<LLAlloctor>::Reallocate( void* p, size_t size, int align)
+{
+ if (p == NULL)
+ return Allocate(size, align);
+
+ AllocationHeader::ValidateIntegrity(p, m_AllocatorIdentifier, align);
+ RegisterDeallocation(p);
+
+ size_t oldSize = GetPtrSize(p);
+ size_t oldPadCount = AllocationHeader::GetHeader(p)->GetPadding();
+
+ void* realPtr = AllocationHeader::GetRealPointer(p);
+ size_t realSize = AllocationHeader::CalculateNeededAllocationSize(size, align);
+ char* rawPtr = (char*)LLAlloctor::Realloc(realPtr, realSize);
+ if(rawPtr == NULL)
+ return NULL;
+
+ int newPadCount = AllocationHeader::GetRequiredPadding(rawPtr, align);
+
+ if (newPadCount != oldPadCount){
+ // new ptr needs different align padding. move memory and repad
+ char* srcptr = rawPtr + AllocationHeader::GetHeaderSize() + oldPadCount;
+ char* dstptr = rawPtr + AllocationHeader::GetHeaderSize() + newPadCount;
+ memmove(dstptr, srcptr, ( oldSize < size ? oldSize : size ) );
+ }
+
+ void* newptr = AddHeaderAndFooter(rawPtr, size, align);
+ RegisterAllocation(newptr);
+
+ return newptr;
+}
+
+template<class LLAlloctor>
+void UnityDefaultAllocator<LLAlloctor>::Deallocate (void* p)
+{
+ if (p == NULL)
+ return;
+
+ AllocationHeader::ValidateIntegrity(p, m_AllocatorIdentifier);
+ RegisterDeallocation(p);
+
+ void* realpointer = AllocationHeader::GetRealPointer(p);
+
+ LLAlloctor::Free(realpointer);
+}
+
+template<class LLAlloctor>
+template<RequestType requestType>
+bool UnityDefaultAllocator<LLAlloctor>::AllocationPage(const void* p){
+
+ // A memory and performance optimization could be to register lone pointers in the array instead of setting the bit.
+ // when multiple pointers arrive, pull the pointer out, register it, and register the next. Requires some bookkeeping.
+ // bottom 2 bits of the pointer can be used for flags.
+ int pageAllocationListIndex = 0;
+ UInt32 val = (UInt32)p;
+
+ if(sizeof(void*) > sizeof(UInt32))
+ {
+ Assert(sizeof(void*) == sizeof(UInt64));
+ UInt32 highbits = (UInt32)((UInt64)(uintptr_t)(p) >> 32);
+ if(highbits != 0)
+ {
+ pageAllocationListIndex = -1;
+ for(int i = 0; i < kNumPageAllocationBlocks; i++)
+ if(m_PageAllocationList[i].m_HighBits == highbits)
+ pageAllocationListIndex = i;
+
+ if(pageAllocationListIndex == -1)
+ {
+ // highbits not found in the list. find a free list element
+ for(int i = 0; i < kNumPageAllocationBlocks; i++)
+ {
+ if(m_PageAllocationList[i].m_PageAllocations == NULL)
+ {
+ m_PageAllocationList[i].m_HighBits = highbits;
+ pageAllocationListIndex = i;
+ break;
+ }
+ }
+ if(requestType == kTest)
+ {
+ return false;
+ }
+ else
+ {
+ if(pageAllocationListIndex == -1)
+ ErrorString("Using memoryadresses from more that 16GB of memory");
+ }
+ }
+ }
+ }
+
+ int ****& pageAllocations = m_PageAllocationList[pageAllocationListIndex].m_PageAllocations;
+ int page1 = (val >> (32-kPage1Bits)) & ((1<<kPage1Bits)-1);
+ int page2 = (val >> (32-kPage1Bits-kPage2Bits)) & ((1<<kPage2Bits)-1);
+ int page3 = (val >> (32-kPage1Bits-kPage2Bits-kPage3Bits)) & ((1<<kPage3Bits)-1);
+ int page4 = (val >> (32-kPage1Bits-kPage2Bits-kPage3Bits-kPage4Bits)) & ((1<<kPage4Bits)-1);
+ int bitindex = (val >> kTargetBitsRepresentedPerBit) & 0x1F;
+
+ if(requestType == kUnregister){
+ Assert(pageAllocations != NULL);
+ Assert(pageAllocations[page1] != NULL);
+ Assert(pageAllocations[page1][page2] != NULL);
+ Assert(pageAllocations[page1][page2][page3] != NULL);
+
+ pageAllocations[page1][page2][page3][page4] &= ~(1<<bitindex);
+ if(--pageAllocations[page1][page2][page3][(1<<kPage4Bits)] == 0)
+ {
+ m_BookKeepingMemoryUsage -= ((1<<kPage4Bits)+1)*sizeof(int*);
+ MemoryManager::LowLevelFree (pageAllocations[page1][page2][page3]);
+ pageAllocations[page1][page2][page3] = NULL;
+ }
+ if(--pageAllocations[page1][page2][(1<<kPage3Bits)] == 0)
+ {
+ m_BookKeepingMemoryUsage -= ((1<<kPage3Bits)+1)*sizeof(int**);
+ MemoryManager::LowLevelFree (pageAllocations[page1][page2]);
+ pageAllocations[page1][page2] = NULL;
+ }
+ if(--pageAllocations[page1][(1<<kPage2Bits)] == 0)
+ {
+ m_BookKeepingMemoryUsage -= ((1<<kPage2Bits)+1)*sizeof(int***);
+ MemoryManager::LowLevelFree (pageAllocations[page1]);
+ pageAllocations[page1] = NULL;
+ }
+ if(--pageAllocations[(1<<kPage1Bits)] == 0)
+ {
+ m_BookKeepingMemoryUsage -= ((1<<kPage1Bits)+1)*sizeof(int***);
+ MemoryManager::LowLevelFree (pageAllocations);
+ pageAllocations = NULL;
+ }
+ return true;
+ }
+
+ if(pageAllocations == NULL)
+ {
+ if(requestType == kRegister)
+ {
+ pageAllocations = (int****)MemoryManager::LowLevelCAllocate((1<<kPage1Bits)+1,sizeof(int****));
+ m_BookKeepingMemoryUsage += ((1<<kPage1Bits)+1)*sizeof(int****);
+ pageAllocations[(1<<kPage1Bits)] = 0;
+ }
+ else
+ return false;
+ }
+ if(pageAllocations[page1] == NULL)
+ {
+ if(requestType == kRegister)
+ {
+ pageAllocations[page1] = (int***)MemoryManager::LowLevelCAllocate((1<<kPage2Bits)+1,sizeof(int***));
+ m_BookKeepingMemoryUsage += ((1<<kPage2Bits)+1)*sizeof(int***);
+ pageAllocations[page1][(1<<kPage2Bits)] = 0;
+ }
+ else
+ return false;
+ }
+ if(pageAllocations[page1][page2] == NULL)
+ {
+ if(requestType == kRegister)
+ {
+ pageAllocations[page1][page2] = (int**)MemoryManager::LowLevelCAllocate((1<<kPage3Bits)+1,sizeof(int**));
+ m_BookKeepingMemoryUsage += ((1<<kPage3Bits)+1)*sizeof(int**);
+ pageAllocations[page1][page2][(1<<kPage3Bits)] = 0;
+ }
+ else
+ return false;
+ }
+ if(pageAllocations[page1][page2][page3] == NULL)
+ {
+ if(requestType == kRegister)
+ {
+ pageAllocations[page1][page2][page3] = (int*)MemoryManager::LowLevelCAllocate((1<<kPage4Bits)+1,sizeof(int*));
+ m_BookKeepingMemoryUsage += ((1<<kPage4Bits)+1)*sizeof(int*);
+ pageAllocations[page1][page2][page3][(1<<kPage4Bits)] = 0;
+ }
+ else
+ return false;
+ }
+ if(requestType == kTest)
+ return (pageAllocations[page1][page2][page3][page4] & (1<<bitindex)) != 0;
+ pageAllocations[page1][page2][page3][(1<<kPage4Bits)]++;
+ pageAllocations[page1][page2][(1<<kPage3Bits)]++;
+ pageAllocations[page1][(1<<kPage2Bits)]++;
+ pageAllocations[(1<<kPage1Bits)]++;
+ Assert((pageAllocations[page1][page2][page3][page4] & (1<<bitindex)) == 0); // the bit for this pointer should not be set yet
+ pageAllocations[page1][page2][page3][page4] |= (1<<bitindex);
+ return true;
+
+}
+
+template<class LLAlloctor>
+void* UnityDefaultAllocator<LLAlloctor>::AddHeaderAndFooter( void* ptr, size_t size, int align ) const
+{
+ Assert(align >= kDefaultMemoryAlignment && align <= 16*1024 && IsPowerOfTwo(align));
+ // calculate required padding for ptr to be aligned after header addition
+ // ppppppppHHHH***********
+ int padCount = AllocationHeader::GetRequiredPadding(ptr, align);
+ void* realPtr = ((char*)ptr) + (padCount + AllocationHeader::GetHeaderSize());
+ AllocationHeader::Set(realPtr, m_AllocatorIdentifier, size, padCount, align);
+ return realPtr;
+}
+
+template<class LLAlloctor>
+void UnityDefaultAllocator<LLAlloctor>::RegisterAllocation( const void* p )
+{
+ Mutex::AutoLock lock(m_AllocLock);
+ const size_t ptrSize = GetPtrSize(p);
+ const int overheadSize = AllocationHeader::GetHeader(p)->GetOverheadSize();
+ RegisterAllocationData(ptrSize, overheadSize);
+ m_TotalReservedMemory += ptrSize + overheadSize;
+ AllocationPage<kRegister>(p);
+}
+
+template<class LLAlloctor>
+void UnityDefaultAllocator<LLAlloctor>::RegisterDeallocation( const void* p )
+{
+ Mutex::AutoLock lock(m_AllocLock);
+ const size_t ptrSize = GetPtrSize(p);
+ const int overheadSize = AllocationHeader::GetHeader(p)->GetOverheadSize();
+ RegisterDeallocationData(ptrSize, overheadSize);
+ m_TotalReservedMemory -= ptrSize + overheadSize;
+ AllocationPage<kUnregister>(p);
+}
+
+template<class LLAlloctor>
+bool UnityDefaultAllocator<LLAlloctor>::Contains (const void* p)
+{
+ Mutex::AutoLock lock(m_AllocLock);
+ return AllocationPage<kTest>(p);
+}
+
+template<class LLAlloctor>
+size_t UnityDefaultAllocator<LLAlloctor>::GetPtrSize( const void* ptr ) const
+{
+ return AllocationHeader::GetHeader(ptr)->GetRequestedSize();
+}
+
+template<class LLAlloctor>
+ProfilerAllocationHeader* UnityDefaultAllocator<LLAlloctor>::GetProfilerHeader(const void* ptr) const
+{
+ // LocalHeader:ProfilerHeader:Data
+ return AllocationHeader::GetProfilerHeader(ptr);
+}
+
+template<class LLAlloctor>
+int UnityDefaultAllocator<LLAlloctor>::GetOverheadSize(void* ptr)
+{
+ return AllocationHeader::GetHeader(ptr)->GetOverheadSize();
+}
+
+template class UnityDefaultAllocator<LowLevelAllocator>;
+
+#endif