Free the constants that have no uses in ~LLVMContext.

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
This commit is contained in:
Torok Edwin 2009-08-31 16:14:59 +00:00
parent 72ddf7b555
commit 2cd5155c0e
4 changed files with 31 additions and 4 deletions

View 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

View 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;
}
}
};
}

View File

@ -500,7 +500,7 @@ void DerivedType::dropAllTypeUses() {
llvm_release_global_lock();
}
} else {
} else if (!AlwaysOpaqueTy) {
AlwaysOpaqueTy = OpaqueType::get(getContext());
Holder = new PATypeHolder(AlwaysOpaqueTy);
}

View 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) {