X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FADT%2FScopedHashTable.h;h=efddd9f9b857576af2f7df97e7778d6751c9f26f;hb=ac39a035351a20928e087617e412aa6ce510181f;hp=df766935db7cfa57f3b4b3e276f5ccd00771f5b0;hpb=7f05aa72f970bdb92c831a83b02197b8699f7635;p=oota-llvm.git diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h index df766935db7..efddd9f9b85 100644 --- a/include/llvm/ADT/ScopedHashTable.h +++ b/include/llvm/ADT/ScopedHashTable.h @@ -31,12 +31,13 @@ #ifndef LLVM_ADT_SCOPEDHASHTABLE_H #define LLVM_ADT_SCOPEDHASHTABLE_H -#include #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Allocator.h" namespace llvm { -template +template , + typename AllocatorTy = MallocAllocator> class ScopedHashTable; template @@ -45,11 +46,8 @@ class ScopedHashTableVal { ScopedHashTableVal *NextForKey; K Key; V Val; + ScopedHashTableVal(const K &key, const V &val) : Key(key), Val(val) {} public: - ScopedHashTableVal(ScopedHashTableVal *nextInScope, - ScopedHashTableVal *nextForKey, const K &key, const V &val) - : NextInScope(nextInScope), NextForKey(nextForKey), Key(key), Val(val) { - } const K &getKey() const { return Key; } const V &getValue() const { return Val; } @@ -57,39 +55,66 @@ public: ScopedHashTableVal *getNextForKey() { return NextForKey; } const ScopedHashTableVal *getNextForKey() const { return NextForKey; } -public: ScopedHashTableVal *getNextInScope() { return NextInScope; } + + template + static ScopedHashTableVal *Create(ScopedHashTableVal *nextInScope, + ScopedHashTableVal *nextForKey, + const K &key, const V &val, + AllocatorTy &Allocator) { + ScopedHashTableVal *New = Allocator.template Allocate(); + // Set up the value. + new (New) ScopedHashTableVal(key, val); + New->NextInScope = nextInScope; + New->NextForKey = nextForKey; + return New; + } + + template + void Destroy(AllocatorTy &Allocator) { + // Free memory referenced by the item. + this->~ScopedHashTableVal(); + Allocator.Deallocate(this); + } }; -template +template , + typename AllocatorTy = MallocAllocator> class ScopedHashTableScope { /// HT - The hashtable that we are active for. - ScopedHashTable &HT; + ScopedHashTable &HT; /// PrevScope - This is the scope that we are shadowing in HT. ScopedHashTableScope *PrevScope; /// LastValInScope - This is the last value that was inserted for this scope /// or null if none have been inserted yet. - ScopedHashTableVal *LastValInScope; - void operator=(ScopedHashTableScope&); // DO NOT IMPLEMENT - ScopedHashTableScope(ScopedHashTableScope&); // DO NOT IMPLEMENT + ScopedHashTableVal *LastValInScope; + void operator=(ScopedHashTableScope&) LLVM_DELETED_FUNCTION; + ScopedHashTableScope(ScopedHashTableScope&) LLVM_DELETED_FUNCTION; public: - ScopedHashTableScope(ScopedHashTable &HT); + ScopedHashTableScope(ScopedHashTable &HT); ~ScopedHashTableScope(); + ScopedHashTableScope *getParentScope() { return PrevScope; } + const ScopedHashTableScope *getParentScope() const { return PrevScope; } + private: - friend class ScopedHashTable; - ScopedHashTableVal *getLastValInScope() { return LastValInScope; } - void setLastValInScope(ScopedHashTableVal *Val) { LastValInScope = Val; } + friend class ScopedHashTable; + ScopedHashTableVal *getLastValInScope() { + return LastValInScope; + } + void setLastValInScope(ScopedHashTableVal *Val) { + LastValInScope = Val; + } }; -template +template > class ScopedHashTableIterator { - ScopedHashTableVal *Node; + ScopedHashTableVal *Node; public: - ScopedHashTableIterator(ScopedHashTableVal *node) : Node(node){} + ScopedHashTableIterator(ScopedHashTableVal *node) : Node(node) {} V &operator*() const { assert(Node && "Dereference end()"); @@ -117,61 +142,91 @@ public: }; -template +template class ScopedHashTable { - DenseMap*> TopLevelMap; - ScopedHashTableScope *CurScope; +public: + /// ScopeTy - This is a helpful typedef that allows clients to get easy access + /// to the name of the scope for this hash table. + typedef ScopedHashTableScope ScopeTy; +private: + typedef ScopedHashTableVal ValTy; + DenseMap TopLevelMap; + ScopeTy *CurScope; + + AllocatorTy Allocator; + ScopedHashTable(const ScopedHashTable&); // NOT YET IMPLEMENTED void operator=(const ScopedHashTable&); // NOT YET IMPLEMENTED - friend class ScopedHashTableScope; + friend class ScopedHashTableScope; public: ScopedHashTable() : CurScope(0) {} + ScopedHashTable(AllocatorTy A) : CurScope(0), Allocator(A) {} ~ScopedHashTable() { assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!"); } + + + /// Access to the allocator. + typedef typename ReferenceAdder::result AllocatorRefTy; + typedef typename ReferenceAdder::result AllocatorCRefTy; + AllocatorRefTy getAllocator() { return Allocator; } + AllocatorCRefTy getAllocator() const { return Allocator; } bool count(const K &Key) const { return TopLevelMap.count(Key); } V lookup(const K &Key) { - return TopLevelMap[Key].getValue(); + typename DenseMap::iterator I = TopLevelMap.find(Key); + if (I != TopLevelMap.end()) + return I->second->getValue(); + + return V(); } void insert(const K &Key, const V &Val) { - assert(CurScope && "No scope active!"); - - ScopedHashTableVal *&KeyEntry = TopLevelMap[Key]; - - KeyEntry = new ScopedHashTableVal(CurScope->getLastValInScope(), - KeyEntry, Key, Val); - CurScope->setLastValInScope(KeyEntry); + insertIntoScope(CurScope, Key, Val); } - typedef ScopedHashTableIterator iterator; + typedef ScopedHashTableIterator iterator; iterator end() { return iterator(0); } iterator begin(const K &Key) { - typename DenseMap*>::iterator I = + typename DenseMap::iterator I = TopLevelMap.find(Key); if (I == TopLevelMap.end()) return end(); return iterator(I->second); } + + ScopeTy *getCurScope() { return CurScope; } + const ScopeTy *getCurScope() const { return CurScope; } + + /// insertIntoScope - This inserts the specified key/value at the specified + /// (possibly not the current) scope. While it is ok to insert into a scope + /// that isn't the current one, it isn't ok to insert *underneath* an existing + /// value of the specified key. + void insertIntoScope(ScopeTy *S, const K &Key, const V &Val) { + assert(S && "No scope active!"); + ScopedHashTableVal *&KeyEntry = TopLevelMap[Key]; + KeyEntry = ValTy::Create(S->getLastValInScope(), KeyEntry, Key, Val, + Allocator); + S->setLastValInScope(KeyEntry); + } }; /// ScopedHashTableScope ctor - Install this as the current scope for the hash /// table. -template -ScopedHashTableScope::ScopedHashTableScope(ScopedHashTable &ht) - : HT(ht) { +template +ScopedHashTableScope:: + ScopedHashTableScope(ScopedHashTable &ht) : HT(ht) { PrevScope = HT.CurScope; HT.CurScope = this; LastValInScope = 0; } -template -ScopedHashTableScope::~ScopedHashTableScope() { +template +ScopedHashTableScope::~ScopedHashTableScope() { assert(HT.CurScope == this && "Scope imbalance!"); HT.CurScope = PrevScope; @@ -183,7 +238,7 @@ ScopedHashTableScope::~ScopedHashTableScope() { "Scope imbalance!"); HT.TopLevelMap.erase(ThisEntry->getKey()); } else { - ScopedHashTableVal *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()]; + ScopedHashTableVal *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()]; assert(KeyEntry == ThisEntry && "Scope imbalance!"); KeyEntry = ThisEntry->getNextForKey(); } @@ -192,7 +247,7 @@ ScopedHashTableScope::~ScopedHashTableScope() { LastValInScope = ThisEntry->getNextInScope(); // Delete this entry. - delete ThisEntry; + ThisEntry->Destroy(HT.getAllocator()); } }