allocMemDets.roDataSize = 0;
allocMemDets.xcptnsCount = 0;
allocMemDets.flag = (CorJitAllocMemFlag)0;
- allocMemDets.hotCodeBlock = 0;
- allocMemDets.coldCodeBlock = 0;
- allocMemDets.roDataBlock = 0;
+ allocMemDets.hotCodeBlock = nullptr;
+ allocMemDets.coldCodeBlock = nullptr;
+ allocMemDets.roDataBlock = nullptr;
- allocGCInfoDets.retval = 0;
+ allocGCInfoDets.retval = nullptr;
allocGCInfoDets.size = 0;
+
+ memoryTracker = nullptr;
}
CompileResult::~CompileResult()
{
#define LWM(map, key, value) \
- if (map != nullptr) \
- delete map;
+ delete map;
#include "crlwmlist.h"
- if (CallTargetTypes != nullptr)
- delete CallTargetTypes;
+ delete CallTargetTypes;
+ delete memoryTracker;
}
// Is the CompileResult empty? Define this as whether all the maps that store information given by the JIT are empty.
return isEmpty;
}
+// Allocate memory associated with this CompileResult. Keep track of it in a list so we can free it all later.
+void* CompileResult::allocateMemory(size_t sizeInBytes)
+{
+ if (memoryTracker == nullptr)
+ memoryTracker = new MemoryTracker();
+ return memoryTracker->allocate(sizeInBytes);
+}
+
void CompileResult::recAssert(const char* assertText)
{
if (AssertLog == nullptr)
#include "runtimedetails.h"
#include "lightweightmap.h"
+// MemoryTracker: a very simple allocator and tracker of allocated memory, so it can be deleted when needed.
+class MemoryTracker
+{
+public:
+ MemoryTracker() : m_pHead(nullptr) {}
+ ~MemoryTracker() { freeAll(); }
+
+ void* allocate(size_t sizeInBytes)
+ {
+ BYTE* pNew = new BYTE[sizeInBytes];
+ m_pHead = new MemoryNode(pNew, m_pHead); // Prepend this new one to the tracked memory list.
+ return pNew;
+ }
+
+private:
+
+ MemoryTracker(const MemoryTracker&) = delete; // no copy ctor
+
+ void freeAll()
+ {
+ for (MemoryNode* p = m_pHead; p != nullptr; )
+ {
+ MemoryNode* pNext = p->m_pNext;
+ delete p;
+ p = pNext;
+ }
+ m_pHead = nullptr;
+ }
+
+ struct MemoryNode
+ {
+ MemoryNode(BYTE* pMem, MemoryNode* pNext) : m_pMem(pMem), m_pNext(pNext) {}
+ ~MemoryNode() { delete[] m_pMem; }
+
+ BYTE* m_pMem;
+ MemoryNode* m_pNext;
+ };
+
+ MemoryNode* m_pHead;
+};
+
class CompileResult
{
public:
void dumpToConsole();
+ void* allocateMemory(size_t sizeInBytes);
+
void recAssert(const char* buff);
void dmpAssertLog(DWORD key, DWORD value);
const char* repAssert();
LightWeightMap<DWORDLONG, DWORD>* CallTargetTypes;
private:
+ MemoryTracker* memoryTracker;
Capture_AllocMemDetails allocMemDets;
allocGCInfoDetails allocGCInfoDets;
};
{
jitInstance->mc->cr->AddCall("allocMem");
// TODO-Cleanup: investigate if we need to check roDataBlock as well. Could hot block size be ever 0?
- *hotCodeBlock = new BYTE[hotCodeSize];
+ *hotCodeBlock = jitInstance->mc->cr->allocateMemory(hotCodeSize);
if (coldCodeSize > 0)
- *coldCodeBlock = new BYTE[coldCodeSize];
+ *coldCodeBlock = jitInstance->mc->cr->allocateMemory(coldCodeSize);
else
*coldCodeBlock = nullptr;
- *roDataBlock = new BYTE[roDataSize];
+ *roDataBlock = jitInstance->mc->cr->allocateMemory(roDataSize);
jitInstance->mc->cr->recAllocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock,
coldCodeBlock, roDataBlock);
}
)
{
jitInstance->mc->cr->AddCall("allocGCInfo");
- void* temp = (unsigned char*)new BYTE[size];
+ void* temp = jitInstance->mc->cr->allocateMemory(size);
jitInstance->mc->cr->recAllocGCInfo(size, temp);
return temp;
void* JitInstance::allocateArray(size_t cBytes)
{
mc->cr->AddCall("allocateArray");
- return new BYTE[cBytes];
+ return mc->cr->allocateMemory(cBytes);
}
// Used to allocate memory that needs to live as long as the jit
void JitInstance::freeArray(void* array)
{
mc->cr->AddCall("freeArray");
- delete [] (BYTE*)array;
+ // We don't bother freeing this until the mc->cr itself gets freed.
}
// Used to free memory allocated by JitInstance::allocateLongLivedArray.