X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FLeakDetector.cpp;h=f6651e93e273222d207cfd81801a97c496fc2e56;hb=1f6efa3996dd1929fbc129203ce5009b620e6969;hp=a6d96df7ba1f18d4b723759d9e4ccdde9b95bafc;hpb=b663d76f866d03756dd563d246d9bdaabca4ca33;p=oota-llvm.git diff --git a/lib/VMCore/LeakDetector.cpp b/lib/VMCore/LeakDetector.cpp index a6d96df7ba1..f6651e93e27 100644 --- a/lib/VMCore/LeakDetector.cpp +++ b/lib/VMCore/LeakDetector.cpp @@ -1,107 +1,69 @@ //===-- LeakDetector.cpp - Implement LeakDetector interface ---------------===// -// +// // 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. +// //===----------------------------------------------------------------------===// // // This file implements the LeakDetector class. // //===----------------------------------------------------------------------===// -#include "Support/LeakDetector.h" +#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/Mutex.h" +#include "llvm/Support/Threading.h" #include "llvm/Value.h" -#include using namespace llvm; -namespace { - - template - struct 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()) { - std::cerr - << "Leaked " << Name << " objects found: " << Message << ":\n\t"; - std::copy(Ts.begin(), Ts.end(), - std::ostream_iterator(std::cerr, " ")); - std::cerr << '\n'; - - // Clear out results so we don't get duplicate warnings on - // next call... - Ts.clear(); - return true; - } - return false; - } - - private: - std::set Ts; - const T* Cache; - const char* const Name; - }; - - typedef LeakDetectorImpl Objects; - typedef LeakDetectorImpl LLVMObjects; - - Objects& getObjects() { - static Objects o("GENERIC"); - return o; - } +static ManagedStatic > ObjectsLock; +static ManagedStatic > Objects; - LLVMObjects& getLLVMObjects() { - static LLVMObjects o("LLVM"); - return o; - } +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)) - std::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(Context); }