aboutsummaryrefslogtreecommitdiff
path: root/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ExecutionEngine/JIT/JITMemoryManager.cpp')
-rw-r--r--lib/ExecutionEngine/JIT/JITMemoryManager.cpp73
1 files changed, 57 insertions, 16 deletions
diff --git a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
index 70ccdccb80..9820493828 100644
--- a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
+++ b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
@@ -251,6 +251,8 @@ namespace {
/// middle of emitting a function, and we don't know how large the function we
/// are emitting is.
class VISIBILITY_HIDDEN DefaultJITMemoryManager : public JITMemoryManager {
+ bool PoisonMemory; // Whether to poison freed memory.
+
std::vector<sys::MemoryBlock> Blocks; // Memory blocks allocated by the JIT
FreeRangeHeader *FreeMemoryList; // Circular list of free blocks.
@@ -258,6 +260,7 @@ namespace {
MemoryRangeHeader *CurBlock;
uint8_t *CurStubPtr, *StubBase;
+ uint8_t *CurGlobalPtr, *GlobalEnd;
uint8_t *GOTBase; // Target Specific reserved memory
void *DlsymTable; // Stub external symbol information
@@ -324,7 +327,7 @@ namespace {
CurBlock = FreeMemoryList;
FreeMemoryList = FreeMemoryList->AllocateBlock();
- uint8_t *result = (uint8_t *)CurBlock+1;
+ uint8_t *result = (uint8_t *)(CurBlock + 1);
if (Alignment == 0) Alignment = 1;
result = (uint8_t*)(((intptr_t)result+Alignment-1) &
@@ -336,6 +339,30 @@ namespace {
return result;
}
+ /// allocateGlobal - Allocate memory for a global. Unlike allocateSpace,
+ /// this method does not touch the current block and can be called at any
+ /// time.
+ uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
+ uint8_t *Result = CurGlobalPtr;
+
+ // Align the pointer.
+ if (Alignment == 0) Alignment = 1;
+ Result = (uint8_t*)(((uintptr_t)Result + Alignment-1) &
+ ~(uintptr_t)(Alignment-1));
+
+ // Move the current global pointer forward.
+ CurGlobalPtr += Result - CurGlobalPtr + Size;
+
+ // Check for overflow.
+ if (CurGlobalPtr > GlobalEnd) {
+ // FIXME: Allocate more memory.
+ fprintf(stderr, "JIT ran out of memory for globals!\n");
+ abort();
+ }
+
+ return Result;
+ }
+
/// startExceptionTable - Use startFunctionBody to allocate memory for the
/// function's exception table.
uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize) {
@@ -375,12 +402,12 @@ namespace {
// Find the block that is allocated for this function.
MemoryRangeHeader *MemRange = I->second;
assert(MemRange->ThisAllocated && "Block isn't allocated!");
-
+
// Fill the buffer with garbage!
-#ifndef NDEBUG
- memset(MemRange+1, 0xCD, MemRange->BlockSize-sizeof(*MemRange));
-#endif
-
+ if (PoisonMemory) {
+ memset(MemRange+1, 0xCD, MemRange->BlockSize-sizeof(*MemRange));
+ }
+
// Free the memory.
FreeMemoryList = MemRange->FreeBlock(FreeMemoryList);
@@ -393,12 +420,12 @@ namespace {
// Find the block that is allocated for this function.
MemRange = I->second;
assert(MemRange->ThisAllocated && "Block isn't allocated!");
-
+
// Fill the buffer with garbage!
-#ifndef NDEBUG
- memset(MemRange+1, 0xCD, MemRange->BlockSize-sizeof(*MemRange));
-#endif
-
+ if (PoisonMemory) {
+ memset(MemRange+1, 0xCD, MemRange->BlockSize-sizeof(*MemRange));
+ }
+
// Free the memory.
FreeMemoryList = MemRange->FreeBlock(FreeMemoryList);
@@ -420,10 +447,22 @@ namespace {
for (unsigned i = 0, e = Blocks.size(); i != e; ++i)
sys::Memory::setExecutable(Blocks[i]);
}
+
+ /// setPoisonMemory - Controls whether we write garbage over freed memory.
+ ///
+ void setPoisonMemory(bool poison) {
+ PoisonMemory = poison;
+ }
};
}
DefaultJITMemoryManager::DefaultJITMemoryManager() {
+#ifdef NDEBUG
+ PoisonMemory = true;
+#else
+ PoisonMemory = false;
+#endif
+
// Allocate a 16M block of memory for functions.
#if defined(__APPLE__) && defined(__arm__)
sys::MemoryBlock MemBlock = getNewMemoryBlock(4 << 20);
@@ -433,11 +472,13 @@ DefaultJITMemoryManager::DefaultJITMemoryManager() {
uint8_t *MemBase = static_cast<uint8_t*>(MemBlock.base());
- // Allocate stubs backwards from the base, allocate functions forward
- // from the base.
+ // Allocate stubs backwards to the base, globals forward from the stubs, and
+ // functions forward after globals.
StubBase = MemBase;
CurStubPtr = MemBase + 512*1024; // Use 512k for stubs, working backwards.
-
+ CurGlobalPtr = CurStubPtr; // Use 2M for globals, working forwards.
+ GlobalEnd = CurGlobalPtr + 2*1024*1024;
+
// We set up the memory chunk with 4 mem regions, like this:
// [ START
// [ Free #0 ] -> Large space to allocate functions from.
@@ -474,7 +515,7 @@ DefaultJITMemoryManager::DefaultJITMemoryManager() {
// Add a FreeRangeHeader to the start of the function body region, indicating
// that the space is free. Mark the previous block allocated so we never look
// at it.
- FreeRangeHeader *Mem0 = (FreeRangeHeader*)CurStubPtr;
+ FreeRangeHeader *Mem0 = (FreeRangeHeader*)GlobalEnd;
Mem0->ThisAllocated = 0;
Mem0->PrevAllocated = 1;
Mem0->BlockSize = (char*)Mem1-(char*)Mem0;
@@ -522,7 +563,7 @@ uint8_t *DefaultJITMemoryManager::allocateStub(const GlobalValue* F,
sys::MemoryBlock DefaultJITMemoryManager::getNewMemoryBlock(unsigned size) {
// Allocate a new block close to the last one.
- const sys::MemoryBlock *BOld = Blocks.empty() ? 0 : &Blocks.front();
+ const sys::MemoryBlock *BOld = Blocks.empty() ? 0 : &Blocks.back();
std::string ErrMsg;
sys::MemoryBlock B = sys::Memory::AllocateRWX(size, BOld, &ErrMsg);
if (B.base() == 0) {