aboutsummaryrefslogtreecommitdiff
path: root/lib/VMCore/LeakDetector.cpp
diff options
context:
space:
mode:
authorOwen Anderson <resistor@mac.com>2009-08-19 00:37:02 +0000
committerOwen Anderson <resistor@mac.com>2009-08-19 00:37:02 +0000
commitba43a385a817d7f59e528a744dc40e44317ec739 (patch)
tree24c44eff556d950b06fac6a988cea428bc1a3a47 /lib/VMCore/LeakDetector.cpp
parentecc67e2e1b2c13c99427510fff71d598086eb309 (diff)
Privatize part of the leak detector mechanism, which turned out to be heavily contended
when trying to run opt in parallel. This lets parallel opt crunch 403.gcc in about a third of the time. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79387 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore/LeakDetector.cpp')
-rw-r--r--lib/VMCore/LeakDetector.cpp114
1 files changed, 24 insertions, 90 deletions
diff --git a/lib/VMCore/LeakDetector.cpp b/lib/VMCore/LeakDetector.cpp
index a6be1afed4..3185742174 100644
--- a/lib/VMCore/LeakDetector.cpp
+++ b/lib/VMCore/LeakDetector.cpp
@@ -11,129 +11,63 @@
//
//===----------------------------------------------------------------------===//
+#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/RWMutex.h"
+#include "llvm/System/Mutex.h"
#include "llvm/System/Threading.h"
#include "llvm/Value.h"
using namespace llvm;
-namespace {
- template <class T>
- struct VISIBILITY_HIDDEN PrinterTrait {
- static void print(const T* P) { cerr << P; }
- };
+static ManagedStatic<sys::SmartMutex<true> > ObjectsLock;
+static ManagedStatic<LeakDetectorImpl<void> > Objects;
- 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();
- }
+static void clearGarbage(LLVMContext &Context) {
+ Objects->clear();
+ Context.pImpl->LLVMObjects.clear();
}
void LeakDetector::addGarbageObjectImpl(void *Object) {
+ sys::SmartScopedLock<true> Lock(*ObjectsLock);
Objects->addGarbage(Object);
}
void LeakDetector::addGarbageObjectImpl(const Value *Object) {
- LLVMObjects->addGarbage(Object);
+ LLVMContextImpl *pImpl = Object->getContext().pImpl;
+ sys::SmartScopedLock<true> Lock(pImpl->LLVMObjectsLock);
+ pImpl->LLVMObjects.addGarbage(Object);
}
void LeakDetector::removeGarbageObjectImpl(void *Object) {
+ sys::SmartScopedLock<true> Lock(*ObjectsLock);
Objects->removeGarbage(Object);
}
void LeakDetector::removeGarbageObjectImpl(const Value *Object) {
- LLVMObjects->removeGarbage(Object);
+ LLVMContextImpl *pImpl = Object->getContext().pImpl;
+ sys::SmartScopedLock<true> Lock(pImpl->LLVMObjectsLock);
+ pImpl->LLVMObjects.removeGarbage(Object);
}
-void LeakDetector::checkForGarbageImpl(const std::string &Message) {
+void LeakDetector::checkForGarbageImpl(LLVMContext &Context,
+ const std::string &Message) {
+ LLVMContextImpl *pImpl = Context.pImpl;
+ sys::SmartScopedLock<true> Lock(*ObjectsLock);
+ sys::SmartScopedLock<true> CLock(pImpl->LLVMObjectsLock);
+
Objects->setName("GENERIC");
- LLVMObjects->setName("LLVM");
+ pImpl->LLVMObjects.setName("LLVM");
// use non-short-circuit version so that both checks are performed
if (Objects->hasGarbage(Message) |
- LLVMObjects->hasGarbage(Message))
+ pImpl->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();
+ clearGarbage(Context);
}