diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/ExecutionEngine/JITMemoryManager.h | 14 | ||||
-rw-r--r-- | llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp | 20 | ||||
-rw-r--r-- | llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp | 44 | ||||
-rw-r--r-- | llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp | 77 |
4 files changed, 80 insertions, 75 deletions
diff --git a/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h b/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h index 9f6fb63fbe5..568518898c3 100644 --- a/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h +++ b/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -132,9 +132,11 @@ public: /// virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0; - /// deallocateMemForFunction - Free JIT memory for the specified function. - /// This is never called when the JIT is currently emitting a function. - virtual void deallocateMemForFunction(const Function *F) = 0; + /// deallocateFunctionBody - Free the specified function body. The argument + /// must be the return value from a call to startFunctionBody() that hasn't + /// been deallocated yet. This is never called when the JIT is currently + /// emitting a function. + virtual void deallocateFunctionBody(void *Body) = 0; /// startExceptionTable - When we finished JITing the function, if exception /// handling is set, we emit the exception table. @@ -146,6 +148,12 @@ public: virtual void endExceptionTable(const Function *F, uint8_t *TableStart, uint8_t *TableEnd, uint8_t* FrameRegister) = 0; + /// deallocateExceptionTable - Free the specified exception table's memory. + /// The argument must be the return value from a call to startExceptionTable() + /// that hasn't been deallocated yet. This is never called when the JIT is + /// currently emitting an exception table. + virtual void deallocateExceptionTable(void *ET) = 0; + /// CheckInvariants - For testing only. Return true if all internal /// invariants are preserved, or return false and set ErrorStr to a helpful /// error message. diff --git a/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp b/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp index 5066447cd98..073d6fbbde6 100644 --- a/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -42,6 +42,7 @@ #include "llvm/System/Disassembler.h" #include "llvm/System/Memory.h" #include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" @@ -548,6 +549,13 @@ namespace { /// finishFunction. JITEvent_EmittedFunctionDetails EmissionDetails; + struct EmittedCode { + void *FunctionBody; + void *ExceptionTable; + EmittedCode() : FunctionBody(0), ExceptionTable(0) {} + }; + DenseMap<const Function *, EmittedCode> EmittedFunctions; + // CurFnStubUses - For a given Function, a vector of stubs that it // references. This facilitates the JIT detecting that a stub is no // longer used, so that it may be deallocated. @@ -1011,7 +1019,8 @@ void JITEmitter::startFunction(MachineFunction &F) { BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(), ActualSize); BufferEnd = BufferBegin+ActualSize; - + EmittedFunctions[F.getFunction()].FunctionBody = BufferBegin; + // Ensure the constant pool/jump table info is at least 4-byte aligned. emitAlignment(16); @@ -1201,6 +1210,7 @@ bool JITEmitter::finishFunction(MachineFunction &F) { BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(), ActualSize); BufferEnd = BufferBegin+ActualSize; + EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin; uint8_t *EhStart; uint8_t *FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd, EhStart); @@ -1244,7 +1254,13 @@ void JITEmitter::retryWithMoreMemory(MachineFunction &F) { /// deallocateMemForFunction - Deallocate all memory for the specified /// function body. Also drop any references the function has to stubs. void JITEmitter::deallocateMemForFunction(const Function *F) { - MemMgr->deallocateMemForFunction(F); + DenseMap<const Function *, EmittedCode>::iterator Emitted = + EmittedFunctions.find(F); + if (Emitted != EmittedFunctions.end()) { + MemMgr->deallocateFunctionBody(Emitted->second.FunctionBody); + MemMgr->deallocateExceptionTable(Emitted->second.ExceptionTable); + EmittedFunctions.erase(Emitted); + } // TODO: Do we need to unregister exception handling information from libgcc // here? diff --git a/llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp index 474843f0662..ea9d09fffc7 100644 --- a/llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp +++ b/llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp @@ -297,9 +297,6 @@ namespace { uint8_t *GOTBase; // Target Specific reserved memory void *DlsymTable; // Stub external symbol information - - std::map<const Function*, MemoryRangeHeader*> FunctionBlocks; - std::map<const Function*, MemoryRangeHeader*> TableBlocks; public: DefaultJITMemoryManager(); ~DefaultJITMemoryManager(); @@ -414,7 +411,6 @@ namespace { "Mismatched function start/end!"); uintptr_t BlockSize = FunctionEnd - (uint8_t *)CurBlock; - FunctionBlocks[F] = CurBlock; // Release the memory at the end of this block that isn't needed. FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); @@ -464,7 +460,6 @@ namespace { "Mismatched table start/end!"); uintptr_t BlockSize = TableEnd - (uint8_t *)CurBlock; - TableBlocks[F] = CurBlock; // Release the memory at the end of this block that isn't needed. FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); @@ -478,15 +473,9 @@ namespace { return DlsymTable; } - /// deallocateMemForFunction - Deallocate all memory for the specified - /// function body. - void deallocateMemForFunction(const Function *F) { - std::map<const Function*, MemoryRangeHeader*>::iterator - I = FunctionBlocks.find(F); - if (I == FunctionBlocks.end()) return; - + void deallocateBlock(void *Block) { // Find the block that is allocated for this function. - MemoryRangeHeader *MemRange = I->second; + MemoryRangeHeader *MemRange = static_cast<MemoryRangeHeader*>(Block) - 1; assert(MemRange->ThisAllocated && "Block isn't allocated!"); // Fill the buffer with garbage! @@ -496,27 +485,18 @@ namespace { // Free the memory. FreeMemoryList = MemRange->FreeBlock(FreeMemoryList); - - // Finally, remove this entry from FunctionBlocks. - FunctionBlocks.erase(I); - - I = TableBlocks.find(F); - if (I == TableBlocks.end()) return; - - // Find the block that is allocated for this function. - MemRange = I->second; - assert(MemRange->ThisAllocated && "Block isn't allocated!"); + } - // Fill the buffer with garbage! - if (PoisonMemory) { - memset(MemRange+1, 0xCD, MemRange->BlockSize-sizeof(*MemRange)); - } + /// deallocateFunctionBody - Deallocate all memory for the specified + /// function body. + void deallocateFunctionBody(void *Body) { + deallocateBlock(Body); + } - // Free the memory. - FreeMemoryList = MemRange->FreeBlock(FreeMemoryList); - - // Finally, remove this entry from TableBlocks. - TableBlocks.erase(I); + /// deallocateExceptionTable - Deallocate memory for the specified + /// exception table. + void deallocateExceptionTable(void *ET) { + deallocateBlock(ET); } /// setMemoryWritable - When code generation is in progress, diff --git a/llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp b/llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp index 89a4be70be2..f0c491fba5b 100644 --- a/llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp +++ b/llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp @@ -32,37 +32,36 @@ TEST(JITMemoryManagerTest, NoAllocations) { OwningPtr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); uintptr_t size; - uint8_t *start; std::string Error; // Allocate the functions. OwningPtr<Function> F1(makeFakeFunction()); size = 1024; - start = MemMgr->startFunctionBody(F1.get(), size); - memset(start, 0xFF, 1024); - MemMgr->endFunctionBody(F1.get(), start, start + 1024); + uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size); + memset(FunctionBody1, 0xFF, 1024); + MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + 1024); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; OwningPtr<Function> F2(makeFakeFunction()); size = 1024; - start = MemMgr->startFunctionBody(F2.get(), size); - memset(start, 0xFF, 1024); - MemMgr->endFunctionBody(F2.get(), start, start + 1024); + uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size); + memset(FunctionBody2, 0xFF, 1024); + MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + 1024); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; OwningPtr<Function> F3(makeFakeFunction()); size = 1024; - start = MemMgr->startFunctionBody(F3.get(), size); - memset(start, 0xFF, 1024); - MemMgr->endFunctionBody(F3.get(), start, start + 1024); + uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); + memset(FunctionBody3, 0xFF, 1024); + MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + 1024); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; // Deallocate them out of order, in case that matters. - MemMgr->deallocateMemForFunction(F2.get()); + MemMgr->deallocateFunctionBody(FunctionBody2); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateMemForFunction(F1.get()); + MemMgr->deallocateFunctionBody(FunctionBody1); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateMemForFunction(F3.get()); + MemMgr->deallocateFunctionBody(FunctionBody3); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; } @@ -72,7 +71,6 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { OwningPtr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); uintptr_t size; - uint8_t *start; std::string Error; // Big functions are a little less than the largest block size. @@ -83,26 +81,26 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { // Allocate big functions OwningPtr<Function> F1(makeFakeFunction()); size = bigFuncSize; - start = MemMgr->startFunctionBody(F1.get(), size); + uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size); ASSERT_LE(bigFuncSize, size); - memset(start, 0xFF, bigFuncSize); - MemMgr->endFunctionBody(F1.get(), start, start + bigFuncSize); + memset(FunctionBody1, 0xFF, bigFuncSize); + MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + bigFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; OwningPtr<Function> F2(makeFakeFunction()); size = bigFuncSize; - start = MemMgr->startFunctionBody(F2.get(), size); + uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size); ASSERT_LE(bigFuncSize, size); - memset(start, 0xFF, bigFuncSize); - MemMgr->endFunctionBody(F2.get(), start, start + bigFuncSize); + memset(FunctionBody2, 0xFF, bigFuncSize); + MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + bigFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; OwningPtr<Function> F3(makeFakeFunction()); size = bigFuncSize; - start = MemMgr->startFunctionBody(F3.get(), size); + uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); ASSERT_LE(bigFuncSize, size); - memset(start, 0xFF, bigFuncSize); - MemMgr->endFunctionBody(F3.get(), start, start + bigFuncSize); + memset(FunctionBody3, 0xFF, bigFuncSize); + MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + bigFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; // Check that each large function took it's own slab. @@ -111,43 +109,46 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { // Allocate small functions OwningPtr<Function> F4(makeFakeFunction()); size = smallFuncSize; - start = MemMgr->startFunctionBody(F4.get(), size); + uint8_t *FunctionBody4 = MemMgr->startFunctionBody(F4.get(), size); ASSERT_LE(smallFuncSize, size); - memset(start, 0xFF, smallFuncSize); - MemMgr->endFunctionBody(F4.get(), start, start + smallFuncSize); + memset(FunctionBody4, 0xFF, smallFuncSize); + MemMgr->endFunctionBody(F4.get(), FunctionBody4, + FunctionBody4 + smallFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; OwningPtr<Function> F5(makeFakeFunction()); size = smallFuncSize; - start = MemMgr->startFunctionBody(F5.get(), size); + uint8_t *FunctionBody5 = MemMgr->startFunctionBody(F5.get(), size); ASSERT_LE(smallFuncSize, size); - memset(start, 0xFF, smallFuncSize); - MemMgr->endFunctionBody(F5.get(), start, start + smallFuncSize); + memset(FunctionBody5, 0xFF, smallFuncSize); + MemMgr->endFunctionBody(F5.get(), FunctionBody5, + FunctionBody5 + smallFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; OwningPtr<Function> F6(makeFakeFunction()); size = smallFuncSize; - start = MemMgr->startFunctionBody(F6.get(), size); + uint8_t *FunctionBody6 = MemMgr->startFunctionBody(F6.get(), size); ASSERT_LE(smallFuncSize, size); - memset(start, 0xFF, smallFuncSize); - MemMgr->endFunctionBody(F6.get(), start, start + smallFuncSize); + memset(FunctionBody6, 0xFF, smallFuncSize); + MemMgr->endFunctionBody(F6.get(), FunctionBody6, + FunctionBody6 + smallFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; // Check that the small functions didn't allocate any new slabs. EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); // Deallocate them out of order, in case that matters. - MemMgr->deallocateMemForFunction(F2.get()); + MemMgr->deallocateFunctionBody(FunctionBody2); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateMemForFunction(F1.get()); + MemMgr->deallocateFunctionBody(FunctionBody1); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateMemForFunction(F4.get()); + MemMgr->deallocateFunctionBody(FunctionBody4); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateMemForFunction(F3.get()); + MemMgr->deallocateFunctionBody(FunctionBody3); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateMemForFunction(F5.get()); + MemMgr->deallocateFunctionBody(FunctionBody5); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateMemForFunction(F6.get()); + MemMgr->deallocateFunctionBody(FunctionBody6); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; } |