diff options
Diffstat (limited to 'lib/ExecutionEngine/JIT/JITMemoryManager.cpp')
-rw-r--r-- | lib/ExecutionEngine/JIT/JITMemoryManager.cpp | 73 |
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) { |