summaryrefslogtreecommitdiffstats
path: root/lib/ExecutionEngine
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp47
-rw-r--r--lib/ExecutionEngine/Interpreter/Execution.cpp41
-rw-r--r--lib/ExecutionEngine/Interpreter/Interpreter.h7
-rw-r--r--lib/ExecutionEngine/JIT/JIT.cpp10
-rw-r--r--lib/ExecutionEngine/JIT/JIT.h7
-rw-r--r--lib/ExecutionEngine/JIT/JITDebugRegisterer.h2
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp111
-rw-r--r--lib/ExecutionEngine/JIT/MacOSJITEventListener.cpp172
-rw-r--r--lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp12
9 files changed, 150 insertions, 259 deletions
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp
index 053d960..21499e5 100644
--- a/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -49,7 +49,7 @@ ExecutionEngine::EERegisterFn ExecutionEngine::ExceptionTableRegister = 0;
ExecutionEngine::ExecutionEngine(ModuleProvider *P)
: EEState(*this),
LazyFunctionCreator(0) {
- LazyCompilationDisabled = false;
+ CompilingLazily = false;
GVCompilationDisabled = false;
SymbolSearchingDisabled = false;
DlsymStubsEnabled = false;
@@ -117,8 +117,7 @@ Function *ExecutionEngine::FindFunctionNamed(const char *FnName) {
void *ExecutionEngineState::RemoveMapping(
const MutexGuard &, const GlobalValue *ToUnmap) {
- std::map<MapUpdatingCVH, void *>::iterator I =
- GlobalAddressMap.find(getVH(ToUnmap));
+ GlobalAddressMapTy::iterator I = GlobalAddressMap.find(ToUnmap);
void *OldVal;
if (I == GlobalAddressMap.end())
OldVal = 0;
@@ -141,7 +140,7 @@ void ExecutionEngine::addGlobalMapping(const GlobalValue *GV, void *Addr) {
DEBUG(errs() << "JIT: Map \'" << GV->getName()
<< "\' to [" << Addr << "]\n";);
- void *&CurVal = EEState.getGlobalAddressMap(locked)[EEState.getVH(GV)];
+ void *&CurVal = EEState.getGlobalAddressMap(locked)[GV];
assert((CurVal == 0 || Addr == 0) && "GlobalMapping already established!");
CurVal = Addr;
@@ -183,7 +182,7 @@ void ExecutionEngine::clearGlobalMappingsFromModule(Module *M) {
void *ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, void *Addr) {
MutexGuard locked(lock);
- std::map<ExecutionEngineState::MapUpdatingCVH, void *> &Map =
+ ExecutionEngineState::GlobalAddressMapTy &Map =
EEState.getGlobalAddressMap(locked);
// Deleting from the mapping?
@@ -191,7 +190,7 @@ void *ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, void *Addr) {
return EEState.RemoveMapping(locked, GV);
}
- void *&CurVal = Map[EEState.getVH(GV)];
+ void *&CurVal = Map[GV];
void *OldVal = CurVal;
if (CurVal && !EEState.getGlobalAddressReverseMap(locked).empty())
@@ -214,8 +213,8 @@ void *ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, void *Addr) {
void *ExecutionEngine::getPointerToGlobalIfAvailable(const GlobalValue *GV) {
MutexGuard locked(lock);
- std::map<ExecutionEngineState::MapUpdatingCVH, void*>::iterator I =
- EEState.getGlobalAddressMap(locked).find(EEState.getVH(GV));
+ ExecutionEngineState::GlobalAddressMapTy::iterator I =
+ EEState.getGlobalAddressMap(locked).find(GV);
return I != EEState.getGlobalAddressMap(locked).end() ? I->second : 0;
}
@@ -227,7 +226,7 @@ const GlobalValue *ExecutionEngine::getGlobalValueAtAddress(void *Addr) {
// If we haven't computed the reverse mapping yet, do so first.
if (EEState.getGlobalAddressReverseMap(locked).empty()) {
- for (std::map<ExecutionEngineState::MapUpdatingCVH, void *>::iterator
+ for (ExecutionEngineState::GlobalAddressMapTy::iterator
I = EEState.getGlobalAddressMap(locked).begin(),
E = EEState.getGlobalAddressMap(locked).end(); I != E; ++I)
EEState.getGlobalAddressReverseMap(locked).insert(std::make_pair(I->second,
@@ -476,7 +475,7 @@ void *ExecutionEngine::getPointerToGlobal(const GlobalValue *GV) {
return getPointerToFunction(F);
MutexGuard locked(lock);
- void *p = EEState.getGlobalAddressMap(locked)[EEState.getVH(GV)];
+ void *p = EEState.getGlobalAddressMap(locked)[GV];
if (p)
return p;
@@ -486,7 +485,7 @@ void *ExecutionEngine::getPointerToGlobal(const GlobalValue *GV) {
EmitGlobalVariable(GVar);
else
llvm_unreachable("Global hasn't had an address allocated yet!");
- return EEState.getGlobalAddressMap(locked)[EEState.getVH(GV)];
+ return EEState.getGlobalAddressMap(locked)[GV];
}
/// This function converts a Constant* into a GenericValue. The interesting
@@ -761,8 +760,11 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
Result.PointerVal = 0;
else if (const Function *F = dyn_cast<Function>(C))
Result = PTOGV(getPointerToFunctionOrStub(const_cast<Function*>(F)));
- else if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(C))
+ else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(C))
Result = PTOGV(getOrEmitGlobalVariable(const_cast<GlobalVariable*>(GV)));
+ else if (const BlockAddress *BA = dyn_cast<BlockAddress>(C))
+ Result = PTOGV(getPointerToBasicBlock(const_cast<BasicBlock*>(
+ BA->getBasicBlock())));
else
llvm_unreachable("Unknown constant pointer type!");
break;
@@ -1072,17 +1074,22 @@ void ExecutionEngine::EmitGlobalVariable(const GlobalVariable *GV) {
++NumGlobals;
}
-ExecutionEngineState::MapUpdatingCVH::MapUpdatingCVH(
- ExecutionEngineState &EES, const GlobalValue *GV)
- : CallbackVH(const_cast<GlobalValue*>(GV)), EES(EES) {}
+ExecutionEngineState::ExecutionEngineState(ExecutionEngine &EE)
+ : EE(EE), GlobalAddressMap(this) {
+}
-void ExecutionEngineState::MapUpdatingCVH::deleted() {
- MutexGuard locked(EES.EE.lock);
- EES.RemoveMapping(locked, *this); // Destroys *this.
+sys::Mutex *ExecutionEngineState::AddressMapConfig::getMutex(
+ ExecutionEngineState *EES) {
+ return &EES->EE.lock;
+}
+void ExecutionEngineState::AddressMapConfig::onDelete(
+ ExecutionEngineState *EES, const GlobalValue *Old) {
+ void *OldVal = EES->GlobalAddressMap.lookup(Old);
+ EES->GlobalAddressReverseMap.erase(OldVal);
}
-void ExecutionEngineState::MapUpdatingCVH::allUsesReplacedWith(
- Value *new_value) {
+void ExecutionEngineState::AddressMapConfig::onRAUW(
+ ExecutionEngineState *, const GlobalValue *, const GlobalValue *) {
assert(false && "The ExecutionEngine doesn't know how to handle a"
" RAUW on a value it has a global mapping for.");
}
diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp
index f8c775e..01bd2c7 100644
--- a/lib/ExecutionEngine/Interpreter/Execution.cpp
+++ b/lib/ExecutionEngine/Interpreter/Execution.cpp
@@ -572,9 +572,9 @@ void Interpreter::exitCalled(GenericValue GV) {
// runAtExitHandlers() assumes there are no stack frames, but
// if exit() was called, then it had a stack frame. Blow away
// the stack before interpreting atexit handlers.
- ECStack.clear ();
- runAtExitHandlers ();
- exit (GV.IntVal.zextOrTrunc(32).getZExtValue());
+ ECStack.clear();
+ runAtExitHandlers();
+ exit(GV.IntVal.zextOrTrunc(32).getZExtValue());
}
/// Pop the last stack frame off of ECStack and then copy the result
@@ -585,8 +585,8 @@ void Interpreter::exitCalled(GenericValue GV) {
/// care of switching to the normal destination BB, if we are returning
/// from an invoke.
///
-void Interpreter::popStackAndReturnValueToCaller (const Type *RetTy,
- GenericValue Result) {
+void Interpreter::popStackAndReturnValueToCaller(const Type *RetTy,
+ GenericValue Result) {
// Pop the current stack frame.
ECStack.pop_back();
@@ -629,15 +629,15 @@ void Interpreter::visitUnwindInst(UnwindInst &I) {
// Unwind stack
Instruction *Inst;
do {
- ECStack.pop_back ();
- if (ECStack.empty ())
+ ECStack.pop_back();
+ if (ECStack.empty())
llvm_report_error("Empty stack during unwind!");
- Inst = ECStack.back ().Caller.getInstruction ();
- } while (!(Inst && isa<InvokeInst> (Inst)));
+ Inst = ECStack.back().Caller.getInstruction();
+ } while (!(Inst && isa<InvokeInst>(Inst)));
// Return from invoke
- ExecutionContext &InvokingSF = ECStack.back ();
- InvokingSF.Caller = CallSite ();
+ ExecutionContext &InvokingSF = ECStack.back();
+ InvokingSF.Caller = CallSite();
// Go to exceptional destination BB of invoke instruction
SwitchToNewBasicBlock(cast<InvokeInst>(Inst)->getUnwindDest(), InvokingSF);
@@ -678,6 +678,13 @@ void Interpreter::visitSwitchInst(SwitchInst &I) {
SwitchToNewBasicBlock(Dest, SF);
}
+void Interpreter::visitIndirectBrInst(IndirectBrInst &I) {
+ ExecutionContext &SF = ECStack.back();
+ void *Dest = GVTOP(getOperandValue(I.getAddress(), SF));
+ SwitchToNewBasicBlock((BasicBlock*)Dest, SF);
+}
+
+
// SwitchToNewBasicBlock - This method is used to jump to a new basic block.
// This function handles the actual updating of block and instruction iterators
// as well as execution of all of the PHI nodes in the destination block.
@@ -720,7 +727,7 @@ void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){
// Memory Instruction Implementations
//===----------------------------------------------------------------------===//
-void Interpreter::visitAllocationInst(AllocationInst &I) {
+void Interpreter::visitAllocaInst(AllocaInst &I) {
ExecutionContext &SF = ECStack.back();
const Type *Ty = I.getType()->getElementType(); // Type to be allocated
@@ -749,14 +756,6 @@ void Interpreter::visitAllocationInst(AllocationInst &I) {
ECStack.back().Allocas.add(Memory);
}
-void Interpreter::visitFreeInst(FreeInst &I) {
- ExecutionContext &SF = ECStack.back();
- assert(isa<PointerType>(I.getOperand(0)->getType()) && "Freeing nonptr?");
- GenericValue Value = getOperandValue(I.getOperand(0), SF);
- // TODO: Check to make sure memory is allocated
- free(GVTOP(Value)); // Free memory
-}
-
// getElementOffset - The workhorse for getelementptr.
//
GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I,
@@ -835,7 +834,7 @@ void Interpreter::visitCallSite(CallSite CS) {
// Check to see if this is an intrinsic function call...
Function *F = CS.getCalledFunction();
- if (F && F->isDeclaration ())
+ if (F && F->isDeclaration())
switch (F->getIntrinsicID()) {
case Intrinsic::not_intrinsic:
break;
diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h
index e026287..038830c 100644
--- a/lib/ExecutionEngine/Interpreter/Interpreter.h
+++ b/lib/ExecutionEngine/Interpreter/Interpreter.h
@@ -19,7 +19,7 @@
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/CallSite.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/raw_ostream.h"
@@ -135,12 +135,12 @@ public:
void visitReturnInst(ReturnInst &I);
void visitBranchInst(BranchInst &I);
void visitSwitchInst(SwitchInst &I);
+ void visitIndirectBrInst(IndirectBrInst &I);
void visitBinaryOperator(BinaryOperator &I);
void visitICmpInst(ICmpInst &I);
void visitFCmpInst(FCmpInst &I);
- void visitAllocationInst(AllocationInst &I);
- void visitFreeInst(FreeInst &I);
+ void visitAllocaInst(AllocaInst &I);
void visitLoadInst(LoadInst &I);
void visitStoreInst(StoreInst &I);
void visitGetElementPtrInst(GetElementPtrInst &I);
@@ -203,6 +203,7 @@ private: // Helper functions
void SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF);
void *getPointerToFunction(Function *F) { return (void*)F; }
+ void *getPointerToBasicBlock(BasicBlock *BB) { return (void*)BB; }
void initializeExecutionEngine() { }
void initializeExternalFunctions();
diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp
index b2a268b..e21d760 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);
}
}
@@ -599,7 +599,7 @@ void JIT::runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked) {
isAlreadyCodeGenerating = false;
// If the function referred to another function that had not yet been
- // read from bitcode, but we are jitting non-lazily, emit it now.
+ // read from bitcode, and we are jitting non-lazily, emit it now.
while (!jitstate->getPendingFunctions(locked).empty()) {
Function *PF = jitstate->getPendingFunctions(locked).back();
jitstate->getPendingFunctions(locked).pop_back();
@@ -616,7 +616,7 @@ void JIT::runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked) {
// If the JIT is configured to emit info so that dlsym can be used to
// rewrite stubs to external globals, do so now.
- if (areDlsymStubsEnabled() && isLazyCompilationDisabled())
+ if (areDlsymStubsEnabled() && !isCompilingLazily())
updateDlsymStubTable();
}
@@ -659,7 +659,7 @@ void *JIT::getPointerToFunction(Function *F) {
return Addr;
}
- if (F->isDeclaration()) {
+ if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
bool AbortOnFailure =
!areDlsymStubsEnabled() && !F->hasExternalWeakLinkage();
void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure);
diff --git a/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h
index 525cc84..fb3cb24 100644
--- a/lib/ExecutionEngine/JIT/JIT.h
+++ b/lib/ExecutionEngine/JIT/JIT.h
@@ -128,6 +128,11 @@ public:
///
void *getPointerToFunction(Function *F);
+ void *getPointerToBasicBlock(BasicBlock *BB) {
+ assert(0 && "JIT does not support address-of-label yet!");
+ return 0;
+ }
+
/// getOrEmitGlobalVariable - Return the address of the specified global
/// variable, possibly emitting it to memory if needed. This is used by the
/// Emitter.
@@ -183,7 +188,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/JITDebugRegisterer.h b/lib/ExecutionEngine/JIT/JITDebugRegisterer.h
index dce506b..7e53d78 100644
--- a/lib/ExecutionEngine/JIT/JITDebugRegisterer.h
+++ b/lib/ExecutionEngine/JIT/JITDebugRegisterer.h
@@ -16,7 +16,7 @@
#define LLVM_EXECUTION_ENGINE_JIT_DEBUGREGISTERER_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include <string>
// This must be kept in sync with gdb/gdb/jit.h .
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index 073d6fb..79f1eb4 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -46,6 +46,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/ValueMap.h"
#include <algorithm>
#ifndef NDEBUG
#include <iomanip>
@@ -62,12 +63,29 @@ static JIT *TheJIT = 0;
// JIT lazy compilation code.
//
namespace {
+ class JITResolverState;
+
+ template<typename ValueTy>
+ struct NoRAUWValueMapConfig : public ValueMapConfig<ValueTy> {
+ typedef JITResolverState *ExtraData;
+ static void onRAUW(JITResolverState *, Value *Old, Value *New) {
+ assert(false && "The JIT doesn't know how to handle a"
+ " RAUW on a value it has emitted.");
+ }
+ };
+
+ struct CallSiteValueMapConfig : public NoRAUWValueMapConfig<Function*> {
+ typedef JITResolverState *ExtraData;
+ static void onDelete(JITResolverState *JRS, Function *F);
+ };
+
class JITResolverState {
public:
- typedef DenseMap<AssertingVH<Function>, void*> FunctionToStubMapTy;
+ typedef ValueMap<Function*, void*, NoRAUWValueMapConfig<Function*> >
+ FunctionToStubMapTy;
typedef std::map<void*, AssertingVH<Function> > CallSiteToFunctionMapTy;
- typedef DenseMap<AssertingVH<Function>, SmallPtrSet<void*, 1> >
- FunctionToCallSitesMapTy;
+ typedef ValueMap<Function *, SmallPtrSet<void*, 1>,
+ CallSiteValueMapConfig> FunctionToCallSitesMapTy;
typedef std::map<AssertingVH<GlobalValue>, void*> GlobalToIndirectSymMapTy;
private:
/// FunctionToStubMap - Keep track of the stub created for a particular
@@ -84,6 +102,9 @@ namespace {
GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
public:
+ JITResolverState() : FunctionToStubMap(this),
+ FunctionToCallSitesMap(this) {}
+
FunctionToStubMapTy& getFunctionToStubMap(const MutexGuard& locked) {
assert(locked.holds(TheJIT->lock));
return FunctionToStubMap;
@@ -111,8 +132,10 @@ namespace {
void AddCallSite(const MutexGuard &locked, void *CallSite, Function *F) {
assert(locked.holds(TheJIT->lock));
- assert(CallSiteToFunctionMap.insert(std::make_pair(CallSite, F)).second &&
- "Pair was already in CallSiteToFunctionMap");
+ bool Inserted = CallSiteToFunctionMap.insert(
+ std::make_pair(CallSite, F)).second;
+ (void)Inserted;
+ assert(Inserted && "Pair was already in CallSiteToFunctionMap");
FunctionToCallSitesMap[F].insert(CallSite);
}
@@ -142,8 +165,9 @@ namespace {
FunctionToCallSitesMapTy::iterator F2C_I = FunctionToCallSitesMap.find(F);
assert(F2C_I != FunctionToCallSitesMap.end() &&
"FunctionToCallSitesMap broken");
- assert(F2C_I->second.erase(Stub) &&
- "FunctionToCallSitesMap broken");
+ bool Erased = F2C_I->second.erase(Stub);
+ (void)Erased;
+ assert(Erased && "FunctionToCallSitesMap broken");
if (F2C_I->second.empty())
FunctionToCallSitesMap.erase(F2C_I);
@@ -152,13 +176,17 @@ namespace {
void EraseAllCallSites(const MutexGuard &locked, Function *F) {
assert(locked.holds(TheJIT->lock));
+ EraseAllCallSitesPrelocked(F);
+ }
+ void EraseAllCallSitesPrelocked(Function *F) {
FunctionToCallSitesMapTy::iterator F2C = FunctionToCallSitesMap.find(F);
if (F2C == FunctionToCallSitesMap.end())
return;
for (SmallPtrSet<void*, 1>::const_iterator I = F2C->second.begin(),
E = F2C->second.end(); I != E; ++I) {
- assert(CallSiteToFunctionMap.erase(*I) == 1 &&
- "Missing call site->function mapping");
+ bool Erased = CallSiteToFunctionMap.erase(*I);
+ (void)Erased;
+ assert(Erased && "Missing call site->function mapping");
}
FunctionToCallSitesMap.erase(F2C);
}
@@ -245,6 +273,10 @@ namespace {
JITResolver *JITResolver::TheJITResolver = 0;
+void CallSiteValueMapConfig::onDelete(JITResolverState *JRS, Function *F) {
+ JRS->EraseAllCallSitesPrelocked(F);
+}
+
/// getFunctionStubIfAvailable - This returns a pointer to a function stub
/// if it has already been created.
void *JITResolver::getFunctionStubIfAvailable(Function *F) {
@@ -263,11 +295,11 @@ void *JITResolver::getFunctionStub(Function *F) {
void *&Stub = state.getFunctionToStubMap(locked)[F];
if (Stub) return Stub;
- // Call the lazy resolver function unless we are JIT'ing non-lazily, in which
- // case we must resolve the symbol now.
- void *Actual = TheJIT->isLazyCompilationDisabled()
- ? (void *)0 : (void *)(intptr_t)LazyResolverFn;
-
+ // Call the lazy resolver function if we are JIT'ing lazily. Otherwise we
+ // must resolve the symbol now.
+ void *Actual = TheJIT->isCompilingLazily()
+ ? (void *)(intptr_t)LazyResolverFn : (void *)0;
+
// If this is an external declaration, attempt to resolve the address now
// to place in the stub.
if (F->isDeclaration() && !F->hasNotBeenReadFromBitcode()) {
@@ -302,7 +334,7 @@ void *JITResolver::getFunctionStub(Function *F) {
// If we are JIT'ing non-lazily but need to call a function that does not
// exist yet, add it to the JIT's work list so that we can fill in the stub
// address later.
- if (!Actual && TheJIT->isLazyCompilationDisabled())
+ if (!Actual && !TheJIT->isCompilingLazily())
if (!F->isDeclaration() || F->hasNotBeenReadFromBitcode())
TheJIT->addPendingFunction(F);
@@ -439,7 +471,7 @@ void *JITResolver::JITCompilerFn(void *Stub) {
// Otherwise we don't have it, do lazy compilation now.
// If lazy compilation is disabled, emit a useful error message and abort.
- if (TheJIT->isLazyCompilationDisabled()) {
+ if (!TheJIT->isCompilingLazily()) {
llvm_report_error("LLVM JIT requested to do lazy compilation of function '"
+ F->getName() + "' when lazy compiles are disabled!");
}
@@ -550,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) {}
+ };
+ struct EmittedFunctionConfig : public ValueMapConfig<const Function*> {
+ typedef JITEmitter *ExtraData;
+ static void onDelete(JITEmitter *, const Function*);
+ static void onRAUW(JITEmitter *, const Function*, const Function*);
};
- DenseMap<const Function *, EmittedCode> EmittedFunctions;
+ 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.
@@ -574,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();
@@ -729,7 +769,7 @@ void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference,
// mechanism is capable of rewriting the instruction directly, prefer to do
// that instead of emitting a stub. This uses the lazy resolver, so is not
// legal if lazy compilation is disabled.
- if (DoesntNeedStub && !TheJIT->isLazyCompilationDisabled())
+ if (DoesntNeedStub && TheJIT->isCompilingLazily())
return Resolver.AddCallbackAtLocation(F, Reference);
// Otherwise, we have to emit a stub.
@@ -1030,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();
@@ -1253,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);
}
@@ -1487,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
//===----------------------------------------------------------------------===//
@@ -1625,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/MacOSJITEventListener.cpp b/lib/ExecutionEngine/JIT/MacOSJITEventListener.cpp
deleted file mode 100644
index 53585b8..0000000
--- a/lib/ExecutionEngine/JIT/MacOSJITEventListener.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-//===-- MacOSJITEventListener.cpp - Save symbol table for OSX perf tools --===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a JITEventListener object that records JITted functions to
-// a global __jitSymbolTable linked list. Apple's performance tools use this to
-// determine a symbol name and accurate code range for a PC value. Because
-// performance tools are generally asynchronous, the code below is written with
-// the hope that it could be interrupted at any time and have useful answers.
-// However, we don't go crazy with atomic operations, we just do a "reasonable
-// effort".
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "macos-jit-event-listener"
-#include "llvm/Function.h"
-#include "llvm/ExecutionEngine/JITEventListener.h"
-#include <stddef.h>
-using namespace llvm;
-
-#ifdef __APPLE__
-#define ENABLE_JIT_SYMBOL_TABLE 0
-#endif
-
-#if ENABLE_JIT_SYMBOL_TABLE
-
-namespace {
-
-/// JITSymbolEntry - Each function that is JIT compiled results in one of these
-/// being added to an array of symbols. This indicates the name of the function
-/// as well as the address range it occupies. This allows the client to map
-/// from a PC value to the name of the function.
-struct JITSymbolEntry {
- const char *FnName; // FnName - a strdup'd string.
- void *FnStart;
- intptr_t FnSize;
-};
-
-
-struct JITSymbolTable {
- /// NextPtr - This forms a linked list of JitSymbolTable entries. This
- /// pointer is not used right now, but might be used in the future. Consider
- /// it reserved for future use.
- JITSymbolTable *NextPtr;
-
- /// Symbols - This is an array of JitSymbolEntry entries. Only the first
- /// 'NumSymbols' symbols are valid.
- JITSymbolEntry *Symbols;
-
- /// NumSymbols - This indicates the number entries in the Symbols array that
- /// are valid.
- unsigned NumSymbols;
-
- /// NumAllocated - This indicates the amount of space we have in the Symbols
- /// array. This is a private field that should not be read by external tools.
- unsigned NumAllocated;
-};
-
-class MacOSJITEventListener : public JITEventListener {
-public:
- virtual void NotifyFunctionEmitted(const Function &F,
- void *FnStart, size_t FnSize,
- const EmittedFunctionDetails &Details);
- virtual void NotifyFreeingMachineCode(const Function &F, void *OldPtr);
-};
-
-} // anonymous namespace.
-
-// This is a public symbol so the performance tools can find it.
-JITSymbolTable *__jitSymbolTable;
-
-namespace llvm {
-JITEventListener *createMacOSJITEventListener() {
- return new MacOSJITEventListener;
-}
-}
-
-// Adds the just-emitted function to the symbol table.
-void MacOSJITEventListener::NotifyFunctionEmitted(
- const Function &F, void *FnStart, size_t FnSize,
- const EmittedFunctionDetails &) {
- assert(F.hasName() && FnStart != 0 && "Bad symbol to add");
- JITSymbolTable **SymTabPtrPtr = 0;
- SymTabPtrPtr = &__jitSymbolTable;
-
- // If this is the first entry in the symbol table, add the JITSymbolTable
- // index.
- if (*SymTabPtrPtr == 0) {
- JITSymbolTable *New = new JITSymbolTable();
- New->NextPtr = 0;
- New->Symbols = 0;
- New->NumSymbols = 0;
- New->NumAllocated = 0;
- *SymTabPtrPtr = New;
- }
-
- JITSymbolTable *SymTabPtr = *SymTabPtrPtr;
-
- // If we have space in the table, reallocate the table.
- if (SymTabPtr->NumSymbols >= SymTabPtr->NumAllocated) {
- // If we don't have space, reallocate the table.
- unsigned NewSize = std::max(64U, SymTabPtr->NumAllocated*2);
- JITSymbolEntry *NewSymbols = new JITSymbolEntry[NewSize];
- JITSymbolEntry *OldSymbols = SymTabPtr->Symbols;
-
- // Copy the old entries over.
- memcpy(NewSymbols, OldSymbols, SymTabPtr->NumSymbols*sizeof(OldSymbols[0]));
-
- // Swap the new symbols in, delete the old ones.
- SymTabPtr->Symbols = NewSymbols;
- SymTabPtr->NumAllocated = NewSize;
- delete [] OldSymbols;
- }
-
- // Otherwise, we have enough space, just tack it onto the end of the array.
- JITSymbolEntry &Entry = SymTabPtr->Symbols[SymTabPtr->NumSymbols];
- Entry.FnName = strdup(F.getName().data());
- Entry.FnStart = FnStart;
- Entry.FnSize = FnSize;
- ++SymTabPtr->NumSymbols;
-}
-
-// Removes the to-be-deleted function from the symbol table.
-void MacOSJITEventListener::NotifyFreeingMachineCode(
- const Function &, void *FnStart) {
- assert(FnStart && "Invalid function pointer");
- JITSymbolTable **SymTabPtrPtr = 0;
- SymTabPtrPtr = &__jitSymbolTable;
-
- JITSymbolTable *SymTabPtr = *SymTabPtrPtr;
- JITSymbolEntry *Symbols = SymTabPtr->Symbols;
-
- // Scan the table to find its index. The table is not sorted, so do a linear
- // scan.
- unsigned Index;
- for (Index = 0; Symbols[Index].FnStart != FnStart; ++Index)
- assert(Index != SymTabPtr->NumSymbols && "Didn't find function!");
-
- // Once we have an index, we know to nuke this entry, overwrite it with the
- // entry at the end of the array, making the last entry redundant.
- const char *OldName = Symbols[Index].FnName;
- Symbols[Index] = Symbols[SymTabPtr->NumSymbols-1];
- free((void*)OldName);
-
- // Drop the number of symbols in the table.
- --SymTabPtr->NumSymbols;
-
- // Finally, if we deleted the final symbol, deallocate the table itself.
- if (SymTabPtr->NumSymbols != 0)
- return;
-
- *SymTabPtrPtr = 0;
- delete [] Symbols;
- delete SymTabPtr;
-}
-
-#else // !ENABLE_JIT_SYMBOL_TABLE
-
-namespace llvm {
-// By defining this to return NULL, we can let clients call it unconditionally,
-// even if they aren't on an Apple system.
-JITEventListener *createMacOSJITEventListener() {
- return NULL;
-}
-} // namespace llvm
-
-#endif // ENABLE_JIT_SYMBOL_TABLE
diff --git a/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp b/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp
index 00c4af7..b45c71f 100644
--- a/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp
+++ b/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp
@@ -43,7 +43,7 @@ public:
virtual void NotifyFunctionEmitted(const Function &F,
void *FnStart, size_t FnSize,
const EmittedFunctionDetails &Details);
- virtual void NotifyFreeingMachineCode(const Function &F, void *OldPtr);
+ virtual void NotifyFreeingMachineCode(void *OldPtr);
};
OProfileJITEventListener::OProfileJITEventListener()
@@ -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");
}
}
OpenPOWER on IntegriCloud