diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index ff584733eec..1159971a45b 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -126,7 +126,7 @@ public: /// addModuleProvider - Add a ModuleProvider to the list of modules that we /// can JIT from. Note that this takes ownership of the ModuleProvider: when /// the ExecutionEngine is destroyed, it destroys the MP as well. - void addModuleProvider(ModuleProvider *P) { + virtual void addModuleProvider(ModuleProvider *P) { Modules.push_back(P); } @@ -137,7 +137,8 @@ public: /// removeModuleProvider - Remove a ModuleProvider from the list of modules. /// Release module from ModuleProvider. - Module* removeModuleProvider(ModuleProvider *P, std::string *ErrInfo = 0); + virtual Module* removeModuleProvider(ModuleProvider *P, + std::string *ErrInfo = 0); /// FindFunctionNamed - Search all of the active modules to find the one that /// defines FnName. This is very slow operation and shouldn't be used for @@ -174,6 +175,10 @@ public: /// use in dynamic compilation scenarios when you want to move globals void clearAllGlobalMappings(); + /// clearGlobalMappingsFromModule - Clear all global mappings that came from a + /// particular module, because it has been removed from the JIT. + void clearGlobalMappingsFromModule(Module *M); + /// updateGlobalMapping - Replace an existing mapping for GV with a new /// address. This updates both maps as required. If "Addr" is null, the /// entry for the global is removed from the mappings. This returns the old diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 535f4ac90f7..8b94ad02840 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -59,6 +59,7 @@ Module* ExecutionEngine::removeModuleProvider(ModuleProvider *P, ModuleProvider *MP = *I; if (MP == P) { Modules.erase(I); + clearGlobalMappingsFromModule(MP->getModule()); return MP->releaseModule(ErrInfo); } } @@ -106,6 +107,22 @@ void ExecutionEngine::clearAllGlobalMappings() { state.getGlobalAddressReverseMap(locked).clear(); } +/// clearGlobalMappingsFromModule - Clear all global mappings that came from a +/// particular module, because it has been removed from the JIT. +void ExecutionEngine::clearGlobalMappingsFromModule(Module *M) { + MutexGuard locked(lock); + + for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ++FI) { + state.getGlobalAddressMap(locked).erase(FI); + state.getGlobalAddressReverseMap(locked).erase(FI); + } + for (Module::global_iterator GI = M->global_begin(), GE = M->global_end(); + GI != GE; ++GI) { + state.getGlobalAddressMap(locked).erase(GI); + state.getGlobalAddressReverseMap(locked).erase(GI); + } +} + /// updateGlobalMapping - Replace an existing mapping for GV with a new /// address. This updates both maps as required. If "Addr" is null, the /// entry for the global is removed from the mappings. diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp index 4b888ef018c..48286e915ee 100644 --- a/lib/ExecutionEngine/JIT/JIT.cpp +++ b/lib/ExecutionEngine/JIT/JIT.cpp @@ -91,15 +91,17 @@ ExecutionEngine *ExecutionEngine::createJIT(ModuleProvider *MP, JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji, JITMemoryManager *JMM) - : ExecutionEngine(MP), TM(tm), TJI(tji), jitstate(MP) { + : ExecutionEngine(MP), TM(tm), TJI(tji) { setTargetData(TM.getTargetData()); + jitstate = new JITState(MP); + // Initialize MCE MCE = createEmitter(*this, JMM); // Add target data MutexGuard locked(lock); - FunctionPassManager &PM = jitstate.getPM(locked); + FunctionPassManager &PM = jitstate->getPM(locked); PM.add(new TargetData(*TM.getTargetData())); // Turn the machine code intermediate representation into bytes in memory that @@ -114,10 +116,54 @@ JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji, } JIT::~JIT() { + delete jitstate; delete MCE; delete &TM; } +/// addModuleProvider - Add a new ModuleProvider to the JIT. If we previously +/// removed the last ModuleProvider, we need re-initialize jitstate with a valid +/// ModuleProvider. +void JIT::addModuleProvider(ModuleProvider *MP) { + MutexGuard locked(lock); + + if (Modules.empty()) { + assert(!jitstate && "jitstate should be NULL if Modules vector is empty!"); + + jitstate = new JITState(MP); + + FunctionPassManager &PM = jitstate->getPM(locked); + PM.add(new TargetData(*TM.getTargetData())); + + // Turn the machine code intermediate representation into bytes in memory + // that may be executed. + if (TM.addPassesToEmitMachineCode(PM, *MCE, false /*fast*/)) { + cerr << "Target does not support machine code emission!\n"; + abort(); + } + + // Initialize passes. + PM.doInitialization(); + } + + ExecutionEngine::addModuleProvider(MP); +} + +/// removeModuleProvider - If we are removing the last ModuleProvider, +/// invalidate the jitstate since the PassManager it contains references a +/// released ModuleProvider. +Module *JIT::removeModuleProvider(ModuleProvider *MP, std::string *E) { + Module *result = ExecutionEngine::removeModuleProvider(MP, E); + + MutexGuard locked(lock); + if (Modules.empty()) { + delete jitstate; + jitstate = 0; + } + + return result; +} + /// run - Start execution with the specified function and arguments. /// GenericValue JIT::runFunction(Function *F, @@ -289,15 +335,15 @@ void JIT::runJITOnFunction(Function *F) { // JIT the function isAlreadyCodeGenerating = true; - jitstate.getPM(locked).run(*F); + jitstate->getPM(locked).run(*F); isAlreadyCodeGenerating = false; // If the function referred to a global variable that had not yet been // emitted, it allocates memory for the global, but doesn't emit it yet. Emit // all of these globals now. - while (!jitstate.getPendingGlobals(locked).empty()) { - const GlobalVariable *GV = jitstate.getPendingGlobals(locked).back(); - jitstate.getPendingGlobals(locked).pop_back(); + while (!jitstate->getPendingGlobals(locked).empty()) { + const GlobalVariable *GV = jitstate->getPendingGlobals(locked).back(); + jitstate->getPendingGlobals(locked).pop_back(); EmitGlobalVariable(GV); } } @@ -387,7 +433,7 @@ void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) { unsigned MisAligned = ((intptr_t)Ptr & (A-1)); Ptr = (char*)Ptr + (MisAligned ? (A-MisAligned) : 0); } - jitstate.getPendingGlobals(locked).push_back(GV); + jitstate->getPendingGlobals(locked).push_back(GV); } addGlobalMapping(GV, Ptr); return Ptr; diff --git a/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h index 69e301bf6d0..7366f944365 100644 --- a/lib/ExecutionEngine/JIT/JIT.h +++ b/lib/ExecutionEngine/JIT/JIT.h @@ -54,7 +54,7 @@ class JIT : public ExecutionEngine { TargetJITInfo &TJI; // The JITInfo for the target we are compiling to MachineCodeEmitter *MCE; // MCE object - JITState jitstate; + JITState *jitstate; JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji, JITMemoryManager *JMM); @@ -76,6 +76,10 @@ public: return createJIT(MP, Err, 0); } + virtual void addModuleProvider(ModuleProvider *MP); + virtual Module *removeModuleProvider(ModuleProvider *MP, + std::string *ErrInfo = 0); + /// run - Start execution with the specified function and arguments. /// virtual GenericValue runFunction(Function *F,