diff options
| author | Owen Anderson <resistor@mac.com> | 2009-08-19 00:52:13 +0000 | 
|---|---|---|
| committer | Owen Anderson <resistor@mac.com> | 2009-08-19 00:52:13 +0000 | 
| commit | 077df2c4ce16671a6e811b4006f5c0dd098d1be5 (patch) | |
| tree | d37b37c1ce37a6903c209f03fe84150b4199306e /llvm/lib/VMCore/LeakDetector.cpp | |
| parent | 304253908957b2bd7b8ab716611d18b8c452576d (diff) | |
| download | bcm5719-llvm-077df2c4ce16671a6e811b4006f5c0dd098d1be5.tar.gz bcm5719-llvm-077df2c4ce16671a6e811b4006f5c0dd098d1be5.zip | |
Revert my last patch temporarily.
llvm-svn: 79388
Diffstat (limited to 'llvm/lib/VMCore/LeakDetector.cpp')
| -rw-r--r-- | llvm/lib/VMCore/LeakDetector.cpp | 114 | 
1 files changed, 90 insertions, 24 deletions
| diff --git a/llvm/lib/VMCore/LeakDetector.cpp b/llvm/lib/VMCore/LeakDetector.cpp index 31857421746..a6be1afed49 100644 --- a/llvm/lib/VMCore/LeakDetector.cpp +++ b/llvm/lib/VMCore/LeakDetector.cpp @@ -11,63 +11,129 @@  //  //===----------------------------------------------------------------------===// -#include "LLVMContextImpl.h"  #include "llvm/Support/LeakDetector.h"  #include "llvm/ADT/SmallPtrSet.h"  #include "llvm/Support/Compiler.h"  #include "llvm/Support/ManagedStatic.h"  #include "llvm/Support/Streams.h" -#include "llvm/System/Mutex.h" +#include "llvm/System/RWMutex.h"  #include "llvm/System/Threading.h"  #include "llvm/Value.h"  using namespace llvm; -static ManagedStatic<sys::SmartMutex<true> > ObjectsLock; -static ManagedStatic<LeakDetectorImpl<void> > Objects; +namespace { +  template <class T> +  struct VISIBILITY_HIDDEN PrinterTrait { +    static void print(const T* P) { cerr << P; } +  }; -static void clearGarbage(LLVMContext &Context) { -  Objects->clear(); -  Context.pImpl->LLVMObjects.clear(); +  template<> +  struct VISIBILITY_HIDDEN PrinterTrait<Value> { +    static void print(const Value* P) { cerr << *P; } +  }; + +  ManagedStatic<sys::SmartRWMutex<true> > LeakDetectorLock; + +  template <typename T> +  struct VISIBILITY_HIDDEN LeakDetectorImpl { +    explicit LeakDetectorImpl(const char* const name = "") :  +      Cache(0), Name(name) { } + +    void clear() { +      Cache = 0; +      Ts.clear(); +    } +     +    void setName(const char* n) {  +      Name = n; +    } +     +    // Because the most common usage pattern, by far, is to add a +    // garbage object, then remove it immediately, we optimize this +    // case.  When an object is added, it is not added to the set +    // immediately, it is added to the CachedValue Value.  If it is +    // immediately removed, no set search need be performed. +    void addGarbage(const T* o) { +      sys::SmartScopedWriter<true> Writer(*LeakDetectorLock); +      if (Cache) { +        assert(Ts.count(Cache) == 0 && "Object already in set!"); +        Ts.insert(Cache); +      } +      Cache = o; +    } + +    void removeGarbage(const T* o) { +      sys::SmartScopedWriter<true> Writer(*LeakDetectorLock); +      if (o == Cache) +        Cache = 0; // Cache hit +      else +        Ts.erase(o); +    } + +    bool hasGarbage(const std::string& Message) { +      addGarbage(0); // Flush the Cache + +      sys::SmartScopedReader<true> Reader(*LeakDetectorLock); +      assert(Cache == 0 && "No value should be cached anymore!"); + +      if (!Ts.empty()) { +        cerr << "Leaked " << Name << " objects found: " << Message << ":\n"; +        for (typename SmallPtrSet<const T*, 8>::iterator I = Ts.begin(), +               E = Ts.end(); I != E; ++I) { +          cerr << "\t"; +          PrinterTrait<T>::print(*I); +          cerr << "\n"; +        } +        cerr << '\n'; + +        return true; +      } +       +      return false; +    } + +  private: +    SmallPtrSet<const T*, 8> Ts; +    const T* Cache; +    const char* Name; +  }; + +  static ManagedStatic<LeakDetectorImpl<void> > Objects; +  static ManagedStatic<LeakDetectorImpl<Value> > LLVMObjects; + +  static void clearGarbage() { +    Objects->clear(); +    LLVMObjects->clear(); +  }  }  void LeakDetector::addGarbageObjectImpl(void *Object) { -  sys::SmartScopedLock<true> Lock(*ObjectsLock);    Objects->addGarbage(Object);  }  void LeakDetector::addGarbageObjectImpl(const Value *Object) { -  LLVMContextImpl *pImpl = Object->getContext().pImpl; -  sys::SmartScopedLock<true> Lock(pImpl->LLVMObjectsLock); -  pImpl->LLVMObjects.addGarbage(Object); +  LLVMObjects->addGarbage(Object);  }  void LeakDetector::removeGarbageObjectImpl(void *Object) { -  sys::SmartScopedLock<true> Lock(*ObjectsLock);    Objects->removeGarbage(Object);  }  void LeakDetector::removeGarbageObjectImpl(const Value *Object) { -  LLVMContextImpl *pImpl = Object->getContext().pImpl; -  sys::SmartScopedLock<true> Lock(pImpl->LLVMObjectsLock); -  pImpl->LLVMObjects.removeGarbage(Object); +  LLVMObjects->removeGarbage(Object);  } -void LeakDetector::checkForGarbageImpl(LLVMContext &Context,  -                                       const std::string &Message) { -  LLVMContextImpl *pImpl = Context.pImpl; -  sys::SmartScopedLock<true> Lock(*ObjectsLock); -  sys::SmartScopedLock<true> CLock(pImpl->LLVMObjectsLock); -   +void LeakDetector::checkForGarbageImpl(const std::string &Message) {    Objects->setName("GENERIC"); -  pImpl->LLVMObjects.setName("LLVM"); +  LLVMObjects->setName("LLVM");    // use non-short-circuit version so that both checks are performed    if (Objects->hasGarbage(Message) | -      pImpl->LLVMObjects.hasGarbage(Message)) +      LLVMObjects->hasGarbage(Message))      cerr << "\nThis is probably because you removed an object, but didn't "           << "delete it.  Please check your code for memory leaks.\n";    // Clear out results so we don't get duplicate warnings on    // next call... -  clearGarbage(Context); +  clearGarbage();  } | 

