X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FLeakDetector.cpp;h=9f3584e25a22d9650b685dc99709533715797646;hb=0b12ecf6ff6b5d3a144178257b6206f0c4788792;hp=24c946ab6ea4109b9af889abda3b565cea1c2f23;hpb=b576c94c15af9a440f69d9d03c2afead7971118c;p=oota-llvm.git diff --git a/lib/VMCore/LeakDetector.cpp b/lib/VMCore/LeakDetector.cpp index 24c946ab6ea..9f3584e25a2 100644 --- a/lib/VMCore/LeakDetector.cpp +++ b/lib/VMCore/LeakDetector.cpp @@ -1,89 +1,131 @@ //===-- 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 "llvm/Support/LeakDetector.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Streams.h" #include "llvm/Value.h" #include +using namespace llvm; -// Lazily allocate set so that release build doesn't have to do anything. -static std::set *Objects = 0; -static std::set *LLVMObjects = 0; +namespace { + template + struct VISIBILITY_HIDDEN PrinterTrait { + static void print(const T* P) { cerr << P; } + }; -// 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. -// -static const Value *CachedValue; + template<> + struct VISIBILITY_HIDDEN PrinterTrait { + static void print(const Value* P) { cerr << *P; } + }; -void LeakDetector::addGarbageObjectImpl(void *Object) { - if (Objects == 0) - Objects = new std::set(); - assert(Objects->count(Object) == 0 && "Object already in set!"); - Objects->insert(Object); -} + template + struct VISIBILITY_HIDDEN LeakDetectorImpl { + LeakDetectorImpl(const char* const name) : Cache(0), Name(name) { } -void LeakDetector::removeGarbageObjectImpl(void *Object) { - if (Objects) - Objects->erase(Object); -} + // 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 LeakDetector::addGarbageObjectImpl(const Value *Object) { - if (CachedValue) { + 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()) { + cerr << "Leaked " << Name << " objects found: " << Message << ":\n"; + for (typename std::set::iterator I = Ts.begin(), + E = Ts.end(); I != E; ++I) { + cerr << "\t"; + PrinterTrait::print(*I); + cerr << "\n"; + } + cerr << '\n'; + + return true; + } + return false; + } + + private: + std::set Ts; + const T* Cache; + const char* const Name; + }; + + static LeakDetectorImpl *Objects; + static LeakDetectorImpl *LLVMObjects; + + static LeakDetectorImpl &getObjects() { + if (Objects == 0) + Objects = new LeakDetectorImpl("GENERIC"); + return *Objects; + } + + static LeakDetectorImpl &getLLVMObjects() { if (LLVMObjects == 0) - LLVMObjects = new std::set(); - assert(LLVMObjects->count(CachedValue) == 0 && "Object already in set!"); - LLVMObjects->insert(CachedValue); + LLVMObjects = new LeakDetectorImpl("LLVM"); + return *LLVMObjects; } - CachedValue = Object; -} -void LeakDetector::removeGarbageObjectImpl(const Value *Object) { - if (Object == CachedValue) - CachedValue = 0; // Cache hit! - else if (LLVMObjects) - LLVMObjects->erase(Object); + static void clearGarbage() { + delete Objects; + delete LLVMObjects; + Objects = 0; + LLVMObjects = 0; + } } -void LeakDetector::checkForGarbageImpl(const std::string &Message) { - if (CachedValue) // Flush the cache to the set... - addGarbageObjectImpl((Value*)0); - - assert(CachedValue == 0 && "No value should be cached anymore!"); +void LeakDetector::addGarbageObjectImpl(void *Object) { + getObjects().addGarbage(Object); +} - if ((Objects && !Objects->empty()) || (LLVMObjects && !LLVMObjects->empty())){ - std::cerr << "Leaked objects found: " << Message << "\n"; +void LeakDetector::addGarbageObjectImpl(const Value *Object) { + getLLVMObjects().addGarbage(Object); +} - if (Objects && !Objects->empty()) { - std::cerr << " Non-Value objects leaked:"; - for (std::set::iterator I = Objects->begin(), - E = Objects->end(); I != E; ++I) - std::cerr << " " << *I; - } +void LeakDetector::removeGarbageObjectImpl(void *Object) { + getObjects().removeGarbage(Object); +} - if (LLVMObjects && !LLVMObjects->empty()) { - std::cerr << " LLVM Value subclasses leaked:"; - for (std::set::iterator I = LLVMObjects->begin(), - E = LLVMObjects->end(); I != E; ++I) - std::cerr << **I << "\n"; - } +void LeakDetector::removeGarbageObjectImpl(const Value *Object) { + getLLVMObjects().removeGarbage(Object); +} - std::cerr << "This is probably because you removed an LLVM value " - << "(Instruction, BasicBlock, \netc), but didn't delete it. " - << "Please check your code for memory leaks.\n"; +void LeakDetector::checkForGarbageImpl(const std::string &Message) { + // use non-short-circuit version so that both checks are performed + if (getObjects().hasGarbage(Message) | + getLLVMObjects().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... - delete Objects; delete LLVMObjects; - Objects = 0; LLVMObjects = 0; - } + // Clear out results so we don't get duplicate warnings on + // next call... + clearGarbage(); }