aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ExecutionEngine
diff options
context:
space:
mode:
authorJeffrey Yasskin <jyasskin@google.com>2009-10-27 00:03:05 +0000
committerJeffrey Yasskin <jyasskin@google.com>2009-10-27 00:03:05 +0000
commit7a9034c4db248fe8b8cb82762881b51b221988d3 (patch)
tree730343fa9578d5b2ea0637b4cf330070aab8c0f7 /lib/ExecutionEngine
parentf2becca90b832cc02345fba063b9b439b2be33ad (diff)
downloadexternal_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.cpp4
-rw-r--r--lib/ExecutionEngine/JIT/JIT.h2
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp45
-rw-r--r--lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp10
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");
}
}