mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
Fix PR7972, in which the PassRegistry was being leaked. As part of this,
switch to using a ManagedStatic for the global PassRegistry instead of a ManagedCleanup, and fix a destruction ordering bug this exposed. llvm-svn: 113283
This commit is contained in:
parent
92dd0fd9ba
commit
94ae132fc8
@ -37,6 +37,7 @@ class PassRegistry {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
PassRegistry() : pImpl(0) { }
|
PassRegistry() : pImpl(0) { }
|
||||||
|
~PassRegistry();
|
||||||
|
|
||||||
/// getPassRegistry - Access the global registry object, which is
|
/// getPassRegistry - Access the global registry object, which is
|
||||||
/// automatically initialized at application launch and destroyed by
|
/// automatically initialized at application launch and destroyed by
|
||||||
|
@ -22,45 +22,14 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
static PassRegistry *PassRegistryObj = 0;
|
// FIXME: We use ManagedStatic to erase the pass registrar on shutdown.
|
||||||
PassRegistry *PassRegistry::getPassRegistry() {
|
|
||||||
// Use double-checked locking to safely initialize the registrar when
|
|
||||||
// we're running in multithreaded mode.
|
|
||||||
PassRegistry* tmp = PassRegistryObj;
|
|
||||||
if (llvm_is_multithreaded()) {
|
|
||||||
sys::MemoryFence();
|
|
||||||
if (!tmp) {
|
|
||||||
llvm_acquire_global_lock();
|
|
||||||
tmp = PassRegistryObj;
|
|
||||||
if (!tmp) {
|
|
||||||
tmp = new PassRegistry();
|
|
||||||
sys::MemoryFence();
|
|
||||||
PassRegistryObj = tmp;
|
|
||||||
}
|
|
||||||
llvm_release_global_lock();
|
|
||||||
}
|
|
||||||
} else if (!tmp) {
|
|
||||||
PassRegistryObj = new PassRegistry();
|
|
||||||
}
|
|
||||||
|
|
||||||
return PassRegistryObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// FIXME: We use ManagedCleanup to erase the pass registrar on shutdown.
|
|
||||||
// Unfortunately, passes are registered with static ctors, and having
|
// Unfortunately, passes are registered with static ctors, and having
|
||||||
// llvm_shutdown clear this map prevents successful ressurection after
|
// llvm_shutdown clear this map prevents successful ressurection after
|
||||||
// llvm_shutdown is run. Ideally we should find a solution so that we don't
|
// llvm_shutdown is run. Ideally we should find a solution so that we don't
|
||||||
// leak the map, AND can still resurrect after shutdown.
|
// leak the map, AND can still resurrect after shutdown.
|
||||||
void cleanupPassRegistry(void*) {
|
static ManagedStatic<PassRegistry> PassRegistryObj;
|
||||||
if (PassRegistryObj) {
|
PassRegistry *PassRegistry::getPassRegistry() {
|
||||||
delete PassRegistryObj;
|
return &*PassRegistryObj;
|
||||||
PassRegistryObj = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ManagedCleanup<&cleanupPassRegistry> registryCleanup ATTRIBUTE_USED;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -94,6 +63,12 @@ void *PassRegistry::getImpl() const {
|
|||||||
// Accessors
|
// Accessors
|
||||||
//
|
//
|
||||||
|
|
||||||
|
PassRegistry::~PassRegistry() {
|
||||||
|
PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(pImpl);
|
||||||
|
if (Impl) delete Impl;
|
||||||
|
pImpl = 0;
|
||||||
|
}
|
||||||
|
|
||||||
const PassInfo *PassRegistry::getPassInfo(const void *TI) const {
|
const PassInfo *PassRegistry::getPassInfo(const void *TI) const {
|
||||||
PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
|
PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
|
||||||
PassRegistryImpl::MapType::const_iterator I = Impl->PassInfoMap.find(TI);
|
PassRegistryImpl::MapType::const_iterator I = Impl->PassInfoMap.find(TI);
|
||||||
@ -188,6 +163,12 @@ void PassRegistry::addRegistrationListener(PassRegistrationListener *L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PassRegistry::removeRegistrationListener(PassRegistrationListener *L) {
|
void PassRegistry::removeRegistrationListener(PassRegistrationListener *L) {
|
||||||
|
// NOTE: This is necessary, because removeRegistrationListener() can be called
|
||||||
|
// as part of the llvm_shutdown sequence. Since we have no control over the
|
||||||
|
// order of that sequence, we need to gracefully handle the case where the
|
||||||
|
// PassRegistry is destructed before the object that triggers this call.
|
||||||
|
if (!pImpl) return;
|
||||||
|
|
||||||
PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
|
PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
|
||||||
std::vector<PassRegistrationListener*>::iterator I =
|
std::vector<PassRegistrationListener*>::iterator I =
|
||||||
std::find(Impl->Listeners.begin(), Impl->Listeners.end(), L);
|
std::find(Impl->Listeners.begin(), Impl->Listeners.end(), L);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user