X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FLeakDetector.cpp;h=a44f61d822eeec61e550eda04151746b2b64d2b0;hb=1b4051095dd518175bea303ed6d7328bd6849cd4;hp=4c9f12580724e9cd01dfcc5fc840f4ca2d50f533;hpb=8f487662869d10c866b9ebdccb8f6a7509d3ab56;p=oota-llvm.git diff --git a/lib/VMCore/LeakDetector.cpp b/lib/VMCore/LeakDetector.cpp index 4c9f1258072..a44f61d822e 100644 --- a/lib/VMCore/LeakDetector.cpp +++ b/lib/VMCore/LeakDetector.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -11,122 +11,59 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/Compiler.h" +#include "LLVMContextImpl.h" #include "llvm/Support/LeakDetector.h" -#include "llvm/Support/Streams.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/System/Mutex.h" +#include "llvm/System/Threading.h" #include "llvm/Value.h" -#include using namespace llvm; -namespace { - template - struct VISIBILITY_HIDDEN PrinterTrait { - static void print(const T* P) { llvm_cerr << P; } - }; - - template<> - struct VISIBILITY_HIDDEN PrinterTrait { - static void print(const Value* P) { llvm_cerr << *P; } - }; - - template - struct VISIBILITY_HIDDEN LeakDetectorImpl { - LeakDetectorImpl(const char* const name) : Cache(0), Name(name) { } - - // 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) { - if (Cache) { - assert(Ts.count(Cache) == 0 && "Object already in set!"); - Ts.insert(Cache); - } - Cache = o; - } - - void removeGarbage(const T* o) { - if (o == Cache) - Cache = 0; // Cache hit - else - Ts.erase(o); - } - - bool hasGarbage(const std::string& Message) { - addGarbage(0); // Flush the Cache - - assert(Cache == 0 && "No value should be cached anymore!"); - - if (!Ts.empty()) { - llvm_cerr - << "Leaked " << Name << " objects found: " << Message << ":\n"; - for (typename std::set::iterator I = Ts.begin(), - E = Ts.end(); I != E; ++I) { - llvm_cerr << "\t"; - PrinterTrait::print(*I); - llvm_cerr << "\n"; - } - llvm_cerr << '\n'; - - return true; - } - return false; - } - - private: - std::set Ts; - const T* Cache; - const char* const Name; - }; - - LeakDetectorImpl *Objects; - LeakDetectorImpl *LLVMObjects; - - LeakDetectorImpl &getObjects() { - if (Objects == 0) - Objects = new LeakDetectorImpl("GENERIC"); - return *Objects; - } - - LeakDetectorImpl &getLLVMObjects() { - if (LLVMObjects == 0) - LLVMObjects = new LeakDetectorImpl("LLVM"); - return *LLVMObjects; - } +static ManagedStatic > ObjectsLock; +static ManagedStatic > Objects; - void clearGarbage() { - delete Objects; - delete LLVMObjects; - Objects = 0; - LLVMObjects = 0; - } +static void clearGarbage(LLVMContext &Context) { + Objects->clear(); + Context.pImpl->LLVMObjects.clear(); } void LeakDetector::addGarbageObjectImpl(void *Object) { - getObjects().addGarbage(Object); + sys::SmartScopedLock Lock(*ObjectsLock); + Objects->addGarbage(Object); } void LeakDetector::addGarbageObjectImpl(const Value *Object) { - getLLVMObjects().addGarbage(Object); + LLVMContextImpl *pImpl = Object->getContext().pImpl; + pImpl->LLVMObjects.addGarbage(Object); } void LeakDetector::removeGarbageObjectImpl(void *Object) { - getObjects().removeGarbage(Object); + sys::SmartScopedLock Lock(*ObjectsLock); + Objects->removeGarbage(Object); } void LeakDetector::removeGarbageObjectImpl(const Value *Object) { - getLLVMObjects().removeGarbage(Object); + LLVMContextImpl *pImpl = Object->getContext().pImpl; + 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 Lock(*ObjectsLock); + + Objects->setName("GENERIC"); + pImpl->LLVMObjects.setName("LLVM"); + // use non-short-circuit version so that both checks are performed - if (getObjects().hasGarbage(Message) | - getLLVMObjects().hasGarbage(Message)) - llvm_cerr << "\nThis is probably because you removed an object, but didn't " - << "delete it. Please check your code for memory leaks.\n"; + if (Objects->hasGarbage(Message) | + pImpl->LLVMObjects.hasGarbage(Message)) + errs() << "\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); }