diff options
author | Jeffrey Yasskin <jyasskin@google.com> | 2009-10-27 00:03:05 +0000 |
---|---|---|
committer | Jeffrey Yasskin <jyasskin@google.com> | 2009-10-27 00:03:05 +0000 |
commit | 7a9034c4db248fe8b8cb82762881b51b221988d3 (patch) | |
tree | 730343fa9578d5b2ea0637b4cf330070aab8c0f7 /lib/ExecutionEngine | |
parent | f2becca90b832cc02345fba063b9b439b2be33ad (diff) | |
download | external_llvm-7a9034c4db248fe8b8cb82762881b51b221988d3.zip external_llvm-7a9034c4db248fe8b8cb82762881b51b221988d3.tar.gz external_llvm-7a9034c4db248fe8b8cb82762881b51b221988d3.tar.bz2 |
Automatically do the equivalent of freeMachineCodeForFunction(F) when F is
being destroyed. This allows users to run global optimizations like globaldce
even after some functions have been jitted.
This patch also removes the Function* parameter to
JITEventListener::NotifyFreeingMachineCode() since it can cause that to be
called when the Function is partially destroyed. This change will be even more
helpful later when I think we'll want to allow machine code to actually outlive
its Function.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85182 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r-- | lib/ExecutionEngine/JIT/JIT.cpp | 4 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/JIT.h | 2 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/JITEmitter.cpp | 45 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp | 10 |
4 files changed, 40 insertions, 21 deletions
diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp index cb82590..6b1464e 100644 --- a/lib/ExecutionEngine/JIT/JIT.cpp +++ b/lib/ExecutionEngine/JIT/JIT.cpp @@ -556,10 +556,10 @@ void JIT::NotifyFunctionEmitted( } } -void JIT::NotifyFreeingMachineCode(const Function &F, void *OldPtr) { +void JIT::NotifyFreeingMachineCode(void *OldPtr) { MutexGuard locked(lock); for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { - EventListeners[I]->NotifyFreeingMachineCode(F, OldPtr); + EventListeners[I]->NotifyFreeingMachineCode(OldPtr); } } diff --git a/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h index 525cc84..1e907f1 100644 --- a/lib/ExecutionEngine/JIT/JIT.h +++ b/lib/ExecutionEngine/JIT/JIT.h @@ -183,7 +183,7 @@ public: void NotifyFunctionEmitted( const Function &F, void *Code, size_t Size, const JITEvent_EmittedFunctionDetails &Details); - void NotifyFreeingMachineCode(const Function &F, void *OldPtr); + void NotifyFreeingMachineCode(void *OldPtr); private: static JITCodeEmitter *createEmitter(JIT &J, JITMemoryManager *JMM, diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index 2915f49..394fd8f 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -582,17 +582,24 @@ namespace { JITEvent_EmittedFunctionDetails EmissionDetails; struct EmittedCode { - void *FunctionBody; + void *FunctionBody; // Beginning of the function's allocation. + void *Code; // The address the function's code actually starts at. void *ExceptionTable; - EmittedCode() : FunctionBody(0), ExceptionTable(0) {} + EmittedCode() : FunctionBody(0), Code(0), ExceptionTable(0) {} }; - DenseMap<const Function *, EmittedCode> EmittedFunctions; + struct EmittedFunctionConfig : public ValueMapConfig<const Function*> { + typedef JITEmitter *ExtraData; + static void onDelete(JITEmitter *, const Function*); + static void onRAUW(JITEmitter *, const Function*, const Function*); + }; + ValueMap<const Function *, EmittedCode, + EmittedFunctionConfig> 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. - DenseMap<const Function *, SmallVector<void*, 1> > CurFnStubUses; - + DenseMap<AssertingVH<const Function>, SmallVector<void*, 1> > CurFnStubUses; + // StubFnRefs - For a given pointer to a stub, a set of Functions which // reference the stub. When the count of a stub's references drops to zero, // the stub is unused. @@ -606,7 +613,8 @@ namespace { public: JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM) - : SizeEstimate(0), Resolver(jit), MMI(0), CurFn(0) { + : SizeEstimate(0), Resolver(jit), MMI(0), CurFn(0), + EmittedFunctions(this) { MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager(); if (jit.getJITInfo().needsGOT()) { MemMgr->AllocateGOT(); @@ -1062,6 +1070,7 @@ void JITEmitter::startFunction(MachineFunction &F) { // About to start emitting the machine code for the function. emitAlignment(std::max(F.getFunction()->getAlignment(), 8U)); TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr); + EmittedFunctions[F.getFunction()].Code = CurBufferPtr; MBBLocations.clear(); @@ -1285,12 +1294,15 @@ void JITEmitter::retryWithMoreMemory(MachineFunction &F) { /// deallocateMemForFunction - Deallocate all memory for the specified /// function body. Also drop any references the function has to stubs. +/// May be called while the Function is being destroyed inside ~Value(). void JITEmitter::deallocateMemForFunction(const Function *F) { - DenseMap<const Function *, EmittedCode>::iterator Emitted = - EmittedFunctions.find(F); + ValueMap<const Function *, EmittedCode, EmittedFunctionConfig>::iterator + Emitted = EmittedFunctions.find(F); if (Emitted != EmittedFunctions.end()) { MemMgr->deallocateFunctionBody(Emitted->second.FunctionBody); MemMgr->deallocateExceptionTable(Emitted->second.ExceptionTable); + TheJIT->NotifyFreeingMachineCode(Emitted->second.Code); + EmittedFunctions.erase(Emitted); } @@ -1519,6 +1531,17 @@ uintptr_t JITEmitter::getJumpTableEntryAddress(unsigned Index) const { return (uintptr_t)((char *)JumpTableBase + Offset); } +void JITEmitter::EmittedFunctionConfig::onDelete( + JITEmitter *Emitter, const Function *F) { + Emitter->deallocateMemForFunction(F); +} +void JITEmitter::EmittedFunctionConfig::onRAUW( + JITEmitter *, const Function*, const Function*) { + llvm_unreachable("The JIT doesn't know how to handle a" + " RAUW on a value it has emitted."); +} + + //===----------------------------------------------------------------------===// // Public interface to this file //===----------------------------------------------------------------------===// @@ -1657,13 +1680,9 @@ void JIT::updateDlsymStubTable() { /// freeMachineCodeForFunction - release machine code memory for given Function. /// void JIT::freeMachineCodeForFunction(Function *F) { - // Delete translation for this from the ExecutionEngine, so it will get // retranslated next time it is used. - void *OldPtr = updateGlobalMapping(F, 0); - - if (OldPtr) - TheJIT->NotifyFreeingMachineCode(*F, OldPtr); + updateGlobalMapping(F, 0); // Free the actual memory for the function body and related stuff. assert(isa<JITEmitter>(JCE) && "Unexpected MCE?"); diff --git a/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp b/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp index 00c4af7..d05ab4d 100644 --- a/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp +++ b/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp @@ -147,13 +147,13 @@ void OProfileJITEventListener::NotifyFunctionEmitted( } } -// Removes the to-be-deleted function from the symbol table. -void OProfileJITEventListener::NotifyFreeingMachineCode( - const Function &F, void *FnStart) { +// Removes the being-deleted function from the symbol table. +void OProfileJITEventListener::NotifyFreeingMachineCode(void *FnStart) { assert(FnStart && "Invalid function pointer"); if (op_unload_native_code(Agent, reinterpret_cast<uint64_t>(FnStart)) == -1) { - DEBUG(errs() << "Failed to tell OProfile about unload of native function " - << F.getName() << " at " << FnStart << "\n"); + DEBUG(errs() + << "Failed to tell OProfile about unload of native function at " + << FnStart << "\n"); } } |