/// 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);
}
/// 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
/// 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
ModuleProvider *MP = *I;
if (MP == P) {
Modules.erase(I);
+ clearGlobalMappingsFromModule(MP->getModule());
return MP->releaseModule(ErrInfo);
}
}
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.
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
}
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,
// 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);
}
}
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;
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);
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,