Fix PR7972, in which the PassRegistry was being leaked. As part of this,
authorOwen Anderson <resistor@mac.com>
Tue, 7 Sep 2010 20:48:10 +0000 (20:48 +0000)
committerOwen Anderson <resistor@mac.com>
Tue, 7 Sep 2010 20:48:10 +0000 (20:48 +0000)
switch to using a ManagedStatic for the global PassRegistry instead of a
ManagedCleanup, and fix a destruction ordering bug this exposed.

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

include/llvm/PassRegistry.h
lib/VMCore/PassRegistry.cpp

index 809dba0bc0dc79be5c2b84d2055e2d1d3e0d6b59..fa269a9c5a1dd4041972835f302ad1805ada9495 100644 (file)
@@ -37,6 +37,7 @@ class PassRegistry {
    
 public:
   PassRegistry() : pImpl(0) { }
+  ~PassRegistry();
   
   /// getPassRegistry - Access the global registry object, which is 
   /// automatically initialized at application launch and destroyed by
index 562c58c0b95203769962d2087ac23b668a755ab4..9196d42114461d2f0e568ac86a8b3d5ea266d185 100644 (file)
 
 using namespace llvm;
 
-static PassRegistry *PassRegistryObj = 0;
-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.
+// FIXME: We use ManagedStatic to erase the pass registrar on shutdown.
 // Unfortunately, passes are registered with static ctors, and having
 // llvm_shutdown clear this map prevents successful ressurection after 
 // llvm_shutdown is run.  Ideally we should find a solution so that we don't
 // leak the map, AND can still resurrect after shutdown.
-void cleanupPassRegistry(void*) {
-  if (PassRegistryObj) {
-    delete PassRegistryObj;
-    PassRegistryObj = 0;
-  }
-}
-ManagedCleanup<&cleanupPassRegistry> registryCleanup ATTRIBUTE_USED;
-
+static ManagedStatic<PassRegistry> PassRegistryObj;
+PassRegistry *PassRegistry::getPassRegistry() {
+  return &*PassRegistryObj;
 }
 
 //===----------------------------------------------------------------------===//
@@ -94,6 +63,12 @@ void *PassRegistry::getImpl() const {
 // Accessors
 //
 
+PassRegistry::~PassRegistry() {
+  PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(pImpl);
+  if (Impl) delete Impl;
+  pImpl = 0;
+}
+
 const PassInfo *PassRegistry::getPassInfo(const void *TI) const {
   PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl());
   PassRegistryImpl::MapType::const_iterator I = Impl->PassInfoMap.find(TI);
@@ -188,6 +163,12 @@ void PassRegistry::addRegistrationListener(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());
   std::vector<PassRegistrationListener*>::iterator I =
     std::find(Impl->Listeners.begin(), Impl->Listeners.end(), L);