1 //===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the StringMap class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_ADT_STRINGMAP_H 15 #define LLVM_ADT_STRINGMAP_H 16 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/Support/Allocator.h" 19 #include "llvm/Support/PointerLikeTypeTraits.h" 20 #include <cassert> 21 #include <cstdint> 22 #include <cstdlib> 23 #include <cstring> 24 #include <utility> 25 #include <initializer_list> 26 #include <new> 27 #include <utility> 28 29 namespace llvm { 30 31 template<typename ValueT> 32 class StringMapConstIterator; 33 template<typename ValueT> 34 class StringMapIterator; 35 template<typename ValueTy> 36 class StringMapEntry; 37 38 /// StringMapEntryBase - Shared base class of StringMapEntry instances. 39 class StringMapEntryBase { 40 unsigned StrLen; 41 42 public: StringMapEntryBase(unsigned Len)43 explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {} 44 getKeyLength()45 unsigned getKeyLength() const { return StrLen; } 46 }; 47 48 /// StringMapImpl - This is the base class of StringMap that is shared among 49 /// all of its instantiations. 50 class StringMapImpl { 51 protected: 52 // Array of NumBuckets pointers to entries, null pointers are holes. 53 // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed 54 // by an array of the actual hash values as unsigned integers. 55 StringMapEntryBase **TheTable; 56 unsigned NumBuckets; 57 unsigned NumItems; 58 unsigned NumTombstones; 59 unsigned ItemSize; 60 61 protected: StringMapImpl(unsigned itemSize)62 explicit StringMapImpl(unsigned itemSize) 63 : TheTable(nullptr), 64 // Initialize the map with zero buckets to allocation. 65 NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {} StringMapImpl(StringMapImpl && RHS)66 StringMapImpl(StringMapImpl &&RHS) 67 : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets), 68 NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones), 69 ItemSize(RHS.ItemSize) { 70 RHS.TheTable = nullptr; 71 RHS.NumBuckets = 0; 72 RHS.NumItems = 0; 73 RHS.NumTombstones = 0; 74 } 75 76 StringMapImpl(unsigned InitSize, unsigned ItemSize); 77 unsigned RehashTable(unsigned BucketNo = 0); 78 79 /// LookupBucketFor - Look up the bucket that the specified string should end 80 /// up in. If it already exists as a key in the map, the Item pointer for the 81 /// specified bucket will be non-null. Otherwise, it will be null. In either 82 /// case, the FullHashValue field of the bucket will be set to the hash value 83 /// of the string. 84 unsigned LookupBucketFor(StringRef Key); 85 86 /// FindKey - Look up the bucket that contains the specified key. If it exists 87 /// in the map, return the bucket number of the key. Otherwise return -1. 88 /// This does not modify the map. 89 int FindKey(StringRef Key) const; 90 91 /// RemoveKey - Remove the specified StringMapEntry from the table, but do not 92 /// delete it. This aborts if the value isn't in the table. 93 void RemoveKey(StringMapEntryBase *V); 94 95 /// RemoveKey - Remove the StringMapEntry for the specified key from the 96 /// table, returning it. If the key is not in the table, this returns null. 97 StringMapEntryBase *RemoveKey(StringRef Key); 98 99 /// Allocate the table with the specified number of buckets and otherwise 100 /// setup the map as empty. 101 void init(unsigned Size); 102 103 public: getTombstoneVal()104 static StringMapEntryBase *getTombstoneVal() { 105 uintptr_t Val = static_cast<uintptr_t>(-1); 106 Val <<= PointerLikeTypeTraits<StringMapEntryBase *>::NumLowBitsAvailable; 107 return reinterpret_cast<StringMapEntryBase *>(Val); 108 } 109 getNumBuckets()110 unsigned getNumBuckets() const { return NumBuckets; } getNumItems()111 unsigned getNumItems() const { return NumItems; } 112 empty()113 bool empty() const { return NumItems == 0; } size()114 unsigned size() const { return NumItems; } 115 swap(StringMapImpl & Other)116 void swap(StringMapImpl &Other) { 117 std::swap(TheTable, Other.TheTable); 118 std::swap(NumBuckets, Other.NumBuckets); 119 std::swap(NumItems, Other.NumItems); 120 std::swap(NumTombstones, Other.NumTombstones); 121 } 122 }; 123 124 /// StringMapEntry - This is used to represent one value that is inserted into 125 /// a StringMap. It contains the Value itself and the key: the string length 126 /// and data. 127 template<typename ValueTy> 128 class StringMapEntry : public StringMapEntryBase { 129 public: 130 ValueTy second; 131 StringMapEntry(unsigned strLen)132 explicit StringMapEntry(unsigned strLen) 133 : StringMapEntryBase(strLen), second() {} 134 template <typename... InitTy> StringMapEntry(unsigned strLen,InitTy &&...InitVals)135 StringMapEntry(unsigned strLen, InitTy &&... InitVals) 136 : StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {} 137 StringMapEntry(StringMapEntry &E) = delete; 138 getKey()139 StringRef getKey() const { 140 return StringRef(getKeyData(), getKeyLength()); 141 } 142 getValue()143 const ValueTy &getValue() const { return second; } getValue()144 ValueTy &getValue() { return second; } 145 setValue(const ValueTy & V)146 void setValue(const ValueTy &V) { second = V; } 147 148 /// getKeyData - Return the start of the string data that is the key for this 149 /// value. The string data is always stored immediately after the 150 /// StringMapEntry object. getKeyData()151 const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);} 152 first()153 StringRef first() const { return StringRef(getKeyData(), getKeyLength()); } 154 155 /// Create a StringMapEntry for the specified key construct the value using 156 /// \p InitiVals. 157 template <typename AllocatorTy, typename... InitTy> Create(StringRef Key,AllocatorTy & Allocator,InitTy &&...InitVals)158 static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator, 159 InitTy &&... InitVals) { 160 unsigned KeyLength = Key.size(); 161 162 // Allocate a new item with space for the string at the end and a null 163 // terminator. 164 unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+ 165 KeyLength+1; 166 unsigned Alignment = alignof(StringMapEntry); 167 168 StringMapEntry *NewItem = 169 static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment)); 170 171 // Construct the value. 172 new (NewItem) StringMapEntry(KeyLength, std::forward<InitTy>(InitVals)...); 173 174 // Copy the string information. 175 char *StrBuffer = const_cast<char*>(NewItem->getKeyData()); 176 if (KeyLength > 0) 177 memcpy(StrBuffer, Key.data(), KeyLength); 178 StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. 179 return NewItem; 180 } 181 182 /// Create - Create a StringMapEntry with normal malloc/free. 183 template <typename... InitType> Create(StringRef Key,InitType &&...InitVal)184 static StringMapEntry *Create(StringRef Key, InitType &&... InitVal) { 185 MallocAllocator A; 186 return Create(Key, A, std::forward<InitType>(InitVal)...); 187 } 188 Create(StringRef Key)189 static StringMapEntry *Create(StringRef Key) { 190 return Create(Key, ValueTy()); 191 } 192 193 /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded 194 /// into a StringMapEntry, return the StringMapEntry itself. GetStringMapEntryFromKeyData(const char * KeyData)195 static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { 196 char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>); 197 return *reinterpret_cast<StringMapEntry*>(Ptr); 198 } 199 200 /// Destroy - Destroy this StringMapEntry, releasing memory back to the 201 /// specified allocator. 202 template<typename AllocatorTy> Destroy(AllocatorTy & Allocator)203 void Destroy(AllocatorTy &Allocator) { 204 // Free memory referenced by the item. 205 unsigned AllocSize = 206 static_cast<unsigned>(sizeof(StringMapEntry)) + getKeyLength() + 1; 207 this->~StringMapEntry(); 208 Allocator.Deallocate(static_cast<void *>(this), AllocSize); 209 } 210 211 /// Destroy this object, releasing memory back to the malloc allocator. Destroy()212 void Destroy() { 213 MallocAllocator A; 214 Destroy(A); 215 } 216 }; 217 218 /// StringMap - This is an unconventional map that is specialized for handling 219 /// keys that are "strings", which are basically ranges of bytes. This does some 220 /// funky memory allocation and hashing things to make it extremely efficient, 221 /// storing the string data *after* the value in the map. 222 template<typename ValueTy, typename AllocatorTy = MallocAllocator> 223 class StringMap : public StringMapImpl { 224 AllocatorTy Allocator; 225 226 public: 227 typedef StringMapEntry<ValueTy> MapEntryTy; 228 StringMap()229 StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {} StringMap(unsigned InitialSize)230 explicit StringMap(unsigned InitialSize) 231 : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {} 232 StringMap(AllocatorTy A)233 explicit StringMap(AllocatorTy A) 234 : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {} 235 StringMap(unsigned InitialSize,AllocatorTy A)236 StringMap(unsigned InitialSize, AllocatorTy A) 237 : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))), 238 Allocator(A) {} 239 StringMap(std::initializer_list<std::pair<StringRef,ValueTy>> List)240 StringMap(std::initializer_list<std::pair<StringRef, ValueTy>> List) 241 : StringMapImpl(List.size(), static_cast<unsigned>(sizeof(MapEntryTy))) { 242 for (const auto &P : List) { 243 insert(P); 244 } 245 } 246 StringMap(StringMap && RHS)247 StringMap(StringMap &&RHS) 248 : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {} 249 250 StringMap &operator=(StringMap RHS) { 251 StringMapImpl::swap(RHS); 252 std::swap(Allocator, RHS.Allocator); 253 return *this; 254 } 255 StringMap(const StringMap & RHS)256 StringMap(const StringMap &RHS) : 257 StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), 258 Allocator(RHS.Allocator) { 259 if (RHS.empty()) 260 return; 261 262 // Allocate TheTable of the same size as RHS's TheTable, and set the 263 // sentinel appropriately (and NumBuckets). 264 init(RHS.NumBuckets); 265 unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1), 266 *RHSHashTable = (unsigned *)(RHS.TheTable + NumBuckets + 1); 267 268 NumItems = RHS.NumItems; 269 NumTombstones = RHS.NumTombstones; 270 for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 271 StringMapEntryBase *Bucket = RHS.TheTable[I]; 272 if (!Bucket || Bucket == getTombstoneVal()) { 273 TheTable[I] = Bucket; 274 continue; 275 } 276 277 TheTable[I] = MapEntryTy::Create( 278 static_cast<MapEntryTy *>(Bucket)->getKey(), Allocator, 279 static_cast<MapEntryTy *>(Bucket)->getValue()); 280 HashTable[I] = RHSHashTable[I]; 281 } 282 283 // Note that here we've copied everything from the RHS into this object, 284 // tombstones included. We could, instead, have re-probed for each key to 285 // instantiate this new object without any tombstone buckets. The 286 // assumption here is that items are rarely deleted from most StringMaps, 287 // and so tombstones are rare, so the cost of re-probing for all inputs is 288 // not worthwhile. 289 } 290 getAllocator()291 AllocatorTy &getAllocator() { return Allocator; } getAllocator()292 const AllocatorTy &getAllocator() const { return Allocator; } 293 294 typedef const char* key_type; 295 typedef ValueTy mapped_type; 296 typedef StringMapEntry<ValueTy> value_type; 297 typedef size_t size_type; 298 299 typedef StringMapConstIterator<ValueTy> const_iterator; 300 typedef StringMapIterator<ValueTy> iterator; 301 begin()302 iterator begin() { 303 return iterator(TheTable, NumBuckets == 0); 304 } end()305 iterator end() { 306 return iterator(TheTable+NumBuckets, true); 307 } begin()308 const_iterator begin() const { 309 return const_iterator(TheTable, NumBuckets == 0); 310 } end()311 const_iterator end() const { 312 return const_iterator(TheTable+NumBuckets, true); 313 } 314 find(StringRef Key)315 iterator find(StringRef Key) { 316 int Bucket = FindKey(Key); 317 if (Bucket == -1) return end(); 318 return iterator(TheTable+Bucket, true); 319 } 320 find(StringRef Key)321 const_iterator find(StringRef Key) const { 322 int Bucket = FindKey(Key); 323 if (Bucket == -1) return end(); 324 return const_iterator(TheTable+Bucket, true); 325 } 326 327 /// lookup - Return the entry for the specified key, or a default 328 /// constructed value if no such entry exists. lookup(StringRef Key)329 ValueTy lookup(StringRef Key) const { 330 const_iterator it = find(Key); 331 if (it != end()) 332 return it->second; 333 return ValueTy(); 334 } 335 336 /// Lookup the ValueTy for the \p Key, or create a default constructed value 337 /// if the key is not in the map. 338 ValueTy &operator[](StringRef Key) { return try_emplace(Key).first->second; } 339 340 /// count - Return 1 if the element is in the map, 0 otherwise. count(StringRef Key)341 size_type count(StringRef Key) const { 342 return find(Key) == end() ? 0 : 1; 343 } 344 345 /// insert - Insert the specified key/value pair into the map. If the key 346 /// already exists in the map, return false and ignore the request, otherwise 347 /// insert it and return true. insert(MapEntryTy * KeyValue)348 bool insert(MapEntryTy *KeyValue) { 349 unsigned BucketNo = LookupBucketFor(KeyValue->getKey()); 350 StringMapEntryBase *&Bucket = TheTable[BucketNo]; 351 if (Bucket && Bucket != getTombstoneVal()) 352 return false; // Already exists in map. 353 354 if (Bucket == getTombstoneVal()) 355 --NumTombstones; 356 Bucket = KeyValue; 357 ++NumItems; 358 assert(NumItems + NumTombstones <= NumBuckets); 359 360 RehashTable(); 361 return true; 362 } 363 364 /// insert - Inserts the specified key/value pair into the map if the key 365 /// isn't already in the map. The bool component of the returned pair is true 366 /// if and only if the insertion takes place, and the iterator component of 367 /// the pair points to the element with key equivalent to the key of the pair. insert(std::pair<StringRef,ValueTy> KV)368 std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) { 369 return try_emplace(KV.first, std::move(KV.second)); 370 } 371 372 /// Emplace a new element for the specified key into the map if the key isn't 373 /// already in the map. The bool component of the returned pair is true 374 /// if and only if the insertion takes place, and the iterator component of 375 /// the pair points to the element with key equivalent to the key of the pair. 376 template <typename... ArgsTy> try_emplace(StringRef Key,ArgsTy &&...Args)377 std::pair<iterator, bool> try_emplace(StringRef Key, ArgsTy &&... Args) { 378 unsigned BucketNo = LookupBucketFor(Key); 379 StringMapEntryBase *&Bucket = TheTable[BucketNo]; 380 if (Bucket && Bucket != getTombstoneVal()) 381 return std::make_pair(iterator(TheTable + BucketNo, false), 382 false); // Already exists in map. 383 384 if (Bucket == getTombstoneVal()) 385 --NumTombstones; 386 Bucket = MapEntryTy::Create(Key, Allocator, std::forward<ArgsTy>(Args)...); 387 ++NumItems; 388 assert(NumItems + NumTombstones <= NumBuckets); 389 390 BucketNo = RehashTable(BucketNo); 391 return std::make_pair(iterator(TheTable + BucketNo, false), true); 392 } 393 394 // clear - Empties out the StringMap clear()395 void clear() { 396 if (empty()) return; 397 398 // Zap all values, resetting the keys back to non-present (not tombstone), 399 // which is safe because we're removing all elements. 400 for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 401 StringMapEntryBase *&Bucket = TheTable[I]; 402 if (Bucket && Bucket != getTombstoneVal()) { 403 static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator); 404 } 405 Bucket = nullptr; 406 } 407 408 NumItems = 0; 409 NumTombstones = 0; 410 } 411 412 /// remove - Remove the specified key/value pair from the map, but do not 413 /// erase it. This aborts if the key is not in the map. remove(MapEntryTy * KeyValue)414 void remove(MapEntryTy *KeyValue) { 415 RemoveKey(KeyValue); 416 } 417 erase(iterator I)418 void erase(iterator I) { 419 MapEntryTy &V = *I; 420 remove(&V); 421 V.Destroy(Allocator); 422 } 423 erase(StringRef Key)424 bool erase(StringRef Key) { 425 iterator I = find(Key); 426 if (I == end()) return false; 427 erase(I); 428 return true; 429 } 430 ~StringMap()431 ~StringMap() { 432 // Delete all the elements in the map, but don't reset the elements 433 // to default values. This is a copy of clear(), but avoids unnecessary 434 // work not required in the destructor. 435 if (!empty()) { 436 for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 437 StringMapEntryBase *Bucket = TheTable[I]; 438 if (Bucket && Bucket != getTombstoneVal()) { 439 static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator); 440 } 441 } 442 } 443 free(TheTable); 444 } 445 }; 446 447 template <typename ValueTy> class StringMapConstIterator { 448 protected: 449 StringMapEntryBase **Ptr = nullptr; 450 451 public: 452 typedef StringMapEntry<ValueTy> value_type; 453 454 StringMapConstIterator() = default; 455 456 explicit StringMapConstIterator(StringMapEntryBase **Bucket, 457 bool NoAdvance = false) Ptr(Bucket)458 : Ptr(Bucket) { 459 if (!NoAdvance) AdvancePastEmptyBuckets(); 460 } 461 462 const value_type &operator*() const { 463 return *static_cast<StringMapEntry<ValueTy>*>(*Ptr); 464 } 465 const value_type *operator->() const { 466 return static_cast<StringMapEntry<ValueTy>*>(*Ptr); 467 } 468 469 bool operator==(const StringMapConstIterator &RHS) const { 470 return Ptr == RHS.Ptr; 471 } 472 bool operator!=(const StringMapConstIterator &RHS) const { 473 return Ptr != RHS.Ptr; 474 } 475 476 inline StringMapConstIterator& operator++() { // Preincrement 477 ++Ptr; 478 AdvancePastEmptyBuckets(); 479 return *this; 480 } 481 StringMapConstIterator operator++(int) { // Postincrement 482 StringMapConstIterator tmp = *this; ++*this; return tmp; 483 } 484 485 private: AdvancePastEmptyBuckets()486 void AdvancePastEmptyBuckets() { 487 while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) 488 ++Ptr; 489 } 490 }; 491 492 template<typename ValueTy> 493 class StringMapIterator : public StringMapConstIterator<ValueTy> { 494 public: 495 StringMapIterator() = default; 496 497 explicit StringMapIterator(StringMapEntryBase **Bucket, 498 bool NoAdvance = false) 499 : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) { 500 } 501 502 StringMapEntry<ValueTy> &operator*() const { 503 return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr); 504 } 505 StringMapEntry<ValueTy> *operator->() const { 506 return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr); 507 } 508 }; 509 510 } // end namespace llvm 511 512 #endif // LLVM_ADT_STRINGMAP_H 513