forked from OSchip/llvm-project
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). llvm-svn: 80590
This commit is contained in:
parent
487d576020
commit
d18e668fbc
|
@ -576,6 +576,14 @@ public:
|
||||||
typename MapTy::iterator map_begin() { return Map.begin(); }
|
typename MapTy::iterator map_begin() { return Map.begin(); }
|
||||||
typename MapTy::iterator map_end() { return Map.end(); }
|
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.
|
/// InsertOrGetItem - Return an iterator for the specified element.
|
||||||
/// If the element exists in the map, the returned iterator points to the
|
/// If the element exists in the map, the returned iterator points to the
|
||||||
/// entry and Exists=true. If not, the iterator points to the newly
|
/// entry and Exists=true. If not, the iterator points to the newly
|
||||||
|
|
|
@ -96,7 +96,6 @@ struct DenseMapAPFloatKeyInfo {
|
||||||
class LLVMContextImpl {
|
class LLVMContextImpl {
|
||||||
public:
|
public:
|
||||||
sys::SmartRWMutex<true> ConstantsLock;
|
sys::SmartRWMutex<true> ConstantsLock;
|
||||||
|
|
||||||
typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt*,
|
typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt*,
|
||||||
DenseMapAPIntKeyInfo> IntMapTy;
|
DenseMapAPIntKeyInfo> IntMapTy;
|
||||||
IntMapTy IntConstants;
|
IntMapTy IntConstants;
|
||||||
|
@ -196,6 +195,28 @@ public:
|
||||||
Int16Ty(C, 16),
|
Int16Ty(C, 16),
|
||||||
Int32Ty(C, 32),
|
Int32Ty(C, 32),
|
||||||
Int64Ty(C, 64) { }
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -500,7 +500,7 @@ void DerivedType::dropAllTypeUses() {
|
||||||
|
|
||||||
llvm_release_global_lock();
|
llvm_release_global_lock();
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!AlwaysOpaqueTy) {
|
||||||
AlwaysOpaqueTy = OpaqueType::get(getContext());
|
AlwaysOpaqueTy = OpaqueType::get(getContext());
|
||||||
Holder = new PATypeHolder(AlwaysOpaqueTy);
|
Holder = new PATypeHolder(AlwaysOpaqueTy);
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,7 +221,6 @@ public:
|
||||||
// PATypeHolder won't destroy non-abstract types.
|
// PATypeHolder won't destroy non-abstract types.
|
||||||
// We can't destroy them by simply iterating, because
|
// We can't destroy them by simply iterating, because
|
||||||
// they may contain references to each-other.
|
// they may contain references to each-other.
|
||||||
#if 0
|
|
||||||
for (std::multimap<unsigned, PATypeHolder>::iterator I
|
for (std::multimap<unsigned, PATypeHolder>::iterator I
|
||||||
= TypesByHash.begin(), E = TypesByHash.end(); I != E; ++I) {
|
= TypesByHash.begin(), E = TypesByHash.end(); I != E; ++I) {
|
||||||
Type *Ty = const_cast<Type*>(I->second.Ty);
|
Type *Ty = const_cast<Type*>(I->second.Ty);
|
||||||
|
@ -235,7 +234,6 @@ public:
|
||||||
operator delete(Ty);
|
operator delete(Ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveFromTypesByHash(unsigned Hash, const Type *Ty) {
|
void RemoveFromTypesByHash(unsigned Hash, const Type *Ty) {
|
||||||
|
|
Loading…
Reference in New Issue