LLVM API Documentation
00001 //===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the DenseMap class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_ADT_DENSEMAP_H 00015 #define LLVM_ADT_DENSEMAP_H 00016 00017 #include "llvm/Support/DataTypes.h" 00018 #include "llvm/Support/MathExtras.h" 00019 #include <cassert> 00020 #include <utility> 00021 00022 namespace llvm { 00023 00024 template<typename T> 00025 struct DenseMapInfo { 00026 //static inline T getEmptyKey(); 00027 //static inline T getTombstoneKey(); 00028 //static unsigned getHashValue(const T &Val); 00029 //static bool isEqual(const T &LHS, const T &RHS); 00030 //static bool isPod() 00031 }; 00032 00033 // Provide DenseMapInfo for all pointers. 00034 template<typename T> 00035 struct DenseMapInfo<T*> { 00036 static inline T* getEmptyKey() { return reinterpret_cast<T*>(-1); } 00037 static inline T* getTombstoneKey() { return reinterpret_cast<T*>(-2); } 00038 static unsigned getHashValue(const T *PtrVal) { 00039 return (unsigned((uintptr_t)PtrVal) >> 4) ^ 00040 (unsigned((uintptr_t)PtrVal) >> 9); 00041 } 00042 static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; } 00043 static bool isPod() { return true; } 00044 }; 00045 00046 // Provide DenseMapInfo for unsigned ints. 00047 template<> struct DenseMapInfo<uint32_t> { 00048 static inline uint32_t getEmptyKey() { return ~0; } 00049 static inline uint32_t getTombstoneKey() { return ~0 - 1; } 00050 static unsigned getHashValue(const uint32_t& Val) { return Val * 37; } 00051 static bool isPod() { return true; } 00052 static bool isEqual(const uint32_t& LHS, const uint32_t& RHS) { 00053 return LHS == RHS; 00054 } 00055 }; 00056 00057 // Provide DenseMapInfo for all pairs whose members have info. 00058 template<typename T, typename U> 00059 struct DenseMapInfo<std::pair<T, U> > { 00060 typedef std::pair<T, U> Pair; 00061 typedef DenseMapInfo<T> FirstInfo; 00062 typedef DenseMapInfo<U> SecondInfo; 00063 00064 static inline Pair getEmptyKey() { 00065 return std::make_pair(FirstInfo::getEmptyKey(), 00066 SecondInfo::getEmptyKey()); 00067 } 00068 static inline Pair getTombstoneKey() { 00069 return std::make_pair(FirstInfo::getTombstoneKey(), 00070 SecondInfo::getEmptyKey()); 00071 } 00072 static unsigned getHashValue(const Pair& PairVal) { 00073 uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32 00074 | (uint64_t)SecondInfo::getHashValue(PairVal.second); 00075 key += ~(key << 32); 00076 key ^= (key >> 22); 00077 key += ~(key << 13); 00078 key ^= (key >> 8); 00079 key += (key << 3); 00080 key ^= (key >> 15); 00081 key += ~(key << 27); 00082 key ^= (key >> 31); 00083 return (unsigned)key; 00084 } 00085 static bool isEqual(const Pair& LHS, const Pair& RHS) { return LHS == RHS; } 00086 static bool isPod() { return FirstInfo::isPod() && SecondInfo::isPod(); } 00087 }; 00088 00089 template<typename KeyT, typename ValueT, 00090 typename KeyInfoT = DenseMapInfo<KeyT>, 00091 typename ValueInfoT = DenseMapInfo<ValueT> > 00092 class DenseMapIterator; 00093 template<typename KeyT, typename ValueT, 00094 typename KeyInfoT = DenseMapInfo<KeyT>, 00095 typename ValueInfoT = DenseMapInfo<ValueT> > 00096 class DenseMapConstIterator; 00097 00098 template<typename KeyT, typename ValueT, 00099 typename KeyInfoT = DenseMapInfo<KeyT>, 00100 typename ValueInfoT = DenseMapInfo<ValueT> > 00101 class DenseMap { 00102 typedef std::pair<KeyT, ValueT> BucketT; 00103 unsigned NumBuckets; 00104 BucketT *Buckets; 00105 00106 unsigned NumEntries; 00107 unsigned NumTombstones; 00108 public: 00109 typedef KeyT key_type; 00110 typedef ValueT mapped_type; 00111 typedef BucketT value_type; 00112 00113 DenseMap(const DenseMap& other) { 00114 NumBuckets = 0; 00115 CopyFrom(other); 00116 } 00117 00118 explicit DenseMap(unsigned NumInitBuckets = 64) { 00119 init(NumInitBuckets); 00120 } 00121 00122 ~DenseMap() { 00123 const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); 00124 for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { 00125 if (!KeyInfoT::isEqual(P->first, EmptyKey) && 00126 !KeyInfoT::isEqual(P->first, TombstoneKey)) 00127 P->second.~ValueT(); 00128 P->first.~KeyT(); 00129 } 00130 operator delete(Buckets); 00131 } 00132 00133 typedef DenseMapIterator<KeyT, ValueT, KeyInfoT> iterator; 00134 typedef DenseMapConstIterator<KeyT, ValueT, KeyInfoT> const_iterator; 00135 inline iterator begin() { 00136 return iterator(Buckets, Buckets+NumBuckets); 00137 } 00138 inline iterator end() { 00139 return iterator(Buckets+NumBuckets, Buckets+NumBuckets); 00140 } 00141 inline const_iterator begin() const { 00142 return const_iterator(Buckets, Buckets+NumBuckets); 00143 } 00144 inline const_iterator end() const { 00145 return const_iterator(Buckets+NumBuckets, Buckets+NumBuckets); 00146 } 00147 00148 bool empty() const { return NumEntries == 0; } 00149 unsigned size() const { return NumEntries; } 00150 00151 /// Grow the densemap so that it has at least Size buckets. Does not shrink 00152 void resize(size_t Size) { grow(Size); } 00153 00154 void clear() { 00155 // If the capacity of the array is huge, and the # elements used is small, 00156 // shrink the array. 00157 if (NumEntries * 4 < NumBuckets && NumBuckets > 64) { 00158 shrink_and_clear(); 00159 return; 00160 } 00161 00162 const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); 00163 for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { 00164 if (!KeyInfoT::isEqual(P->first, EmptyKey)) { 00165 if (!KeyInfoT::isEqual(P->first, TombstoneKey)) { 00166 P->second.~ValueT(); 00167 --NumEntries; 00168 } 00169 P->first = EmptyKey; 00170 } 00171 } 00172 assert(NumEntries == 0 && "Node count imbalance!"); 00173 NumTombstones = 0; 00174 } 00175 00176 /// count - Return true if the specified key is in the map. 00177 bool count(const KeyT &Val) const { 00178 BucketT *TheBucket; 00179 return LookupBucketFor(Val, TheBucket); 00180 } 00181 00182 iterator find(const KeyT &Val) { 00183 BucketT *TheBucket; 00184 if (LookupBucketFor(Val, TheBucket)) 00185 return iterator(TheBucket, Buckets+NumBuckets); 00186 return end(); 00187 } 00188 const_iterator find(const KeyT &Val) const { 00189 BucketT *TheBucket; 00190 if (LookupBucketFor(Val, TheBucket)) 00191 return const_iterator(TheBucket, Buckets+NumBuckets); 00192 return end(); 00193 } 00194 00195 /// lookup - Return the entry for the specified key, or a default 00196 /// constructed value if no such entry exists. 00197 ValueT lookup(const KeyT &Val) const { 00198 BucketT *TheBucket; 00199 if (LookupBucketFor(Val, TheBucket)) 00200 return TheBucket->second; 00201 return ValueT(); 00202 } 00203 00204 std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { 00205 BucketT *TheBucket; 00206 if (LookupBucketFor(KV.first, TheBucket)) 00207 return std::make_pair(iterator(TheBucket, Buckets+NumBuckets), 00208 false); // Already in map. 00209 00210 // Otherwise, insert the new element. 00211 TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket); 00212 return std::make_pair(iterator(TheBucket, Buckets+NumBuckets), 00213 true); 00214 } 00215 00216 /// insert - Range insertion of pairs. 00217 template<typename InputIt> 00218 void insert(InputIt I, InputIt E) { 00219 for (; I != E; ++I) 00220 insert(*I); 00221 } 00222 00223 00224 bool erase(const KeyT &Val) { 00225 BucketT *TheBucket; 00226 if (!LookupBucketFor(Val, TheBucket)) 00227 return false; // not in map. 00228 00229 TheBucket->second.~ValueT(); 00230 TheBucket->first = getTombstoneKey(); 00231 --NumEntries; 00232 ++NumTombstones; 00233 return true; 00234 } 00235 bool erase(iterator I) { 00236 BucketT *TheBucket = &*I; 00237 TheBucket->second.~ValueT(); 00238 TheBucket->first = getTombstoneKey(); 00239 --NumEntries; 00240 ++NumTombstones; 00241 return true; 00242 } 00243 00244 value_type& FindAndConstruct(const KeyT &Key) { 00245 BucketT *TheBucket; 00246 if (LookupBucketFor(Key, TheBucket)) 00247 return *TheBucket; 00248 00249 return *InsertIntoBucket(Key, ValueT(), TheBucket); 00250 } 00251 00252 ValueT &operator[](const KeyT &Key) { 00253 return FindAndConstruct(Key).second; 00254 } 00255 00256 DenseMap& operator=(const DenseMap& other) { 00257 CopyFrom(other); 00258 return *this; 00259 } 00260 00261 private: 00262 void CopyFrom(const DenseMap& other) { 00263 if (NumBuckets != 0 && (!KeyInfoT::isPod() || !ValueInfoT::isPod())) { 00264 const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); 00265 for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { 00266 if (!KeyInfoT::isEqual(P->first, EmptyKey) && 00267 !KeyInfoT::isEqual(P->first, TombstoneKey)) 00268 P->second.~ValueT(); 00269 P->first.~KeyT(); 00270 } 00271 } 00272 00273 NumEntries = other.NumEntries; 00274 NumTombstones = other.NumTombstones; 00275 00276 if (NumBuckets) 00277 operator delete(Buckets); 00278 Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT) * 00279 other.NumBuckets)); 00280 00281 if (KeyInfoT::isPod() && ValueInfoT::isPod()) 00282 memcpy(Buckets, other.Buckets, other.NumBuckets * sizeof(BucketT)); 00283 else 00284 for (size_t i = 0; i < other.NumBuckets; ++i) { 00285 new (&Buckets[i].first) KeyT(other.Buckets[i].first); 00286 if (!KeyInfoT::isEqual(Buckets[i].first, getEmptyKey()) && 00287 !KeyInfoT::isEqual(Buckets[i].first, getTombstoneKey())) 00288 new (&Buckets[i].second) ValueT(other.Buckets[i].second); 00289 } 00290 NumBuckets = other.NumBuckets; 00291 } 00292 00293 BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value, 00294 BucketT *TheBucket) { 00295 // If the load of the hash table is more than 3/4, or if fewer than 1/8 of 00296 // the buckets are empty (meaning that many are filled with tombstones), 00297 // grow the table. 00298 // 00299 // The later case is tricky. For example, if we had one empty bucket with 00300 // tons of tombstones, failing lookups (e.g. for insertion) would have to 00301 // probe almost the entire table until it found the empty bucket. If the 00302 // table completely filled with tombstones, no lookup would ever succeed, 00303 // causing infinite loops in lookup. 00304 if (NumEntries*4 >= NumBuckets*3 || 00305 NumBuckets-(NumEntries+NumTombstones) < NumBuckets/8) { 00306 this->grow(NumBuckets * 2); 00307 LookupBucketFor(Key, TheBucket); 00308 } 00309 ++NumEntries; 00310 00311 // If we are writing over a tombstone, remember this. 00312 if (!KeyInfoT::isEqual(TheBucket->first, getEmptyKey())) 00313 --NumTombstones; 00314 00315 TheBucket->first = Key; 00316 new (&TheBucket->second) ValueT(Value); 00317 return TheBucket; 00318 } 00319 00320 static unsigned getHashValue(const KeyT &Val) { 00321 return KeyInfoT::getHashValue(Val); 00322 } 00323 static const KeyT getEmptyKey() { 00324 return KeyInfoT::getEmptyKey(); 00325 } 00326 static const KeyT getTombstoneKey() { 00327 return KeyInfoT::getTombstoneKey(); 00328 } 00329 00330 /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in 00331 /// FoundBucket. If the bucket contains the key and a value, this returns 00332 /// true, otherwise it returns a bucket with an empty marker or tombstone and 00333 /// returns false. 00334 bool LookupBucketFor(const KeyT &Val, BucketT *&FoundBucket) const { 00335 unsigned BucketNo = getHashValue(Val); 00336 unsigned ProbeAmt = 1; 00337 BucketT *BucketsPtr = Buckets; 00338 00339 // FoundTombstone - Keep track of whether we find a tombstone while probing. 00340 BucketT *FoundTombstone = 0; 00341 const KeyT EmptyKey = getEmptyKey(); 00342 const KeyT TombstoneKey = getTombstoneKey(); 00343 assert(!KeyInfoT::isEqual(Val, EmptyKey) && 00344 !KeyInfoT::isEqual(Val, TombstoneKey) && 00345 "Empty/Tombstone value shouldn't be inserted into map!"); 00346 00347 while (1) { 00348 BucketT *ThisBucket = BucketsPtr + (BucketNo & (NumBuckets-1)); 00349 // Found Val's bucket? If so, return it. 00350 if (KeyInfoT::isEqual(ThisBucket->first, Val)) { 00351 FoundBucket = ThisBucket; 00352 return true; 00353 } 00354 00355 // If we found an empty bucket, the key doesn't exist in the set. 00356 // Insert it and return the default value. 00357 if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) { 00358 // If we've already seen a tombstone while probing, fill it in instead 00359 // of the empty bucket we eventually probed to. 00360 if (FoundTombstone) ThisBucket = FoundTombstone; 00361 FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; 00362 return false; 00363 } 00364 00365 // If this is a tombstone, remember it. If Val ends up not in the map, we 00366 // prefer to return it than something that would require more probing. 00367 if (KeyInfoT::isEqual(ThisBucket->first, TombstoneKey) && !FoundTombstone) 00368 FoundTombstone = ThisBucket; // Remember the first tombstone found. 00369 00370 // Otherwise, it's a hash collision or a tombstone, continue quadratic 00371 // probing. 00372 BucketNo += ProbeAmt++; 00373 } 00374 } 00375 00376 void init(unsigned InitBuckets) { 00377 NumEntries = 0; 00378 NumTombstones = 0; 00379 NumBuckets = InitBuckets; 00380 assert(InitBuckets && (InitBuckets & (InitBuckets-1)) == 0 && 00381 "# initial buckets must be a power of two!"); 00382 Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT)*InitBuckets)); 00383 // Initialize all the keys to EmptyKey. 00384 const KeyT EmptyKey = getEmptyKey(); 00385 for (unsigned i = 0; i != InitBuckets; ++i) 00386 new (&Buckets[i].first) KeyT(EmptyKey); 00387 } 00388 00389 void grow(unsigned AtLeast) { 00390 unsigned OldNumBuckets = NumBuckets; 00391 BucketT *OldBuckets = Buckets; 00392 00393 // Double the number of buckets. 00394 while (NumBuckets <= AtLeast) 00395 NumBuckets <<= 1; 00396 NumTombstones = 0; 00397 Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT)*NumBuckets)); 00398 00399 // Initialize all the keys to EmptyKey. 00400 const KeyT EmptyKey = getEmptyKey(); 00401 for (unsigned i = 0, e = NumBuckets; i != e; ++i) 00402 new (&Buckets[i].first) KeyT(EmptyKey); 00403 00404 // Insert all the old elements. 00405 const KeyT TombstoneKey = getTombstoneKey(); 00406 for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) { 00407 if (!KeyInfoT::isEqual(B->first, EmptyKey) && 00408 !KeyInfoT::isEqual(B->first, TombstoneKey)) { 00409 // Insert the key/value into the new table. 00410 BucketT *DestBucket; 00411 bool FoundVal = LookupBucketFor(B->first, DestBucket); 00412 FoundVal = FoundVal; // silence warning. 00413 assert(!FoundVal && "Key already in new map?"); 00414 DestBucket->first = B->first; 00415 new (&DestBucket->second) ValueT(B->second); 00416 00417 // Free the value. 00418 B->second.~ValueT(); 00419 } 00420 B->first.~KeyT(); 00421 } 00422 00423 // Free the old table. 00424 operator delete(OldBuckets); 00425 } 00426 00427 void shrink_and_clear() { 00428 unsigned OldNumBuckets = NumBuckets; 00429 BucketT *OldBuckets = Buckets; 00430 00431 // Reduce the number of buckets. 00432 NumBuckets = NumEntries > 32 ? 1 << (Log2_32_Ceil(NumEntries) + 1) 00433 : 64; 00434 NumTombstones = 0; 00435 Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT)*NumBuckets)); 00436 00437 // Initialize all the keys to EmptyKey. 00438 const KeyT EmptyKey = getEmptyKey(); 00439 for (unsigned i = 0, e = NumBuckets; i != e; ++i) 00440 new (&Buckets[i].first) KeyT(EmptyKey); 00441 00442 // Free the old buckets. 00443 const KeyT TombstoneKey = getTombstoneKey(); 00444 for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) { 00445 if (!KeyInfoT::isEqual(B->first, EmptyKey) && 00446 !KeyInfoT::isEqual(B->first, TombstoneKey)) { 00447 // Free the value. 00448 B->second.~ValueT(); 00449 } 00450 B->first.~KeyT(); 00451 } 00452 00453 // Free the old table. 00454 operator delete(OldBuckets); 00455 00456 NumEntries = 0; 00457 } 00458 }; 00459 00460 template<typename KeyT, typename ValueT, typename KeyInfoT, typename ValueInfoT> 00461 class DenseMapIterator { 00462 typedef std::pair<KeyT, ValueT> BucketT; 00463 protected: 00464 const BucketT *Ptr, *End; 00465 public: 00466 DenseMapIterator(void) : Ptr(0), End(0) {} 00467 00468 DenseMapIterator(const BucketT *Pos, const BucketT *E) : Ptr(Pos), End(E) { 00469 AdvancePastEmptyBuckets(); 00470 } 00471 00472 std::pair<KeyT, ValueT> &operator*() const { 00473 return *const_cast<BucketT*>(Ptr); 00474 } 00475 std::pair<KeyT, ValueT> *operator->() const { 00476 return const_cast<BucketT*>(Ptr); 00477 } 00478 00479 bool operator==(const DenseMapIterator &RHS) const { 00480 return Ptr == RHS.Ptr; 00481 } 00482 bool operator!=(const DenseMapIterator &RHS) const { 00483 return Ptr != RHS.Ptr; 00484 } 00485 00486 inline DenseMapIterator& operator++() { // Preincrement 00487 ++Ptr; 00488 AdvancePastEmptyBuckets(); 00489 return *this; 00490 } 00491 DenseMapIterator operator++(int) { // Postincrement 00492 DenseMapIterator tmp = *this; ++*this; return tmp; 00493 } 00494 00495 private: 00496 void AdvancePastEmptyBuckets() { 00497 const KeyT Empty = KeyInfoT::getEmptyKey(); 00498 const KeyT Tombstone = KeyInfoT::getTombstoneKey(); 00499 00500 while (Ptr != End && 00501 (KeyInfoT::isEqual(Ptr->first, Empty) || 00502 KeyInfoT::isEqual(Ptr->first, Tombstone))) 00503 ++Ptr; 00504 } 00505 }; 00506 00507 template<typename KeyT, typename ValueT, typename KeyInfoT, typename ValueInfoT> 00508 class DenseMapConstIterator : public DenseMapIterator<KeyT, ValueT, KeyInfoT> { 00509 public: 00510 DenseMapConstIterator(void) : DenseMapIterator<KeyT, ValueT, KeyInfoT>() {} 00511 DenseMapConstIterator(const std::pair<KeyT, ValueT> *Pos, 00512 const std::pair<KeyT, ValueT> *E) 00513 : DenseMapIterator<KeyT, ValueT, KeyInfoT>(Pos, E) { 00514 } 00515 const std::pair<KeyT, ValueT> &operator*() const { 00516 return *this->Ptr; 00517 } 00518 const std::pair<KeyT, ValueT> *operator->() const { 00519 return this->Ptr; 00520 } 00521 }; 00522 00523 } // end namespace llvm 00524 00525 #endif
This web site is hosted by the Computer Science Department at the University of Illinois at Urbana-Champaign.