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/ADT/DenseMapInfo.h" 00018 #include "llvm/Support/AlignOf.h" 00019 #include "llvm/Support/Compiler.h" 00020 #include "llvm/Support/MathExtras.h" 00021 #include "llvm/Support/PointerLikeTypeTraits.h" 00022 #include "llvm/Support/type_traits.h" 00023 #include <algorithm> 00024 #include <cassert> 00025 #include <climits> 00026 #include <cstddef> 00027 #include <cstring> 00028 #include <iterator> 00029 #include <new> 00030 #include <utility> 00031 00032 namespace llvm { 00033 00034 template<typename KeyT, typename ValueT, 00035 typename KeyInfoT = DenseMapInfo<KeyT>, 00036 bool IsConst = false> 00037 class DenseMapIterator; 00038 00039 template<typename DerivedT, 00040 typename KeyT, typename ValueT, typename KeyInfoT> 00041 class DenseMapBase { 00042 protected: 00043 typedef std::pair<KeyT, ValueT> BucketT; 00044 00045 public: 00046 typedef KeyT key_type; 00047 typedef ValueT mapped_type; 00048 typedef BucketT value_type; 00049 00050 typedef DenseMapIterator<KeyT, ValueT, KeyInfoT> iterator; 00051 typedef DenseMapIterator<KeyT, ValueT, 00052 KeyInfoT, true> const_iterator; 00053 inline iterator begin() { 00054 // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets(). 00055 return empty() ? end() : iterator(getBuckets(), getBucketsEnd()); 00056 } 00057 inline iterator end() { 00058 return iterator(getBucketsEnd(), getBucketsEnd(), true); 00059 } 00060 inline const_iterator begin() const { 00061 return empty() ? end() : const_iterator(getBuckets(), getBucketsEnd()); 00062 } 00063 inline const_iterator end() const { 00064 return const_iterator(getBucketsEnd(), getBucketsEnd(), true); 00065 } 00066 00067 bool empty() const { return getNumEntries() == 0; } 00068 unsigned size() const { return getNumEntries(); } 00069 00070 /// Grow the densemap so that it has at least Size buckets. Does not shrink 00071 void resize(size_t Size) { 00072 if (Size > getNumBuckets()) 00073 grow(Size); 00074 } 00075 00076 void clear() { 00077 if (getNumEntries() == 0 && getNumTombstones() == 0) return; 00078 00079 // If the capacity of the array is huge, and the # elements used is small, 00080 // shrink the array. 00081 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) { 00082 shrink_and_clear(); 00083 return; 00084 } 00085 00086 const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); 00087 for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { 00088 if (!KeyInfoT::isEqual(P->first, EmptyKey)) { 00089 if (!KeyInfoT::isEqual(P->first, TombstoneKey)) { 00090 P->second.~ValueT(); 00091 decrementNumEntries(); 00092 } 00093 P->first = EmptyKey; 00094 } 00095 } 00096 assert(getNumEntries() == 0 && "Node count imbalance!"); 00097 setNumTombstones(0); 00098 } 00099 00100 /// count - Return true if the specified key is in the map. 00101 bool count(const KeyT &Val) const { 00102 const BucketT *TheBucket; 00103 return LookupBucketFor(Val, TheBucket); 00104 } 00105 00106 iterator find(const KeyT &Val) { 00107 BucketT *TheBucket; 00108 if (LookupBucketFor(Val, TheBucket)) 00109 return iterator(TheBucket, getBucketsEnd(), true); 00110 return end(); 00111 } 00112 const_iterator find(const KeyT &Val) const { 00113 const BucketT *TheBucket; 00114 if (LookupBucketFor(Val, TheBucket)) 00115 return const_iterator(TheBucket, getBucketsEnd(), true); 00116 return end(); 00117 } 00118 00119 /// Alternate version of find() which allows a different, and possibly 00120 /// less expensive, key type. 00121 /// The DenseMapInfo is responsible for supplying methods 00122 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key 00123 /// type used. 00124 template<class LookupKeyT> 00125 iterator find_as(const LookupKeyT &Val) { 00126 BucketT *TheBucket; 00127 if (LookupBucketFor(Val, TheBucket)) 00128 return iterator(TheBucket, getBucketsEnd(), true); 00129 return end(); 00130 } 00131 template<class LookupKeyT> 00132 const_iterator find_as(const LookupKeyT &Val) const { 00133 const BucketT *TheBucket; 00134 if (LookupBucketFor(Val, TheBucket)) 00135 return const_iterator(TheBucket, getBucketsEnd(), true); 00136 return end(); 00137 } 00138 00139 /// lookup - Return the entry for the specified key, or a default 00140 /// constructed value if no such entry exists. 00141 ValueT lookup(const KeyT &Val) const { 00142 const BucketT *TheBucket; 00143 if (LookupBucketFor(Val, TheBucket)) 00144 return TheBucket->second; 00145 return ValueT(); 00146 } 00147 00148 // Inserts key,value pair into the map if the key isn't already in the map. 00149 // If the key is already in the map, it returns false and doesn't update the 00150 // value. 00151 std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { 00152 BucketT *TheBucket; 00153 if (LookupBucketFor(KV.first, TheBucket)) 00154 return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), 00155 false); // Already in map. 00156 00157 // Otherwise, insert the new element. 00158 TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket); 00159 return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true); 00160 } 00161 00162 #if LLVM_HAS_RVALUE_REFERENCES 00163 // Inserts key,value pair into the map if the key isn't already in the map. 00164 // If the key is already in the map, it returns false and doesn't update the 00165 // value. 00166 std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) { 00167 BucketT *TheBucket; 00168 if (LookupBucketFor(KV.first, TheBucket)) 00169 return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), 00170 false); // Already in map. 00171 00172 // Otherwise, insert the new element. 00173 TheBucket = InsertIntoBucket(std::move(KV.first), 00174 std::move(KV.second), 00175 TheBucket); 00176 return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true); 00177 } 00178 #endif 00179 00180 /// insert - Range insertion of pairs. 00181 template<typename InputIt> 00182 void insert(InputIt I, InputIt E) { 00183 for (; I != E; ++I) 00184 insert(*I); 00185 } 00186 00187 00188 bool erase(const KeyT &Val) { 00189 BucketT *TheBucket; 00190 if (!LookupBucketFor(Val, TheBucket)) 00191 return false; // not in map. 00192 00193 TheBucket->second.~ValueT(); 00194 TheBucket->first = getTombstoneKey(); 00195 decrementNumEntries(); 00196 incrementNumTombstones(); 00197 return true; 00198 } 00199 void erase(iterator I) { 00200 BucketT *TheBucket = &*I; 00201 TheBucket->second.~ValueT(); 00202 TheBucket->first = getTombstoneKey(); 00203 decrementNumEntries(); 00204 incrementNumTombstones(); 00205 } 00206 00207 value_type& FindAndConstruct(const KeyT &Key) { 00208 BucketT *TheBucket; 00209 if (LookupBucketFor(Key, TheBucket)) 00210 return *TheBucket; 00211 00212 return *InsertIntoBucket(Key, ValueT(), TheBucket); 00213 } 00214 00215 ValueT &operator[](const KeyT &Key) { 00216 return FindAndConstruct(Key).second; 00217 } 00218 00219 #if LLVM_HAS_RVALUE_REFERENCES 00220 value_type& FindAndConstruct(KeyT &&Key) { 00221 BucketT *TheBucket; 00222 if (LookupBucketFor(Key, TheBucket)) 00223 return *TheBucket; 00224 00225 return *InsertIntoBucket(Key, ValueT(), TheBucket); 00226 } 00227 00228 ValueT &operator[](KeyT &&Key) { 00229 return FindAndConstruct(Key).second; 00230 } 00231 #endif 00232 00233 /// isPointerIntoBucketsArray - Return true if the specified pointer points 00234 /// somewhere into the DenseMap's array of buckets (i.e. either to a key or 00235 /// value in the DenseMap). 00236 bool isPointerIntoBucketsArray(const void *Ptr) const { 00237 return Ptr >= getBuckets() && Ptr < getBucketsEnd(); 00238 } 00239 00240 /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets 00241 /// array. In conjunction with the previous method, this can be used to 00242 /// determine whether an insertion caused the DenseMap to reallocate. 00243 const void *getPointerIntoBucketsArray() const { return getBuckets(); } 00244 00245 protected: 00246 DenseMapBase() {} 00247 00248 void destroyAll() { 00249 if (getNumBuckets() == 0) // Nothing to do. 00250 return; 00251 00252 const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); 00253 for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { 00254 if (!KeyInfoT::isEqual(P->first, EmptyKey) && 00255 !KeyInfoT::isEqual(P->first, TombstoneKey)) 00256 P->second.~ValueT(); 00257 P->first.~KeyT(); 00258 } 00259 00260 #ifndef NDEBUG 00261 memset((void*)getBuckets(), 0x5a, sizeof(BucketT)*getNumBuckets()); 00262 #endif 00263 } 00264 00265 void initEmpty() { 00266 setNumEntries(0); 00267 setNumTombstones(0); 00268 00269 assert((getNumBuckets() & (getNumBuckets()-1)) == 0 && 00270 "# initial buckets must be a power of two!"); 00271 const KeyT EmptyKey = getEmptyKey(); 00272 for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B) 00273 new (&B->first) KeyT(EmptyKey); 00274 } 00275 00276 void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) { 00277 initEmpty(); 00278 00279 // Insert all the old elements. 00280 const KeyT EmptyKey = getEmptyKey(); 00281 const KeyT TombstoneKey = getTombstoneKey(); 00282 for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) { 00283 if (!KeyInfoT::isEqual(B->first, EmptyKey) && 00284 !KeyInfoT::isEqual(B->first, TombstoneKey)) { 00285 // Insert the key/value into the new table. 00286 BucketT *DestBucket; 00287 bool FoundVal = LookupBucketFor(B->first, DestBucket); 00288 (void)FoundVal; // silence warning. 00289 assert(!FoundVal && "Key already in new map?"); 00290 DestBucket->first = llvm_move(B->first); 00291 new (&DestBucket->second) ValueT(llvm_move(B->second)); 00292 incrementNumEntries(); 00293 00294 // Free the value. 00295 B->second.~ValueT(); 00296 } 00297 B->first.~KeyT(); 00298 } 00299 00300 #ifndef NDEBUG 00301 if (OldBucketsBegin != OldBucketsEnd) 00302 memset((void*)OldBucketsBegin, 0x5a, 00303 sizeof(BucketT) * (OldBucketsEnd - OldBucketsBegin)); 00304 #endif 00305 } 00306 00307 template <typename OtherBaseT> 00308 void copyFrom(const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT>& other) { 00309 assert(getNumBuckets() == other.getNumBuckets()); 00310 00311 setNumEntries(other.getNumEntries()); 00312 setNumTombstones(other.getNumTombstones()); 00313 00314 if (isPodLike<KeyT>::value && isPodLike<ValueT>::value) 00315 memcpy(getBuckets(), other.getBuckets(), 00316 getNumBuckets() * sizeof(BucketT)); 00317 else 00318 for (size_t i = 0; i < getNumBuckets(); ++i) { 00319 new (&getBuckets()[i].first) KeyT(other.getBuckets()[i].first); 00320 if (!KeyInfoT::isEqual(getBuckets()[i].first, getEmptyKey()) && 00321 !KeyInfoT::isEqual(getBuckets()[i].first, getTombstoneKey())) 00322 new (&getBuckets()[i].second) ValueT(other.getBuckets()[i].second); 00323 } 00324 } 00325 00326 void swap(DenseMapBase& RHS) { 00327 std::swap(getNumEntries(), RHS.getNumEntries()); 00328 std::swap(getNumTombstones(), RHS.getNumTombstones()); 00329 } 00330 00331 static unsigned getHashValue(const KeyT &Val) { 00332 return KeyInfoT::getHashValue(Val); 00333 } 00334 template<typename LookupKeyT> 00335 static unsigned getHashValue(const LookupKeyT &Val) { 00336 return KeyInfoT::getHashValue(Val); 00337 } 00338 static const KeyT getEmptyKey() { 00339 return KeyInfoT::getEmptyKey(); 00340 } 00341 static const KeyT getTombstoneKey() { 00342 return KeyInfoT::getTombstoneKey(); 00343 } 00344 00345 private: 00346 unsigned getNumEntries() const { 00347 return static_cast<const DerivedT *>(this)->getNumEntries(); 00348 } 00349 void setNumEntries(unsigned Num) { 00350 static_cast<DerivedT *>(this)->setNumEntries(Num); 00351 } 00352 void incrementNumEntries() { 00353 setNumEntries(getNumEntries() + 1); 00354 } 00355 void decrementNumEntries() { 00356 setNumEntries(getNumEntries() - 1); 00357 } 00358 unsigned getNumTombstones() const { 00359 return static_cast<const DerivedT *>(this)->getNumTombstones(); 00360 } 00361 void setNumTombstones(unsigned Num) { 00362 static_cast<DerivedT *>(this)->setNumTombstones(Num); 00363 } 00364 void incrementNumTombstones() { 00365 setNumTombstones(getNumTombstones() + 1); 00366 } 00367 void decrementNumTombstones() { 00368 setNumTombstones(getNumTombstones() - 1); 00369 } 00370 const BucketT *getBuckets() const { 00371 return static_cast<const DerivedT *>(this)->getBuckets(); 00372 } 00373 BucketT *getBuckets() { 00374 return static_cast<DerivedT *>(this)->getBuckets(); 00375 } 00376 unsigned getNumBuckets() const { 00377 return static_cast<const DerivedT *>(this)->getNumBuckets(); 00378 } 00379 BucketT *getBucketsEnd() { 00380 return getBuckets() + getNumBuckets(); 00381 } 00382 const BucketT *getBucketsEnd() const { 00383 return getBuckets() + getNumBuckets(); 00384 } 00385 00386 void grow(unsigned AtLeast) { 00387 static_cast<DerivedT *>(this)->grow(AtLeast); 00388 } 00389 00390 void shrink_and_clear() { 00391 static_cast<DerivedT *>(this)->shrink_and_clear(); 00392 } 00393 00394 00395 BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value, 00396 BucketT *TheBucket) { 00397 TheBucket = InsertIntoBucketImpl(Key, TheBucket); 00398 00399 TheBucket->first = Key; 00400 new (&TheBucket->second) ValueT(Value); 00401 return TheBucket; 00402 } 00403 00404 #if LLVM_HAS_RVALUE_REFERENCES 00405 BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value, 00406 BucketT *TheBucket) { 00407 TheBucket = InsertIntoBucketImpl(Key, TheBucket); 00408 00409 TheBucket->first = Key; 00410 new (&TheBucket->second) ValueT(std::move(Value)); 00411 return TheBucket; 00412 } 00413 00414 BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) { 00415 TheBucket = InsertIntoBucketImpl(Key, TheBucket); 00416 00417 TheBucket->first = std::move(Key); 00418 new (&TheBucket->second) ValueT(std::move(Value)); 00419 return TheBucket; 00420 } 00421 #endif 00422 00423 BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) { 00424 // If the load of the hash table is more than 3/4, or if fewer than 1/8 of 00425 // the buckets are empty (meaning that many are filled with tombstones), 00426 // grow the table. 00427 // 00428 // The later case is tricky. For example, if we had one empty bucket with 00429 // tons of tombstones, failing lookups (e.g. for insertion) would have to 00430 // probe almost the entire table until it found the empty bucket. If the 00431 // table completely filled with tombstones, no lookup would ever succeed, 00432 // causing infinite loops in lookup. 00433 unsigned NewNumEntries = getNumEntries() + 1; 00434 unsigned NumBuckets = getNumBuckets(); 00435 if (NewNumEntries*4 >= NumBuckets*3) { 00436 this->grow(NumBuckets * 2); 00437 LookupBucketFor(Key, TheBucket); 00438 NumBuckets = getNumBuckets(); 00439 } 00440 if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) { 00441 this->grow(NumBuckets * 2); 00442 LookupBucketFor(Key, TheBucket); 00443 } 00444 assert(TheBucket); 00445 00446 // Only update the state after we've grown our bucket space appropriately 00447 // so that when growing buckets we have self-consistent entry count. 00448 incrementNumEntries(); 00449 00450 // If we are writing over a tombstone, remember this. 00451 const KeyT EmptyKey = getEmptyKey(); 00452 if (!KeyInfoT::isEqual(TheBucket->first, EmptyKey)) 00453 decrementNumTombstones(); 00454 00455 return TheBucket; 00456 } 00457 00458 /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in 00459 /// FoundBucket. If the bucket contains the key and a value, this returns 00460 /// true, otherwise it returns a bucket with an empty marker or tombstone and 00461 /// returns false. 00462 template<typename LookupKeyT> 00463 bool LookupBucketFor(const LookupKeyT &Val, 00464 const BucketT *&FoundBucket) const { 00465 const BucketT *BucketsPtr = getBuckets(); 00466 const unsigned NumBuckets = getNumBuckets(); 00467 00468 if (NumBuckets == 0) { 00469 FoundBucket = 0; 00470 return false; 00471 } 00472 00473 // FoundTombstone - Keep track of whether we find a tombstone while probing. 00474 const BucketT *FoundTombstone = 0; 00475 const KeyT EmptyKey = getEmptyKey(); 00476 const KeyT TombstoneKey = getTombstoneKey(); 00477 assert(!KeyInfoT::isEqual(Val, EmptyKey) && 00478 !KeyInfoT::isEqual(Val, TombstoneKey) && 00479 "Empty/Tombstone value shouldn't be inserted into map!"); 00480 00481 unsigned BucketNo = getHashValue(Val) & (NumBuckets-1); 00482 unsigned ProbeAmt = 1; 00483 while (1) { 00484 const BucketT *ThisBucket = BucketsPtr + BucketNo; 00485 // Found Val's bucket? If so, return it. 00486 if (KeyInfoT::isEqual(Val, ThisBucket->first)) { 00487 FoundBucket = ThisBucket; 00488 return true; 00489 } 00490 00491 // If we found an empty bucket, the key doesn't exist in the set. 00492 // Insert it and return the default value. 00493 if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) { 00494 // If we've already seen a tombstone while probing, fill it in instead 00495 // of the empty bucket we eventually probed to. 00496 FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; 00497 return false; 00498 } 00499 00500 // If this is a tombstone, remember it. If Val ends up not in the map, we 00501 // prefer to return it than something that would require more probing. 00502 if (KeyInfoT::isEqual(ThisBucket->first, TombstoneKey) && !FoundTombstone) 00503 FoundTombstone = ThisBucket; // Remember the first tombstone found. 00504 00505 // Otherwise, it's a hash collision or a tombstone, continue quadratic 00506 // probing. 00507 BucketNo += ProbeAmt++; 00508 BucketNo &= (NumBuckets-1); 00509 } 00510 } 00511 00512 template <typename LookupKeyT> 00513 bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) { 00514 const BucketT *ConstFoundBucket; 00515 bool Result = const_cast<const DenseMapBase *>(this) 00516 ->LookupBucketFor(Val, ConstFoundBucket); 00517 FoundBucket = const_cast<BucketT *>(ConstFoundBucket); 00518 return Result; 00519 } 00520 00521 public: 00522 /// Return the approximate size (in bytes) of the actual map. 00523 /// This is just the raw memory used by DenseMap. 00524 /// If entries are pointers to objects, the size of the referenced objects 00525 /// are not included. 00526 size_t getMemorySize() const { 00527 return getNumBuckets() * sizeof(BucketT); 00528 } 00529 }; 00530 00531 template<typename KeyT, typename ValueT, 00532 typename KeyInfoT = DenseMapInfo<KeyT> > 00533 class DenseMap 00534 : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT>, 00535 KeyT, ValueT, KeyInfoT> { 00536 // Lift some types from the dependent base class into this class for 00537 // simplicity of referring to them. 00538 typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT> BaseT; 00539 typedef typename BaseT::BucketT BucketT; 00540 friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT>; 00541 00542 BucketT *Buckets; 00543 unsigned NumEntries; 00544 unsigned NumTombstones; 00545 unsigned NumBuckets; 00546 00547 public: 00548 explicit DenseMap(unsigned NumInitBuckets = 0) { 00549 init(NumInitBuckets); 00550 } 00551 00552 DenseMap(const DenseMap &other) : BaseT() { 00553 init(0); 00554 copyFrom(other); 00555 } 00556 00557 #if LLVM_HAS_RVALUE_REFERENCES 00558 DenseMap(DenseMap &&other) : BaseT() { 00559 init(0); 00560 swap(other); 00561 } 00562 #endif 00563 00564 template<typename InputIt> 00565 DenseMap(const InputIt &I, const InputIt &E) { 00566 init(NextPowerOf2(std::distance(I, E))); 00567 this->insert(I, E); 00568 } 00569 00570 ~DenseMap() { 00571 this->destroyAll(); 00572 operator delete(Buckets); 00573 } 00574 00575 void swap(DenseMap& RHS) { 00576 std::swap(Buckets, RHS.Buckets); 00577 std::swap(NumEntries, RHS.NumEntries); 00578 std::swap(NumTombstones, RHS.NumTombstones); 00579 std::swap(NumBuckets, RHS.NumBuckets); 00580 } 00581 00582 DenseMap& operator=(const DenseMap& other) { 00583 copyFrom(other); 00584 return *this; 00585 } 00586 00587 #if LLVM_HAS_RVALUE_REFERENCES 00588 DenseMap& operator=(DenseMap &&other) { 00589 this->destroyAll(); 00590 operator delete(Buckets); 00591 init(0); 00592 swap(other); 00593 return *this; 00594 } 00595 #endif 00596 00597 void copyFrom(const DenseMap& other) { 00598 this->destroyAll(); 00599 operator delete(Buckets); 00600 if (allocateBuckets(other.NumBuckets)) { 00601 this->BaseT::copyFrom(other); 00602 } else { 00603 NumEntries = 0; 00604 NumTombstones = 0; 00605 } 00606 } 00607 00608 void init(unsigned InitBuckets) { 00609 if (allocateBuckets(InitBuckets)) { 00610 this->BaseT::initEmpty(); 00611 } else { 00612 NumEntries = 0; 00613 NumTombstones = 0; 00614 } 00615 } 00616 00617 void grow(unsigned AtLeast) { 00618 unsigned OldNumBuckets = NumBuckets; 00619 BucketT *OldBuckets = Buckets; 00620 00621 allocateBuckets(std::max<unsigned>(64, static_cast<unsigned>(NextPowerOf2(AtLeast-1)))); 00622 assert(Buckets); 00623 if (!OldBuckets) { 00624 this->BaseT::initEmpty(); 00625 return; 00626 } 00627 00628 this->moveFromOldBuckets(OldBuckets, OldBuckets+OldNumBuckets); 00629 00630 // Free the old table. 00631 operator delete(OldBuckets); 00632 } 00633 00634 void shrink_and_clear() { 00635 unsigned OldNumEntries = NumEntries; 00636 this->destroyAll(); 00637 00638 // Reduce the number of buckets. 00639 unsigned NewNumBuckets = 0; 00640 if (OldNumEntries) 00641 NewNumBuckets = std::max(64, 1 << (Log2_32_Ceil(OldNumEntries) + 1)); 00642 if (NewNumBuckets == NumBuckets) { 00643 this->BaseT::initEmpty(); 00644 return; 00645 } 00646 00647 operator delete(Buckets); 00648 init(NewNumBuckets); 00649 } 00650 00651 private: 00652 unsigned getNumEntries() const { 00653 return NumEntries; 00654 } 00655 void setNumEntries(unsigned Num) { 00656 NumEntries = Num; 00657 } 00658 00659 unsigned getNumTombstones() const { 00660 return NumTombstones; 00661 } 00662 void setNumTombstones(unsigned Num) { 00663 NumTombstones = Num; 00664 } 00665 00666 BucketT *getBuckets() const { 00667 return Buckets; 00668 } 00669 00670 unsigned getNumBuckets() const { 00671 return NumBuckets; 00672 } 00673 00674 bool allocateBuckets(unsigned Num) { 00675 NumBuckets = Num; 00676 if (NumBuckets == 0) { 00677 Buckets = 0; 00678 return false; 00679 } 00680 00681 Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT) * NumBuckets)); 00682 return true; 00683 } 00684 }; 00685 00686 template<typename KeyT, typename ValueT, 00687 unsigned InlineBuckets = 4, 00688 typename KeyInfoT = DenseMapInfo<KeyT> > 00689 class SmallDenseMap 00690 : public DenseMapBase<SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT>, 00691 KeyT, ValueT, KeyInfoT> { 00692 // Lift some types from the dependent base class into this class for 00693 // simplicity of referring to them. 00694 typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT> BaseT; 00695 typedef typename BaseT::BucketT BucketT; 00696 friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT>; 00697 00698 unsigned Small : 1; 00699 unsigned NumEntries : 31; 00700 unsigned NumTombstones; 00701 00702 struct LargeRep { 00703 BucketT *Buckets; 00704 unsigned NumBuckets; 00705 }; 00706 00707 /// A "union" of an inline bucket array and the struct representing 00708 /// a large bucket. This union will be discriminated by the 'Small' bit. 00709 AlignedCharArrayUnion<BucketT[InlineBuckets], LargeRep> storage; 00710 00711 public: 00712 explicit SmallDenseMap(unsigned NumInitBuckets = 0) { 00713 init(NumInitBuckets); 00714 } 00715 00716 SmallDenseMap(const SmallDenseMap &other) { 00717 init(0); 00718 copyFrom(other); 00719 } 00720 00721 #if LLVM_HAS_RVALUE_REFERENCES 00722 SmallDenseMap(SmallDenseMap &&other) { 00723 init(0); 00724 swap(other); 00725 } 00726 #endif 00727 00728 template<typename InputIt> 00729 SmallDenseMap(const InputIt &I, const InputIt &E) { 00730 init(NextPowerOf2(std::distance(I, E))); 00731 this->insert(I, E); 00732 } 00733 00734 ~SmallDenseMap() { 00735 this->destroyAll(); 00736 deallocateBuckets(); 00737 } 00738 00739 void swap(SmallDenseMap& RHS) { 00740 unsigned TmpNumEntries = RHS.NumEntries; 00741 RHS.NumEntries = NumEntries; 00742 NumEntries = TmpNumEntries; 00743 std::swap(NumTombstones, RHS.NumTombstones); 00744 00745 const KeyT EmptyKey = this->getEmptyKey(); 00746 const KeyT TombstoneKey = this->getTombstoneKey(); 00747 if (Small && RHS.Small) { 00748 // If we're swapping inline bucket arrays, we have to cope with some of 00749 // the tricky bits of DenseMap's storage system: the buckets are not 00750 // fully initialized. Thus we swap every key, but we may have 00751 // a one-directional move of the value. 00752 for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { 00753 BucketT *LHSB = &getInlineBuckets()[i], 00754 *RHSB = &RHS.getInlineBuckets()[i]; 00755 bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->first, EmptyKey) && 00756 !KeyInfoT::isEqual(LHSB->first, TombstoneKey)); 00757 bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->first, EmptyKey) && 00758 !KeyInfoT::isEqual(RHSB->first, TombstoneKey)); 00759 if (hasLHSValue && hasRHSValue) { 00760 // Swap together if we can... 00761 std::swap(*LHSB, *RHSB); 00762 continue; 00763 } 00764 // Swap separately and handle any assymetry. 00765 std::swap(LHSB->first, RHSB->first); 00766 if (hasLHSValue) { 00767 new (&RHSB->second) ValueT(llvm_move(LHSB->second)); 00768 LHSB->second.~ValueT(); 00769 } else if (hasRHSValue) { 00770 new (&LHSB->second) ValueT(llvm_move(RHSB->second)); 00771 RHSB->second.~ValueT(); 00772 } 00773 } 00774 return; 00775 } 00776 if (!Small && !RHS.Small) { 00777 std::swap(getLargeRep()->Buckets, RHS.getLargeRep()->Buckets); 00778 std::swap(getLargeRep()->NumBuckets, RHS.getLargeRep()->NumBuckets); 00779 return; 00780 } 00781 00782 SmallDenseMap &SmallSide = Small ? *this : RHS; 00783 SmallDenseMap &LargeSide = Small ? RHS : *this; 00784 00785 // First stash the large side's rep and move the small side across. 00786 LargeRep TmpRep = llvm_move(*LargeSide.getLargeRep()); 00787 LargeSide.getLargeRep()->~LargeRep(); 00788 LargeSide.Small = true; 00789 // This is similar to the standard move-from-old-buckets, but the bucket 00790 // count hasn't actually rotated in this case. So we have to carefully 00791 // move construct the keys and values into their new locations, but there 00792 // is no need to re-hash things. 00793 for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { 00794 BucketT *NewB = &LargeSide.getInlineBuckets()[i], 00795 *OldB = &SmallSide.getInlineBuckets()[i]; 00796 new (&NewB->first) KeyT(llvm_move(OldB->first)); 00797 OldB->first.~KeyT(); 00798 if (!KeyInfoT::isEqual(NewB->first, EmptyKey) && 00799 !KeyInfoT::isEqual(NewB->first, TombstoneKey)) { 00800 new (&NewB->second) ValueT(llvm_move(OldB->second)); 00801 OldB->second.~ValueT(); 00802 } 00803 } 00804 00805 // The hard part of moving the small buckets across is done, just move 00806 // the TmpRep into its new home. 00807 SmallSide.Small = false; 00808 new (SmallSide.getLargeRep()) LargeRep(llvm_move(TmpRep)); 00809 } 00810 00811 SmallDenseMap& operator=(const SmallDenseMap& other) { 00812 copyFrom(other); 00813 return *this; 00814 } 00815 00816 #if LLVM_HAS_RVALUE_REFERENCES 00817 SmallDenseMap& operator=(SmallDenseMap &&other) { 00818 this->destroyAll(); 00819 deallocateBuckets(); 00820 init(0); 00821 swap(other); 00822 return *this; 00823 } 00824 #endif 00825 00826 void copyFrom(const SmallDenseMap& other) { 00827 this->destroyAll(); 00828 deallocateBuckets(); 00829 Small = true; 00830 if (other.getNumBuckets() > InlineBuckets) { 00831 Small = false; 00832 allocateBuckets(other.getNumBuckets()); 00833 } 00834 this->BaseT::copyFrom(other); 00835 } 00836 00837 void init(unsigned InitBuckets) { 00838 Small = true; 00839 if (InitBuckets > InlineBuckets) { 00840 Small = false; 00841 new (getLargeRep()) LargeRep(allocateBuckets(InitBuckets)); 00842 } 00843 this->BaseT::initEmpty(); 00844 } 00845 00846 void grow(unsigned AtLeast) { 00847 if (AtLeast >= InlineBuckets) 00848 AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast-1)); 00849 00850 if (Small) { 00851 if (AtLeast < InlineBuckets) 00852 return; // Nothing to do. 00853 00854 // First move the inline buckets into a temporary storage. 00855 AlignedCharArrayUnion<BucketT[InlineBuckets]> TmpStorage; 00856 BucketT *TmpBegin = reinterpret_cast<BucketT *>(TmpStorage.buffer); 00857 BucketT *TmpEnd = TmpBegin; 00858 00859 // Loop over the buckets, moving non-empty, non-tombstones into the 00860 // temporary storage. Have the loop move the TmpEnd forward as it goes. 00861 const KeyT EmptyKey = this->getEmptyKey(); 00862 const KeyT TombstoneKey = this->getTombstoneKey(); 00863 for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) { 00864 if (!KeyInfoT::isEqual(P->first, EmptyKey) && 00865 !KeyInfoT::isEqual(P->first, TombstoneKey)) { 00866 assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && 00867 "Too many inline buckets!"); 00868 new (&TmpEnd->first) KeyT(llvm_move(P->first)); 00869 new (&TmpEnd->second) ValueT(llvm_move(P->second)); 00870 ++TmpEnd; 00871 P->second.~ValueT(); 00872 } 00873 P->first.~KeyT(); 00874 } 00875 00876 // Now make this map use the large rep, and move all the entries back 00877 // into it. 00878 Small = false; 00879 new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); 00880 this->moveFromOldBuckets(TmpBegin, TmpEnd); 00881 return; 00882 } 00883 00884 LargeRep OldRep = llvm_move(*getLargeRep()); 00885 getLargeRep()->~LargeRep(); 00886 if (AtLeast <= InlineBuckets) { 00887 Small = true; 00888 } else { 00889 new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); 00890 } 00891 00892 this->moveFromOldBuckets(OldRep.Buckets, OldRep.Buckets+OldRep.NumBuckets); 00893 00894 // Free the old table. 00895 operator delete(OldRep.Buckets); 00896 } 00897 00898 void shrink_and_clear() { 00899 unsigned OldSize = this->size(); 00900 this->destroyAll(); 00901 00902 // Reduce the number of buckets. 00903 unsigned NewNumBuckets = 0; 00904 if (OldSize) { 00905 NewNumBuckets = 1 << (Log2_32_Ceil(OldSize) + 1); 00906 if (NewNumBuckets > InlineBuckets && NewNumBuckets < 64u) 00907 NewNumBuckets = 64; 00908 } 00909 if ((Small && NewNumBuckets <= InlineBuckets) || 00910 (!Small && NewNumBuckets == getLargeRep()->NumBuckets)) { 00911 this->BaseT::initEmpty(); 00912 return; 00913 } 00914 00915 deallocateBuckets(); 00916 init(NewNumBuckets); 00917 } 00918 00919 private: 00920 unsigned getNumEntries() const { 00921 return NumEntries; 00922 } 00923 void setNumEntries(unsigned Num) { 00924 assert(Num < INT_MAX && "Cannot support more than INT_MAX entries"); 00925 NumEntries = Num; 00926 } 00927 00928 unsigned getNumTombstones() const { 00929 return NumTombstones; 00930 } 00931 void setNumTombstones(unsigned Num) { 00932 NumTombstones = Num; 00933 } 00934 00935 const BucketT *getInlineBuckets() const { 00936 assert(Small); 00937 // Note that this cast does not violate aliasing rules as we assert that 00938 // the memory's dynamic type is the small, inline bucket buffer, and the 00939 // 'storage.buffer' static type is 'char *'. 00940 return reinterpret_cast<const BucketT *>(storage.buffer); 00941 } 00942 BucketT *getInlineBuckets() { 00943 return const_cast<BucketT *>( 00944 const_cast<const SmallDenseMap *>(this)->getInlineBuckets()); 00945 } 00946 const LargeRep *getLargeRep() const { 00947 assert(!Small); 00948 // Note, same rule about aliasing as with getInlineBuckets. 00949 return reinterpret_cast<const LargeRep *>(storage.buffer); 00950 } 00951 LargeRep *getLargeRep() { 00952 return const_cast<LargeRep *>( 00953 const_cast<const SmallDenseMap *>(this)->getLargeRep()); 00954 } 00955 00956 const BucketT *getBuckets() const { 00957 return Small ? getInlineBuckets() : getLargeRep()->Buckets; 00958 } 00959 BucketT *getBuckets() { 00960 return const_cast<BucketT *>( 00961 const_cast<const SmallDenseMap *>(this)->getBuckets()); 00962 } 00963 unsigned getNumBuckets() const { 00964 return Small ? InlineBuckets : getLargeRep()->NumBuckets; 00965 } 00966 00967 void deallocateBuckets() { 00968 if (Small) 00969 return; 00970 00971 operator delete(getLargeRep()->Buckets); 00972 getLargeRep()->~LargeRep(); 00973 } 00974 00975 LargeRep allocateBuckets(unsigned Num) { 00976 assert(Num > InlineBuckets && "Must allocate more buckets than are inline"); 00977 LargeRep Rep = { 00978 static_cast<BucketT*>(operator new(sizeof(BucketT) * Num)), Num 00979 }; 00980 return Rep; 00981 } 00982 }; 00983 00984 template<typename KeyT, typename ValueT, 00985 typename KeyInfoT, bool IsConst> 00986 class DenseMapIterator { 00987 typedef std::pair<KeyT, ValueT> Bucket; 00988 typedef DenseMapIterator<KeyT, ValueT, 00989 KeyInfoT, true> ConstIterator; 00990 friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, true>; 00991 public: 00992 typedef ptrdiff_t difference_type; 00993 typedef typename conditional<IsConst, const Bucket, Bucket>::type value_type; 00994 typedef value_type *pointer; 00995 typedef value_type &reference; 00996 typedef std::forward_iterator_tag iterator_category; 00997 private: 00998 pointer Ptr, End; 00999 public: 01000 DenseMapIterator() : Ptr(0), End(0) {} 01001 01002 DenseMapIterator(pointer Pos, pointer E, bool NoAdvance = false) 01003 : Ptr(Pos), End(E) { 01004 if (!NoAdvance) AdvancePastEmptyBuckets(); 01005 } 01006 01007 // If IsConst is true this is a converting constructor from iterator to 01008 // const_iterator and the default copy constructor is used. 01009 // Otherwise this is a copy constructor for iterator. 01010 DenseMapIterator(const DenseMapIterator<KeyT, ValueT, 01011 KeyInfoT, false>& I) 01012 : Ptr(I.Ptr), End(I.End) {} 01013 01014 reference operator*() const { 01015 return *Ptr; 01016 } 01017 pointer operator->() const { 01018 return Ptr; 01019 } 01020 01021 bool operator==(const ConstIterator &RHS) const { 01022 return Ptr == RHS.operator->(); 01023 } 01024 bool operator!=(const ConstIterator &RHS) const { 01025 return Ptr != RHS.operator->(); 01026 } 01027 01028 inline DenseMapIterator& operator++() { // Preincrement 01029 ++Ptr; 01030 AdvancePastEmptyBuckets(); 01031 return *this; 01032 } 01033 DenseMapIterator operator++(int) { // Postincrement 01034 DenseMapIterator tmp = *this; ++*this; return tmp; 01035 } 01036 01037 private: 01038 void AdvancePastEmptyBuckets() { 01039 const KeyT Empty = KeyInfoT::getEmptyKey(); 01040 const KeyT Tombstone = KeyInfoT::getTombstoneKey(); 01041 01042 while (Ptr != End && 01043 (KeyInfoT::isEqual(Ptr->first, Empty) || 01044 KeyInfoT::isEqual(Ptr->first, Tombstone))) 01045 ++Ptr; 01046 } 01047 }; 01048 01049 template<typename KeyT, typename ValueT, typename KeyInfoT> 01050 static inline size_t 01051 capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT> &X) { 01052 return X.getMemorySize(); 01053 } 01054 01055 } // end namespace llvm 01056 01057 #endif