Fix a couple issues with the JIT and multiple modules:
authorNate Begeman <natebegeman@mac.com>
Wed, 21 May 2008 16:34:48 +0000 (16:34 +0000)
committerNate Begeman <natebegeman@mac.com>
Wed, 21 May 2008 16:34:48 +0000 (16:34 +0000)
1. The "JITState" object creates a PassManager with the ModuleProvider that the
   jit is created with.  If the ModuleProvider is removed and deleted, the
   PassManager is invalid.

2. The Global maps in the JIT were not invalidated with a ModuleProvider was
   removed.  This could lead to a case where the Module would be freed, and a
   new Module with Globals at the same addresses could return invalid results.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51384 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ExecutionEngine/ExecutionEngine.h
lib/ExecutionEngine/ExecutionEngine.cpp
lib/ExecutionEngine/JIT/JIT.cpp
lib/ExecutionEngine/JIT/JIT.h

index ff584733eec654fa8003f208741b2dd6389f43c2..1159971a45b59e1653c33b4f156285ea45b49e74 100644 (file)
@@ -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
index 535f4ac90f70157ffbcc0a89c9dfe23db03e4769..8b94ad02840dc8e6fbe386c22601ab7e685f01c2 100644 (file)
@@ -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.
index 4b888ef018ce42c121557d1d1985d8b00eeb3d22..48286e915ee8698a94b2024e24e980a4f2b945ad 100644 (file)
@@ -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;
index 69e301bf6d04bdb8fb08e0c1c1cd33f6d645b211..7366f944365dce8c9dbe8d95a618611ee9c4049f 100644 (file)
@@ -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,