[llvm-commits] CVS: llvm/lib/ExecutionEngine/JIT/JIT.cpp JIT.h JITEmitter.cpp

Reid Spencer reid at x10sys.com
Tue Jul 12 08:52:08 PDT 2005



Changes in directory llvm/lib/ExecutionEngine/JIT:

JIT.cpp updated: 1.55 -> 1.56
JIT.h updated: 1.26 -> 1.27
JITEmitter.cpp updated: 1.67 -> 1.68
---
Log message:

For PR540: http://llvm.cs.uiuc.edu/PR540 :
This patch completes the changes for making lli thread-safe. Here's the list
of changes:
* The Support/ThreadSupport* files were removed and replaced with the 
  MutexGuard.h file since all ThreadSupport* declared was a Mutex Guard.
  The implementation of MutexGuard.h is now based on sys::Mutex which hides
  its implementation and makes it unnecessary to have the -NoSupport.h and
  -PThreads.h versions of ThreadSupport.

* All places in ExecutionEngine that previously referred to "Mutex" now 
  refer to sys::Mutex

* All places in ExecutionEngine that previously referred to "MutexLocker"
  now refer to MutexGuard (this is frivolous but I believe the technically
  correct name for such a class is "Guard" not a "Locker"). 

These changes passed all of llvm-test. All we need now are some test cases
that actually use multiple threads.



---
Diffs of the changes:  (+76 -27)

 JIT.cpp        |   20 ++++++++++++++------
 JIT.h          |   27 ++++++++++++++++++++++-----
 JITEmitter.cpp |   56 ++++++++++++++++++++++++++++++++++++++++----------------
 3 files changed, 76 insertions(+), 27 deletions(-)


Index: llvm/lib/ExecutionEngine/JIT/JIT.cpp
diff -u llvm/lib/ExecutionEngine/JIT/JIT.cpp:1.55 llvm/lib/ExecutionEngine/JIT/JIT.cpp:1.56
--- llvm/lib/ExecutionEngine/JIT/JIT.cpp:1.55	Fri May  6 01:48:54 2005
+++ llvm/lib/ExecutionEngine/JIT/JIT.cpp	Tue Jul 12 10:51:55 2005
@@ -30,13 +30,15 @@
 using namespace llvm;
 
 JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji)
-  : ExecutionEngine(MP), TM(tm), TJI(tji), PM(MP) {
+  : ExecutionEngine(MP), TM(tm), TJI(tji), state(MP) {
   setTargetData(TM.getTargetData());
 
   // Initialize MCE
   MCE = createEmitter(*this);
 
   // Add target data
+  MutexGuard locked(lock);
+  FunctionPassManager& PM = state.getPM(locked);
   PM.add(new TargetData(TM.getTargetData()));
 
   // Compile LLVM Code down to machine code in the intermediate representation
@@ -216,18 +218,20 @@
 void JIT::runJITOnFunction(Function *F) {
   static bool isAlreadyCodeGenerating = false;
   assert(!isAlreadyCodeGenerating && "Error: Recursive compilation detected!");
+	
+  MutexGuard locked(lock);
 
   // JIT the function
   isAlreadyCodeGenerating = true;
-  PM.run(*F);
+  state.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 (!PendingGlobals.empty()) {
-    const GlobalVariable *GV = PendingGlobals.back();
-    PendingGlobals.pop_back();
+  while (!state.getPendingGlobals(locked).empty()) {
+    const GlobalVariable *GV = state.getPendingGlobals(locked).back();
+    state.getPendingGlobals(locked).pop_back();
     EmitGlobalVariable(GV);
   }
 }
@@ -236,6 +240,8 @@
 /// specified function, compiling it if neccesary.
 ///
 void *JIT::getPointerToFunction(Function *F) {
+  MutexGuard locked(lock);
+
   if (void *Addr = getPointerToGlobalIfAvailable(F))
     return Addr;   // Check if function already code gen'd
 
@@ -270,6 +276,8 @@
 /// variable, possibly emitting it to memory if needed.  This is used by the
 /// Emitter.
 void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) {
+  MutexGuard locked(lock);
+
   void *Ptr = getPointerToGlobalIfAvailable(GV);
   if (Ptr) return Ptr;
 
@@ -287,7 +295,7 @@
     // compilation.
     uint64_t S = getTargetData().getTypeSize(GV->getType()->getElementType());
     Ptr = new char[(size_t)S];
-    PendingGlobals.push_back(GV);
+    state.getPendingGlobals(locked).push_back(GV);
   }
   addGlobalMapping(GV, Ptr);
   return Ptr;


Index: llvm/lib/ExecutionEngine/JIT/JIT.h
diff -u llvm/lib/ExecutionEngine/JIT/JIT.h:1.26 llvm/lib/ExecutionEngine/JIT/JIT.h:1.27
--- llvm/lib/ExecutionEngine/JIT/JIT.h:1.26	Thu Apr 21 17:45:04 2005
+++ llvm/lib/ExecutionEngine/JIT/JIT.h	Tue Jul 12 10:51:55 2005
@@ -27,18 +27,35 @@
 class TargetJITInfo;
 class MachineCodeEmitter;
 
-class JIT : public ExecutionEngine {
-  TargetMachine &TM;       // The current target we are compiling to
-  TargetJITInfo &TJI;      // The JITInfo for the target we are compiling to
-
+class JITState {
+private:
   FunctionPassManager PM;  // Passes to compile a function
-  MachineCodeEmitter *MCE; // MCE object
 
   /// PendingGlobals - Global variables which have had memory allocated for them
   /// while a function was code generated, but which have not been initialized
   /// yet.
   std::vector<const GlobalVariable*> PendingGlobals;
 
+public:
+  JITState(ModuleProvider *MP) : PM(MP) {}
+
+  FunctionPassManager& getPM(const MutexGuard& locked) {
+    return PM;
+  }
+
+  std::vector<const GlobalVariable*>& getPendingGlobals(const MutexGuard& locked) {
+    return PendingGlobals;
+  }
+};
+
+
+class JIT : public ExecutionEngine {
+  TargetMachine &TM;       // The current target we are compiling to
+  TargetJITInfo &TJI;      // The JITInfo for the target we are compiling to
+  MachineCodeEmitter *MCE; // MCE object
+
+  JITState state;
+
   JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji);
 public:
   ~JIT();


Index: llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp
diff -u llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp:1.67 llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp:1.68
--- llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp:1.67	Thu Apr 21 23:06:43 2005
+++ llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp	Tue Jul 12 10:51:55 2005
@@ -120,6 +120,28 @@
 // JIT lazy compilation code.
 //
 namespace {
+  class JITResolverState {
+  private:
+    /// FunctionToStubMap - Keep track of the stub created for a particular
+    /// function so that we can reuse them if necessary.
+    std::map<Function*, void*> FunctionToStubMap;
+
+    /// StubToFunctionMap - Keep track of the function that each stub
+    /// corresponds to.
+    std::map<void*, Function*> StubToFunctionMap;
+  
+  public:
+    std::map<Function*, void*>& getFunctionToStubMap(const MutexGuard& locked) {
+      assert(locked.holds(TheJIT->lock));
+      return FunctionToStubMap;
+    }
+    
+    std::map<void*, Function*>& getStubToFunctionMap(const MutexGuard& locked) {
+      assert(locked.holds(TheJIT->lock));
+      return StubToFunctionMap;
+    }
+  };
+  
   /// JITResolver - Keep track of, and resolve, call sites for functions that
   /// have not yet been compiled.
   class JITResolver {
@@ -130,13 +152,7 @@
     /// rewrite instructions to use.
     TargetJITInfo::LazyResolverFn LazyResolverFn;
 
-    // FunctionToStubMap - Keep track of the stub created for a particular
-    // function so that we can reuse them if necessary.
-    std::map<Function*, void*> FunctionToStubMap;
-
-    // StubToFunctionMap - Keep track of the function that each stub corresponds
-    // to.
-    std::map<void*, Function*> StubToFunctionMap;
+    JITResolverState state;
 
     /// ExternalFnToStubMap - This is the equivalent of FunctionToStubMap for
     /// external functions.
@@ -159,8 +175,9 @@
     /// instruction without the use of a stub, record the location of the use so
     /// we know which function is being used at the location.
     void *AddCallbackAtLocation(Function *F, void *Location) {
+      MutexGuard locked(TheJIT->lock);
       /// Get the target-specific JIT resolver function.
-      StubToFunctionMap[Location] = F;
+      state.getStubToFunctionMap(locked)[Location] = F;
       return (void*)LazyResolverFn;
     }
 
@@ -181,8 +198,10 @@
 /// getFunctionStub - This returns a pointer to a function stub, creating
 /// one on demand as needed.
 void *JITResolver::getFunctionStub(Function *F) {
+  MutexGuard locked(TheJIT->lock);
+
   // If we already have a stub for this function, recycle it.
-  void *&Stub = FunctionToStubMap[F];
+  void *&Stub = state.getFunctionToStubMap(locked)[F];
   if (Stub) return Stub;
 
   // Call the lazy resolver function unless we already KNOW it is an external
@@ -207,7 +226,7 @@
 
   // Finally, keep track of the stub-to-Function mapping so that the
   // JITCompilerFn knows which function to compile!
-  StubToFunctionMap[Stub] = F;
+  state.getStubToFunctionMap(locked)[Stub] = F;
   return Stub;
 }
 
@@ -231,16 +250,21 @@
 void *JITResolver::JITCompilerFn(void *Stub) {
   JITResolver &JR = getJITResolver();
 
+  MutexGuard locked(TheJIT->lock);
+
   // The address given to us for the stub may not be exactly right, it might be
   // a little bit after the stub.  As such, use upper_bound to find it.
   std::map<void*, Function*>::iterator I =
-    JR.StubToFunctionMap.upper_bound(Stub);
-  assert(I != JR.StubToFunctionMap.begin() && "This is not a known stub!");
+    JR.state.getStubToFunctionMap(locked).upper_bound(Stub);
+  assert(I != JR.state.getStubToFunctionMap(locked).begin() && "This is not a known stub!");
   Function *F = (--I)->second;
 
-  // The target function will rewrite the stub so that the compilation callback
-  // function is no longer called from this stub.
-  JR.StubToFunctionMap.erase(I);
+  // We might like to remove the stub from the StubToFunction map.
+  // We can't do that! Multiple threads could be stuck, waiting to acquire the
+  // lock above. As soon as the 1st function finishes compiling the function,
+  // the next one will be released, and needs to be able to find the function it needs
+  // to call.
+  //JR.state.getStubToFunctionMap(locked).erase(I);
 
   DEBUG(std::cerr << "JIT: Lazily resolving function '" << F->getName()
                   << "' In stub ptr = " << Stub << " actual ptr = "
@@ -249,7 +273,7 @@
   void *Result = TheJIT->getPointerToFunction(F);
 
   // We don't need to reuse this stub in the future, as F is now compiled.
-  JR.FunctionToStubMap.erase(F);
+  JR.state.getFunctionToStubMap(locked).erase(F);
 
   // FIXME: We could rewrite all references to this stub if we knew them.
   return Result;






More information about the llvm-commits mailing list