llvm.org GIT mirror llvm / 23e5fcf
Fix http://llvm.org/PR4822: allow module deletion after a function has been compiled. When functions are compiled, they accumulate references in the JITResolver's stub maps. This patch removes those references when the functions are destroyed. It's illegal to destroy a Function when any thread may still try to call its machine code. This patch also updates r83987 to use ValueMap instead of explicit CallbackVHs and fixes a couple "do stuff inside assert()" bugs from r84522. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84975 91177308-0d34-0410-b5e6-96231b3b80d8 Jeffrey Yasskin 10 years ago
5 changed file(s) with 110 addition(s) and 60 deletion(s). Raw diff Collapse all Expand all
1818 #include
1919 #include
2020 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/ValueMap.h"
2122 #include "llvm/Support/ValueHandle.h"
2223 #include "llvm/System/Mutex.h"
2324 #include "llvm/Target/TargetMachine.h"
4142
4243 class ExecutionEngineState {
4344 public:
44 class MapUpdatingCVH : public CallbackVH {
45 ExecutionEngineState &EES;
46
47 public:
48 MapUpdatingCVH(ExecutionEngineState &EES, const GlobalValue *GV);
49
50 operator const GlobalValue*() const {
51 return cast(getValPtr());
52 }
53
54 virtual void deleted();
55 virtual void allUsesReplacedWith(Value *new_value);
45 struct AddressMapConfig : public ValueMapConfig {
46 typedef ExecutionEngineState *ExtraData;
47 static sys::Mutex *getMutex(ExecutionEngineState *EES);
48 static void onDelete(ExecutionEngineState *EES, const GlobalValue *Old);
49 static void onRAUW(ExecutionEngineState *, const GlobalValue *,
50 const GlobalValue *);
5651 };
52
53 typedef ValueMap
54 GlobalAddressMapTy;
5755
5856 private:
5957 ExecutionEngine ⅇ
6058
6159 /// GlobalAddressMap - A mapping between LLVM global values and their
6260 /// actualized version...
63 std::map GlobalAddressMap;
61 GlobalAddressMapTy GlobalAddressMap;
6462
6563 /// GlobalAddressReverseMap - This is the reverse mapping of GlobalAddressMap,
6664 /// used to convert raw addresses into the LLVM global value that is emitted
6967 std::map > GlobalAddressReverseMap;
7068
7169 public:
72 ExecutionEngineState(ExecutionEngine &EE) : EE(EE) {}
73
74 MapUpdatingCVH getVH(const GlobalValue *GV) {
75 return MapUpdatingCVH(*this, GV);
76 }
77
78 std::map &
70 ExecutionEngineState(ExecutionEngine &EE);
71
72 GlobalAddressMapTy &
7973 getGlobalAddressMap(const MutexGuard &) {
8074 return GlobalAddressMap;
8175 }
484478 }
485479
486480 ExecutionEngine *create();
487
488481 };
489482
490 inline bool operator<(const ExecutionEngineState::MapUpdatingCVH& lhs,
491 const ExecutionEngineState::MapUpdatingCVH& rhs) {
492 return static_cast(lhs) <
493 static_cast(rhs);
494 }
495
496483 } // End llvm namespace
497484
498485 #endif
116116
117117 void *ExecutionEngineState::RemoveMapping(
118118 const MutexGuard &, const GlobalValue *ToUnmap) {
119 std::map::iterator I =
120 GlobalAddressMap.find(getVH(ToUnmap));
119 GlobalAddressMapTy::iterator I = GlobalAddressMap.find(ToUnmap);
121120 void *OldVal;
122121 if (I == GlobalAddressMap.end())
123122 OldVal = 0;
140139
141140 DEBUG(errs() << "JIT: Map \'" << GV->getName()
142141 << "\' to [" << Addr << "]\n";);
143 void *&CurVal = EEState.getGlobalAddressMap(locked)[EEState.getVH(GV)];
142 void *&CurVal = EEState.getGlobalAddressMap(locked)[GV];
144143 assert((CurVal == 0 || Addr == 0) && "GlobalMapping already established!");
145144 CurVal = Addr;
146145
182181 void *ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, void *Addr) {
183182 MutexGuard locked(lock);
184183
185 std::map &Map =
184 ExecutionEngineState::GlobalAddressMapTy &Map =
186185 EEState.getGlobalAddressMap(locked);
187186
188187 // Deleting from the mapping?
190189 return EEState.RemoveMapping(locked, GV);
191190 }
192191
193 void *&CurVal = Map[EEState.getVH(GV)];
192 void *&CurVal = Map[GV];
194193 void *OldVal = CurVal;
195194
196195 if (CurVal && !EEState.getGlobalAddressReverseMap(locked).empty())
213212 void *ExecutionEngine::getPointerToGlobalIfAvailable(const GlobalValue *GV) {
214213 MutexGuard locked(lock);
215214
216 std::map::iterator I =
217 EEState.getGlobalAddressMap(locked).find(EEState.getVH(GV));
215 ExecutionEngineState::GlobalAddressMapTy::iterator I =
216 EEState.getGlobalAddressMap(locked).find(GV);
218217 return I != EEState.getGlobalAddressMap(locked).end() ? I->second : 0;
219218 }
220219
226225
227226 // If we haven't computed the reverse mapping yet, do so first.
228227 if (EEState.getGlobalAddressReverseMap(locked).empty()) {
229 for (std::map::iterator
228 for (ExecutionEngineState::GlobalAddressMapTy::iterator
230229 I = EEState.getGlobalAddressMap(locked).begin(),
231230 E = EEState.getGlobalAddressMap(locked).end(); I != E; ++I)
232231 EEState.getGlobalAddressReverseMap(locked).insert(std::make_pair(I->second,
475474 return getPointerToFunction(F);
476475
477476 MutexGuard locked(lock);
478 void *p = EEState.getGlobalAddressMap(locked)[EEState.getVH(GV)];
477 void *p = EEState.getGlobalAddressMap(locked)[GV];
479478 if (p)
480479 return p;
481480
485484 EmitGlobalVariable(GVar);
486485 else
487486 llvm_unreachable("Global hasn't had an address allocated yet!");
488 return EEState.getGlobalAddressMap(locked)[EEState.getVH(GV)];
487 return EEState.getGlobalAddressMap(locked)[GV];
489488 }
490489
491490 /// This function converts a Constant* into a GenericValue. The interesting
10711070 ++NumGlobals;
10721071 }
10731072
1074 ExecutionEngineState::MapUpdatingCVH::MapUpdatingCVH(
1075 ExecutionEngineState &EES, const GlobalValue *GV)
1076 : CallbackVH(const_cast(GV)), EES(EES) {}
1077
1078 void ExecutionEngineState::MapUpdatingCVH::deleted() {
1079 MutexGuard locked(EES.EE.lock);
1080 EES.RemoveMapping(locked, *this); // Destroys *this.
1081 }
1082
1083 void ExecutionEngineState::MapUpdatingCVH::allUsesReplacedWith(
1084 Value *new_value) {
1073 ExecutionEngineState::ExecutionEngineState(ExecutionEngine &EE)
1074 : EE(EE), GlobalAddressMap(this) {
1075 }
1076
1077 sys::Mutex *ExecutionEngineState::AddressMapConfig::getMutex(
1078 ExecutionEngineState *EES) {
1079 return &EES->EE.lock;
1080 }
1081 void ExecutionEngineState::AddressMapConfig::onDelete(
1082 ExecutionEngineState *EES, const GlobalValue *Old) {
1083 void *OldVal = EES->GlobalAddressMap.lookup(Old);
1084 EES->GlobalAddressReverseMap.erase(OldVal);
1085 }
1086
1087 void ExecutionEngineState::AddressMapConfig::onRAUW(
1088 ExecutionEngineState *, const GlobalValue *, const GlobalValue *) {
10851089 assert(false && "The ExecutionEngine doesn't know how to handle a"
10861090 " RAUW on a value it has a global mapping for.");
10871091 }
4545 #include "llvm/ADT/SmallPtrSet.h"
4646 #include "llvm/ADT/SmallVector.h"
4747 #include "llvm/ADT/Statistic.h"
48 #include "llvm/ADT/ValueMap.h"
4849 #include
4950 #ifndef NDEBUG
5051 #include
6162 // JIT lazy compilation code.
6263 //
6364 namespace {
65 class JITResolverState;
66
67 template
68 struct NoRAUWValueMapConfig : public ValueMapConfig {
69 typedef JITResolverState *ExtraData;
70 static void onRAUW(JITResolverState *, Value *Old, Value *New) {
71 assert(false && "The JIT doesn't know how to handle a"
72 " RAUW on a value it has emitted.");
73 }
74 };
75
76 struct CallSiteValueMapConfig : public NoRAUWValueMapConfig {
77 typedef JITResolverState *ExtraData;
78 static void onDelete(JITResolverState *JRS, Function *F);
79 };
80
6481 class JITResolverState {
6582 public:
66 typedef DenseMap, void*> FunctionToStubMapTy;
83 typedef ValueMap >
84 FunctionToStubMapTy;
6785 typedef std::map > CallSiteToFunctionMapTy;
68 typedef DenseMap, SmallPtrSet >
69 FunctionToCallSitesMapTy;
86 typedef ValueMap,
87 CallSiteValueMapConfig> FunctionToCallSitesMapTy;
7088 typedef std::map, void*> GlobalToIndirectSymMapTy;
7189 private:
7290 /// FunctionToStubMap - Keep track of the stub created for a particular
83101 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
84102
85103 public:
104 JITResolverState() : FunctionToStubMap(this),
105 FunctionToCallSitesMap(this) {}
106
86107 FunctionToStubMapTy& getFunctionToStubMap(const MutexGuard& locked) {
87108 assert(locked.holds(TheJIT->lock));
88109 return FunctionToStubMap;
110131 void AddCallSite(const MutexGuard &locked, void *CallSite, Function *F) {
111132 assert(locked.holds(TheJIT->lock));
112133
113 assert(CallSiteToFunctionMap.insert(std::make_pair(CallSite, F)).second &&
114 "Pair was already in CallSiteToFunctionMap");
134 bool Inserted = CallSiteToFunctionMap.insert(
135 std::make_pair(CallSite, F)).second;
136 (void)Inserted;
137 assert(Inserted && "Pair was already in CallSiteToFunctionMap");
115138 FunctionToCallSitesMap[F].insert(CallSite);
116139 }
117140
141164 FunctionToCallSitesMapTy::iterator F2C_I = FunctionToCallSitesMap.find(F);
142165 assert(F2C_I != FunctionToCallSitesMap.end() &&
143166 "FunctionToCallSitesMap broken");
144 assert(F2C_I->second.erase(Stub) &&
145 "FunctionToCallSitesMap broken");
167 bool Erased = F2C_I->second.erase(Stub);
168 (void)Erased;
169 assert(Erased && "FunctionToCallSitesMap broken");
146170 if (F2C_I->second.empty())
147171 FunctionToCallSitesMap.erase(F2C_I);
148172
151175
152176 void EraseAllCallSites(const MutexGuard &locked, Function *F) {
153177 assert(locked.holds(TheJIT->lock));
178 EraseAllCallSitesPrelocked(F);
179 }
180 void EraseAllCallSitesPrelocked(Function *F) {
154181 FunctionToCallSitesMapTy::iterator F2C = FunctionToCallSitesMap.find(F);
155182 if (F2C == FunctionToCallSitesMap.end())
156183 return;
157184 for (SmallPtrSet::const_iterator I = F2C->second.begin(),
158185 E = F2C->second.end(); I != E; ++I) {
159 assert(CallSiteToFunctionMap.erase(*I) == 1 &&
160 "Missing call site->function mapping");
186 bool Erased = CallSiteToFunctionMap.erase(*I);
187 (void)Erased;
188 assert(Erased && "Missing call site->function mapping");
161189 }
162190 FunctionToCallSitesMap.erase(F2C);
163191 }
243271 }
244272
245273 JITResolver *JITResolver::TheJITResolver = 0;
274
275 void CallSiteValueMapConfig::onDelete(JITResolverState *JRS, Function *F) {
276 JRS->EraseAllCallSitesPrelocked(F);
277 }
246278
247279 /// getFunctionStubIfAvailable - This returns a pointer to a function stub
248280 /// if it has already been created.
88
99 #include "gtest/gtest.h"
1010 #include "llvm/ADT/OwningPtr.h"
11 #include "llvm/Assembly/Parser.h"
1112 #include "llvm/BasicBlock.h"
1213 #include "llvm/Constant.h"
1314 #include "llvm/Constants.h"
2122 #include "llvm/Module.h"
2223 #include "llvm/ModuleProvider.h"
2324 #include "llvm/Support/IRBuilder.h"
25 #include "llvm/Support/SourceMgr.h"
2426 #include "llvm/Support/TypeBuilder.h"
2527 #include "llvm/Target/TargetSelect.h"
2628 #include "llvm/Type.h"
4850 protected:
4951 virtual void SetUp() {
5052 M = new Module("
", Context);
53 MP = new ExistingModuleProvider(M);
5154 std::string Error;
52 TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT)
55 TheJIT.reset(EngineBuilder(MP).setEngineKind(EngineKind::JIT)
5356 .setErrorStr(&Error).create());
5457 ASSERT_TRUE(TheJIT.get() != NULL) << Error;
5558 }
5659
60 void LoadAssembly(const char *assembly) {
61 SMDiagnostic Error;
62 bool success = NULL != ParseAssemblyString(assembly, M, Error, Context);
63 std::string errMsg;
64 raw_string_ostream os(errMsg);
65 Error.Print("", os);
66 ASSERT_TRUE(success) << os.str();
67 }
68
5769 LLVMContext Context;
58 Module *M; // Owned by ExecutionEngine.
70 Module *M; // Owned by MP.
71 ModuleProvider *MP; // Owned by ExecutionEngine.
5972 OwningPtr TheJIT;
6073 };
6174
263276 }
264277 #endif
265278
279 TEST_F(JITTest, ModuleDeletion) {
280 LoadAssembly("define void @main() { "
281 " call i32 @computeVal() "
282 " ret void "
283 "} "
284 " "
285 "define internal i32 @computeVal() { "
286 " ret i32 0 "
287 "} ");
288 Function *func = M->getFunction("main");
289 TheJIT->getPointerToFunction(func);
290 TheJIT->deleteModuleProvider(MP);
291 }
292
266293 // This code is copied from JITEventListenerTest, but it only runs once for all
267294 // the tests in this directory. Everything seems fine, but that's strange
268295 // behavior.
88
99 LEVEL = ../../..
1010 TESTNAME = JIT
11 LINK_COMPONENTS := core support jit native
11 LINK_COMPONENTS := asmparser core support jit native
1212
1313 include $(LEVEL)/Makefile.config
1414 include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest