Free the constants that have no uses in ~LLVMContext.
authorTorok Edwin <edwintorok@gmail.com>
Mon, 31 Aug 2009 16:14:59 +0000 (16:14 +0000)
committerTorok Edwin <edwintorok@gmail.com>
Mon, 31 Aug 2009 16:14:59 +0000 (16:14 +0000)
This fixes leaks from LLVMContext in multithreaded apps.
Since constants are only deleted if they have no uses, it is safe to not delete
a Module on shutdown, as many single-threaded tools do.
Multithreaded apps should however delete the Module before destroying the
Context to ensure that there are no leaks (assuming they use a different context
for each thread).

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

lib/VMCore/ConstantsContext.h
lib/VMCore/LLVMContextImpl.h
lib/VMCore/Type.cpp
lib/VMCore/TypesContext.h

index 22aba7e..f4a2cde 100644 (file)
@@ -575,6 +575,14 @@ public:
   // to enforce proper synchronization.
   typename MapTy::iterator map_begin() { return Map.begin(); }
   typename MapTy::iterator map_end() { return Map.end(); }
+
+  void freeConstants() {
+    for (typename MapTy::iterator I=Map.begin(), E=Map.end();
+         I != E; ++I) {
+      if (I->second->use_empty())
+        delete I->second;
+    }
+  }
     
   /// InsertOrGetItem - Return an iterator for the specified element.
   /// If the element exists in the map, the returned iterator points to the
index 4016c0a..2faf6ac 100644 (file)
@@ -96,7 +96,6 @@ struct DenseMapAPFloatKeyInfo {
 class LLVMContextImpl {
 public:
   sys::SmartRWMutex<true> ConstantsLock;
-  
   typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt*, 
                          DenseMapAPIntKeyInfo> IntMapTy;
   IntMapTy IntConstants;
@@ -196,6 +195,28 @@ public:
     Int16Ty(C, 16),
     Int32Ty(C, 32),
     Int64Ty(C, 64) { }
+
+  ~LLVMContextImpl()
+  {
+    ExprConstants.freeConstants();
+    ArrayConstants.freeConstants();
+    StructConstants.freeConstants();
+    VectorConstants.freeConstants();
+
+    AggZeroConstants.freeConstants();
+    NullPtrConstants.freeConstants();
+    UndefValueConstants.freeConstants();
+    for (IntMapTy::iterator I=IntConstants.begin(), E=IntConstants.end(); 
+         I != E; ++I) {
+      if (I->second->use_empty())
+        delete I->second;
+    }
+    for (FPMapTy::iterator I=FPConstants.begin(), E=FPConstants.end(); 
+         I != E; ++I) {
+      if (I->second->use_empty())
+        delete I->second;
+    }
+  }
 };
 
 }
index 696ac96..ba190d9 100644 (file)
@@ -500,7 +500,7 @@ void DerivedType::dropAllTypeUses() {
       
         llvm_release_global_lock();
       }
-    } else {
+    } else if (!AlwaysOpaqueTy) {
       AlwaysOpaqueTy = OpaqueType::get(getContext());
       Holder = new PATypeHolder(AlwaysOpaqueTy);
     } 
index 2a287fe..e7950bd 100644 (file)
@@ -221,7 +221,6 @@ public:
     // PATypeHolder won't destroy non-abstract types.
     // We can't destroy them by simply iterating, because
     // they may contain references to each-other.
-#if 0
     for (std::multimap<unsigned, PATypeHolder>::iterator I
          = TypesByHash.begin(), E = TypesByHash.end(); I != E; ++I) {
       Type *Ty = const_cast<Type*>(I->second.Ty);
@@ -235,7 +234,6 @@ public:
         operator delete(Ty);
       }
     }
-#endif
   }
 
   void RemoveFromTypesByHash(unsigned Hash, const Type *Ty) {