aboutsummaryrefslogtreecommitdiff
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
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
-rw-r--r--include/llvm/Support/LeakDetector.h6
-rw-r--r--lib/VMCore/LLVMContextImpl.h5
-rw-r--r--lib/VMCore/LeakDetector.cpp114
3 files changed, 32 insertions, 93 deletions
diff --git a/include/llvm/Support/LeakDetector.h b/include/llvm/Support/LeakDetector.h
index 8d74ac663b..7dbfdbf3d5 100644
--- a/include/llvm/Support/LeakDetector.h
+++ b/include/llvm/Support/LeakDetector.h
@@ -56,9 +56,9 @@ struct LeakDetector {
/// The specified message will be printed indicating when the check was
/// performed.
///
- static void checkForGarbage(const std::string &Message) {
+ static void checkForGarbage(LLVMContext &C, const std::string &Message) {
#ifndef NDEBUG
- checkForGarbageImpl(Message);
+ checkForGarbageImpl(C, Message);
#endif
}
@@ -83,7 +83,7 @@ private:
static void removeGarbageObjectImpl(const Value *Object);
static void addGarbageObjectImpl(void *Object);
static void removeGarbageObjectImpl(void *Object);
- static void checkForGarbageImpl(const std::string &Message);
+ static void checkForGarbageImpl(LLVMContext &C, const std::string &Message);
};
} // End llvm namespace
diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h
index aaa48ca0d4..20d410eaf8 100644
--- a/lib/VMCore/LLVMContextImpl.h
+++ b/lib/VMCore/LLVMContextImpl.h
@@ -16,6 +16,7 @@
#define LLVM_LLVMCONTEXT_IMPL_H
#include "ConstantsContext.h"
+#include "LeaksContext.h"
#include "TypesContext.h"
#include "llvm/LLVMContext.h"
#include "llvm/Constants.h"
@@ -134,6 +135,10 @@ public:
ConstantInt *TheTrueVal;
ConstantInt *TheFalseVal;
+ // Lock used for guarding access to the leak detector
+ sys::SmartMutex<true> LLVMObjectsLock;
+ LeakDetectorImpl<Value> LLVMObjects;
+
// Lock used for guarding access to the type maps.
sys::SmartMutex<true> TypeMapLock;
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);
}