[llvm-commits] [llvm] r73575 - /llvm/trunk/lib/VMCore/Type.cpp

Owen Anderson resistor at mac.com
Tue Jun 16 15:51:19 PDT 2009


Author: resistor
Date: Tue Jun 16 17:51:18 2009
New Revision: 73575

URL: http://llvm.org/viewvc/llvm-project?rev=73575&view=rev
Log:
Use a reader-writer lock to guard large portions of the Type infrastructure, including abstract type refinement.
There's still some more work to be done here, such as guarding removeAbstractTypeUser() and the printers.

Modified:
    llvm/trunk/lib/VMCore/Type.cpp

Modified: llvm/trunk/lib/VMCore/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Type.cpp?rev=73575&r1=73574&r2=73575&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Type.cpp (original)
+++ llvm/trunk/lib/VMCore/Type.cpp Tue Jun 16 17:51:18 2009
@@ -23,6 +23,8 @@
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Threading.h"
+#include "llvm/System/RWMutex.h"
 #include <algorithm>
 #include <cstdarg>
 using namespace llvm;
@@ -40,6 +42,9 @@
 //                         Type Class Implementation
 //===----------------------------------------------------------------------===//
 
+// Reader/writer lock used for guarding access to the type maps.
+static ManagedStatic<sys::RWMutex> TypeMapLock;
+
 // Concrete/Abstract TypeDescriptions - We lazily calculate type descriptions
 // for types as they are needed.  Because resolution of types must invalidate
 // all of the abstract type descriptions, we keep them in a seperate map to make
@@ -848,7 +853,7 @@
         // We already have this type in the table.  Get rid of the newly refined
         // type.
         TypeClass *NewTy = cast<TypeClass>((Type*)I->second.get());
-        Ty->refineAbstractTypeTo(NewTy);
+        Ty->unlockedRefineAbstractTypeTo(NewTy);
         return;
       }
     } else {
@@ -884,7 +889,7 @@
               }
               TypesByHash.erase(Entry);
             }
-            Ty->refineAbstractTypeTo(NewTy);
+            Ty->unlockedRefineAbstractTypeTo(NewTy);
             return;
           }
         }
@@ -968,15 +973,40 @@
     default: 
       break;
   }
-
+  
   IntegerValType IVT(NumBits);
-  IntegerType *ITy = IntegerTypes->get(IVT);
-  if (ITy) return ITy;           // Found a match, return it!
-
-  // Value not found.  Derive a new type!
-  ITy = new IntegerType(NumBits);
-  IntegerTypes->add(IVT, ITy);
+  IntegerType *ITy = 0;
+  if (llvm_is_multithreaded()) {
+    // First, see if the type is already in the table, for which
+    // a reader lock suffices.
+    TypeMapLock->reader_acquire();
+    ITy = IntegerTypes->get(IVT);
+    TypeMapLock->reader_release();
+    
+    if (!ITy) {
+      // OK, not in the table, get a writer lock.
+      TypeMapLock->writer_acquire();
+      ITy = IntegerTypes->get(IVT);
+      
+      // We need to _recheck_ the table in case someone
+      // put it in between when we released the reader lock
+      // and when we gained the writer lock!
+      if (!ITy) {
+        // Value not found.  Derive a new type!
+        ITy = new IntegerType(NumBits);
+        IntegerTypes->add(IVT, ITy);
+      }
+      
+      TypeMapLock->writer_release();
+    }
+  } else {
+    ITy = IntegerTypes->get(IVT);
+    if (ITy) return ITy;           // Found a match, return it!
 
+    // Value not found.  Derive a new type!
+    ITy = new IntegerType(NumBits);
+    IntegerTypes->add(IVT, ITy);
+  }
 #ifdef DEBUG_MERGE_TYPES
   DOUT << "Derived new type: " << *ITy << "\n";
 #endif
@@ -1040,15 +1070,39 @@
                                 const std::vector<const Type*> &Params,
                                 bool isVarArg) {
   FunctionValType VT(ReturnType, Params, isVarArg);
-  FunctionType *FT = FunctionTypes->get(VT);
-  if (FT)
-    return FT;
-
-  FT = (FunctionType*) operator new(sizeof(FunctionType) +
-                                    sizeof(PATypeHandle)*(Params.size()+1));
-  new (FT) FunctionType(ReturnType, Params, isVarArg);
-  FunctionTypes->add(VT, FT);
-
+  FunctionType *FT = 0;
+  
+  if (llvm_is_multithreaded()) {
+    TypeMapLock->reader_acquire();
+    FT = FunctionTypes->get(VT);
+    TypeMapLock->reader_release();
+    
+    if (!FT) {
+      TypeMapLock->writer_acquire();
+      
+      // Have to check again here, because it might have
+      // been inserted between when we release the reader
+      // lock and when we acquired the writer lock.
+      FT = FunctionTypes->get(VT);
+      if (!FT) {
+        FT = (FunctionType*) operator new(sizeof(FunctionType) +
+                                        sizeof(PATypeHandle)*(Params.size()+1));
+        new (FT) FunctionType(ReturnType, Params, isVarArg);
+        FunctionTypes->add(VT, FT);
+      }
+      TypeMapLock->writer_release();
+    }
+  } else {
+    FT = FunctionTypes->get(VT);
+    if (FT)
+      return FT;
+
+    FT = (FunctionType*) operator new(sizeof(FunctionType) +
+                                      sizeof(PATypeHandle)*(Params.size()+1));
+    new (FT) FunctionType(ReturnType, Params, isVarArg);
+    FunctionTypes->add(VT, FT);
+  }
+  
 #ifdef DEBUG_MERGE_TYPES
   DOUT << "Derived new type: " << FT << "\n";
 #endif
@@ -1079,20 +1133,39 @@
   }
 };
 }
-static ManagedStatic<TypeMap<ArrayValType, ArrayType> > ArrayTypes;
 
+static ManagedStatic<TypeMap<ArrayValType, ArrayType> > ArrayTypes;
 
 ArrayType *ArrayType::get(const Type *ElementType, uint64_t NumElements) {
   assert(ElementType && "Can't get array of <null> types!");
   assert(isValidElementType(ElementType) && "Invalid type for array element!");
 
   ArrayValType AVT(ElementType, NumElements);
-  ArrayType *AT = ArrayTypes->get(AVT);
-  if (AT) return AT;           // Found a match, return it!
-
-  // Value not found.  Derive a new type!
-  ArrayTypes->add(AVT, AT = new ArrayType(ElementType, NumElements));
-
+  ArrayType *AT = 0;
+  
+  if (llvm_is_multithreaded()) {
+    TypeMapLock->reader_acquire();
+    AT = ArrayTypes->get(AVT);
+    TypeMapLock->reader_release();
+    
+    if (!AT) {
+      TypeMapLock->writer_acquire();
+      
+      // Recheck.  Might have changed between release and acquire.
+      AT = ArrayTypes->get(AVT);
+      if (!AT) {
+        // Value not found.  Derive a new type!
+        ArrayTypes->add(AVT, AT = new ArrayType(ElementType, NumElements));
+      }
+      TypeMapLock->writer_release();
+    }
+  } else {
+    AT = ArrayTypes->get(AVT);
+    if (AT) return AT;           // Found a match, return it!
+    
+    // Value not found.  Derive a new type!
+    ArrayTypes->add(AVT, AT = new ArrayType(ElementType, NumElements));
+  }
 #ifdef DEBUG_MERGE_TYPES
   DOUT << "Derived new type: " << *AT << "\n";
 #endif
@@ -1136,19 +1209,36 @@
   }
 };
 }
-static ManagedStatic<TypeMap<VectorValType, VectorType> > VectorTypes;
 
+static ManagedStatic<TypeMap<VectorValType, VectorType> > VectorTypes;
 
 VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) {
   assert(ElementType && "Can't get vector of <null> types!");
 
   VectorValType PVT(ElementType, NumElements);
-  VectorType *PT = VectorTypes->get(PVT);
-  if (PT) return PT;           // Found a match, return it!
-
-  // Value not found.  Derive a new type!
-  VectorTypes->add(PVT, PT = new VectorType(ElementType, NumElements));
-
+  VectorType *PT = 0;
+  
+  if (llvm_is_multithreaded()) {
+    TypeMapLock->reader_acquire();
+    PT = VectorTypes->get(PVT);
+    TypeMapLock->reader_release();
+    
+    if (!PT) {
+      TypeMapLock->writer_acquire();
+      PT = VectorTypes->get(PVT);
+      // Recheck.  Might have changed between release and acquire.
+      if (!PT) {
+        VectorTypes->add(PVT, PT = new VectorType(ElementType, NumElements));
+      }
+      TypeMapLock->writer_acquire();
+    }
+  } else {
+    PT = VectorTypes->get(PVT);
+    if (PT) return PT;           // Found a match, return it!
+    
+    // Value not found.  Derive a new type!
+    VectorTypes->add(PVT, PT = new VectorType(ElementType, NumElements));
+  }
 #ifdef DEBUG_MERGE_TYPES
   DOUT << "Derived new type: " << *PT << "\n";
 #endif
@@ -1203,15 +1293,36 @@
 StructType *StructType::get(const std::vector<const Type*> &ETypes, 
                             bool isPacked) {
   StructValType STV(ETypes, isPacked);
-  StructType *ST = StructTypes->get(STV);
-  if (ST) return ST;
-
-  // Value not found.  Derive a new type!
-  ST = (StructType*) operator new(sizeof(StructType) +
-                                  sizeof(PATypeHandle) * ETypes.size());
-  new (ST) StructType(ETypes, isPacked);
-  StructTypes->add(STV, ST);
-
+  StructType *ST = 0;
+  
+  if (llvm_is_multithreaded()) {
+    TypeMapLock->reader_acquire();
+    ST = StructTypes->get(STV);
+    TypeMapLock->reader_release();
+    
+    if (!ST) {
+      TypeMapLock->writer_acquire();
+      ST = StructTypes->get(STV);
+      // Recheck.  Might have changed between release and acquire.
+      if (!ST) {
+        // Value not found.  Derive a new type!
+        ST = (StructType*) operator new(sizeof(StructType) +
+                                        sizeof(PATypeHandle) * ETypes.size());
+        new (ST) StructType(ETypes, isPacked);
+        StructTypes->add(STV, ST);
+      }
+      TypeMapLock->writer_release();
+    }
+  } else {
+    ST = StructTypes->get(STV);
+    if (ST) return ST;
+    
+    // Value not found.  Derive a new type!
+    ST = (StructType*) operator new(sizeof(StructType) +
+                                    sizeof(PATypeHandle) * ETypes.size());
+    new (ST) StructType(ETypes, isPacked);
+    StructTypes->add(STV, ST);
+  }
 #ifdef DEBUG_MERGE_TYPES
   DOUT << "Derived new type: " << *ST << "\n";
 #endif
@@ -1279,12 +1390,30 @@
   assert(isValidElementType(ValueType) && "Invalid type for pointer element!");
   PointerValType PVT(ValueType, AddressSpace);
 
-  PointerType *PT = PointerTypes->get(PVT);
-  if (PT) return PT;
-
-  // Value not found.  Derive a new type!
-  PointerTypes->add(PVT, PT = new PointerType(ValueType, AddressSpace));
-
+  PointerType *PT = 0;
+  
+  if (llvm_is_multithreaded()) {
+    TypeMapLock->reader_acquire();
+    PT = PointerTypes->get(PVT);
+    TypeMapLock->reader_release();
+    
+    if (!PT) {
+      TypeMapLock->writer_acquire();
+      PT = PointerTypes->get(PVT);
+      // Recheck.  Might have changed between release and acquire.
+      if (!PT) {
+        // Value not found.  Derive a new type!
+        PointerTypes->add(PVT, PT = new PointerType(ValueType, AddressSpace));
+      }
+      TypeMapLock->writer_release();
+    }
+  } else {
+    PT = PointerTypes->get(PVT);
+    if (PT) return PT;
+    
+    // Value not found.  Derive a new type!
+    PointerTypes->add(PVT, PT = new PointerType(ValueType, AddressSpace));
+  }
 #ifdef DEBUG_MERGE_TYPES
   DOUT << "Derived new type: " << *PT << "\n";
 #endif
@@ -1344,12 +1473,13 @@
   }
 }
 
-// refineAbstractTypeTo - This function is used when it is discovered that
-// the 'this' abstract type is actually equivalent to the NewType specified.
-// This causes all users of 'this' to switch to reference the more concrete type
-// NewType and for 'this' to be deleted.
+// unlockedRefineAbstractTypeTo - This function is used when it is discovered
+// that the 'this' abstract type is actually equivalent to the NewType
+// specified. This causes all users of 'this' to switch to reference the more 
+// concrete type NewType and for 'this' to be deleted.  Only used for internal
+// callers.
 //
-void DerivedType::refineAbstractTypeTo(const Type *NewType) {
+void DerivedType::unlockedRefineAbstractTypeTo(const Type *NewType) {
   assert(isAbstract() && "refineAbstractTypeTo: Current type is not abstract!");
   assert(this != NewType && "Can't refine to myself!");
   assert(ForwardType == 0 && "This type has already been refined!");
@@ -1368,8 +1498,7 @@
   // refined, that we will not continue using a dead reference...
   //
   PATypeHolder NewTy(NewType);
-
-  // Any PATypeHolders referring to this type will now automatically forward to
+  // Any PATypeHolders referring to this type will now automatically forward o
   // the type we are resolved to.
   ForwardType = NewType;
   if (NewType->isAbstract())
@@ -1414,6 +1543,21 @@
   // destroyed.
 }
 
+// refineAbstractTypeTo - This function is used by external callers to notify
+// us that this abstract type is equivalent to another type.
+//
+void DerivedType::refineAbstractTypeTo(const Type *NewType) {
+  if (llvm_is_multithreaded()) {
+    // All recursive calls will go through unlockedRefineAbstractTypeTo,
+    // to avoid deadlock problems.
+    TypeMapLock->writer_acquire();
+    unlockedRefineAbstractTypeTo(NewType);
+    TypeMapLock->writer_release();
+  } else {
+    unlockedRefineAbstractTypeTo(NewType);
+  }
+}
+
 // notifyUsesThatTypeBecameConcrete - Notify AbstractTypeUsers of this type that
 // the current type has transitioned from being abstract to being concrete.
 //





More information about the llvm-commits mailing list