sanitizer_dense_map.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. //===- sanitizer_dense_map.h - Dense probed hash table ----------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This is fork of llvm/ADT/DenseMap.h class with the following changes:
  10. // * Use mmap to allocate.
  11. // * No iterators.
  12. // * Does not shrink.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #ifndef SANITIZER_DENSE_MAP_H
  16. #define SANITIZER_DENSE_MAP_H
  17. #include "sanitizer_common.h"
  18. #include "sanitizer_dense_map_info.h"
  19. #include "sanitizer_internal_defs.h"
  20. #include "sanitizer_type_traits.h"
  21. namespace __sanitizer {
  22. template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
  23. typename BucketT>
  24. class DenseMapBase {
  25. public:
  26. using size_type = unsigned;
  27. using key_type = KeyT;
  28. using mapped_type = ValueT;
  29. using value_type = BucketT;
  30. WARN_UNUSED_RESULT bool empty() const { return getNumEntries() == 0; }
  31. unsigned size() const { return getNumEntries(); }
  32. /// Grow the densemap so that it can contain at least \p NumEntries items
  33. /// before resizing again.
  34. void reserve(size_type NumEntries) {
  35. auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
  36. if (NumBuckets > getNumBuckets())
  37. grow(NumBuckets);
  38. }
  39. void clear() {
  40. if (getNumEntries() == 0 && getNumTombstones() == 0)
  41. return;
  42. const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
  43. if (__sanitizer::is_trivially_destructible<ValueT>::value) {
  44. // Use a simpler loop when values don't need destruction.
  45. for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P)
  46. P->getFirst() = EmptyKey;
  47. } else {
  48. unsigned NumEntries = getNumEntries();
  49. for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
  50. if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) {
  51. if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
  52. P->getSecond().~ValueT();
  53. --NumEntries;
  54. }
  55. P->getFirst() = EmptyKey;
  56. }
  57. }
  58. CHECK_EQ(NumEntries, 0);
  59. }
  60. setNumEntries(0);
  61. setNumTombstones(0);
  62. }
  63. /// Return 1 if the specified key is in the map, 0 otherwise.
  64. size_type count(const KeyT &Key) const {
  65. const BucketT *TheBucket;
  66. return LookupBucketFor(Key, TheBucket) ? 1 : 0;
  67. }
  68. value_type *find(const KeyT &Key) {
  69. BucketT *TheBucket;
  70. if (LookupBucketFor(Key, TheBucket))
  71. return TheBucket;
  72. return nullptr;
  73. }
  74. const value_type *find(const KeyT &Key) const {
  75. const BucketT *TheBucket;
  76. if (LookupBucketFor(Key, TheBucket))
  77. return TheBucket;
  78. return nullptr;
  79. }
  80. /// Alternate version of find() which allows a different, and possibly
  81. /// less expensive, key type.
  82. /// The DenseMapInfo is responsible for supplying methods
  83. /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
  84. /// type used.
  85. template <class LookupKeyT>
  86. value_type *find_as(const LookupKeyT &Key) {
  87. BucketT *TheBucket;
  88. if (LookupBucketFor(Key, TheBucket))
  89. return TheBucket;
  90. return nullptr;
  91. }
  92. template <class LookupKeyT>
  93. const value_type *find_as(const LookupKeyT &Key) const {
  94. const BucketT *TheBucket;
  95. if (LookupBucketFor(Key, TheBucket))
  96. return TheBucket;
  97. return nullptr;
  98. }
  99. /// lookup - Return the entry for the specified key, or a default
  100. /// constructed value if no such entry exists.
  101. ValueT lookup(const KeyT &Key) const {
  102. const BucketT *TheBucket;
  103. if (LookupBucketFor(Key, TheBucket))
  104. return TheBucket->getSecond();
  105. return ValueT();
  106. }
  107. // Inserts key,value pair into the map if the key isn't already in the map.
  108. // If the key is already in the map, it returns false and doesn't update the
  109. // value.
  110. detail::DenseMapPair<value_type *, bool> insert(const value_type &KV) {
  111. return try_emplace(KV.first, KV.second);
  112. }
  113. // Inserts key,value pair into the map if the key isn't already in the map.
  114. // If the key is already in the map, it returns false and doesn't update the
  115. // value.
  116. detail::DenseMapPair<value_type *, bool> insert(value_type &&KV) {
  117. return try_emplace(__sanitizer::move(KV.first),
  118. __sanitizer::move(KV.second));
  119. }
  120. // Inserts key,value pair into the map if the key isn't already in the map.
  121. // The value is constructed in-place if the key is not in the map, otherwise
  122. // it is not moved.
  123. template <typename... Ts>
  124. detail::DenseMapPair<value_type *, bool> try_emplace(KeyT &&Key,
  125. Ts &&...Args) {
  126. BucketT *TheBucket;
  127. if (LookupBucketFor(Key, TheBucket))
  128. return {TheBucket, false}; // Already in map.
  129. // Otherwise, insert the new element.
  130. TheBucket = InsertIntoBucket(TheBucket, __sanitizer::move(Key),
  131. __sanitizer::forward<Ts>(Args)...);
  132. return {TheBucket, true};
  133. }
  134. // Inserts key,value pair into the map if the key isn't already in the map.
  135. // The value is constructed in-place if the key is not in the map, otherwise
  136. // it is not moved.
  137. template <typename... Ts>
  138. detail::DenseMapPair<value_type *, bool> try_emplace(const KeyT &Key,
  139. Ts &&...Args) {
  140. BucketT *TheBucket;
  141. if (LookupBucketFor(Key, TheBucket))
  142. return {TheBucket, false}; // Already in map.
  143. // Otherwise, insert the new element.
  144. TheBucket =
  145. InsertIntoBucket(TheBucket, Key, __sanitizer::forward<Ts>(Args)...);
  146. return {TheBucket, true};
  147. }
  148. /// Alternate version of insert() which allows a different, and possibly
  149. /// less expensive, key type.
  150. /// The DenseMapInfo is responsible for supplying methods
  151. /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
  152. /// type used.
  153. template <typename LookupKeyT>
  154. detail::DenseMapPair<value_type *, bool> insert_as(value_type &&KV,
  155. const LookupKeyT &Val) {
  156. BucketT *TheBucket;
  157. if (LookupBucketFor(Val, TheBucket))
  158. return {TheBucket, false}; // Already in map.
  159. // Otherwise, insert the new element.
  160. TheBucket =
  161. InsertIntoBucketWithLookup(TheBucket, __sanitizer::move(KV.first),
  162. __sanitizer::move(KV.second), Val);
  163. return {TheBucket, true};
  164. }
  165. bool erase(const KeyT &Val) {
  166. BucketT *TheBucket;
  167. if (!LookupBucketFor(Val, TheBucket))
  168. return false; // not in map.
  169. TheBucket->getSecond().~ValueT();
  170. TheBucket->getFirst() = getTombstoneKey();
  171. decrementNumEntries();
  172. incrementNumTombstones();
  173. return true;
  174. }
  175. void erase(value_type *I) {
  176. CHECK_NE(I, nullptr);
  177. BucketT *TheBucket = &*I;
  178. TheBucket->getSecond().~ValueT();
  179. TheBucket->getFirst() = getTombstoneKey();
  180. decrementNumEntries();
  181. incrementNumTombstones();
  182. }
  183. value_type &FindAndConstruct(const KeyT &Key) {
  184. BucketT *TheBucket;
  185. if (LookupBucketFor(Key, TheBucket))
  186. return *TheBucket;
  187. return *InsertIntoBucket(TheBucket, Key);
  188. }
  189. ValueT &operator[](const KeyT &Key) { return FindAndConstruct(Key).second; }
  190. value_type &FindAndConstruct(KeyT &&Key) {
  191. BucketT *TheBucket;
  192. if (LookupBucketFor(Key, TheBucket))
  193. return *TheBucket;
  194. return *InsertIntoBucket(TheBucket, __sanitizer::move(Key));
  195. }
  196. ValueT &operator[](KeyT &&Key) {
  197. return FindAndConstruct(__sanitizer::move(Key)).second;
  198. }
  199. /// Iterate over active entries of the container.
  200. ///
  201. /// Function can return fast to stop the process.
  202. template <class Fn>
  203. void forEach(Fn fn) {
  204. const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
  205. for (auto *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
  206. const KeyT K = P->getFirst();
  207. if (!KeyInfoT::isEqual(K, EmptyKey) &&
  208. !KeyInfoT::isEqual(K, TombstoneKey)) {
  209. if (!fn(*P))
  210. return;
  211. }
  212. }
  213. }
  214. template <class Fn>
  215. void forEach(Fn fn) const {
  216. const_cast<DenseMapBase *>(this)->forEach(
  217. [&](const value_type &KV) { return fn(KV); });
  218. }
  219. protected:
  220. DenseMapBase() = default;
  221. void destroyAll() {
  222. if (getNumBuckets() == 0) // Nothing to do.
  223. return;
  224. const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
  225. for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
  226. if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&
  227. !KeyInfoT::isEqual(P->getFirst(), TombstoneKey))
  228. P->getSecond().~ValueT();
  229. P->getFirst().~KeyT();
  230. }
  231. }
  232. void initEmpty() {
  233. setNumEntries(0);
  234. setNumTombstones(0);
  235. CHECK_EQ((getNumBuckets() & (getNumBuckets() - 1)), 0);
  236. const KeyT EmptyKey = getEmptyKey();
  237. for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B)
  238. ::new (&B->getFirst()) KeyT(EmptyKey);
  239. }
  240. /// Returns the number of buckets to allocate to ensure that the DenseMap can
  241. /// accommodate \p NumEntries without need to grow().
  242. unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
  243. // Ensure that "NumEntries * 4 < NumBuckets * 3"
  244. if (NumEntries == 0)
  245. return 0;
  246. // +1 is required because of the strict equality.
  247. // For example if NumEntries is 48, we need to return 401.
  248. return RoundUpToPowerOfTwo((NumEntries * 4 / 3 + 1) + /* NextPowerOf2 */ 1);
  249. }
  250. void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) {
  251. initEmpty();
  252. // Insert all the old elements.
  253. const KeyT EmptyKey = getEmptyKey();
  254. const KeyT TombstoneKey = getTombstoneKey();
  255. for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) {
  256. if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) &&
  257. !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) {
  258. // Insert the key/value into the new table.
  259. BucketT *DestBucket;
  260. bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket);
  261. (void)FoundVal; // silence warning.
  262. CHECK(!FoundVal);
  263. DestBucket->getFirst() = __sanitizer::move(B->getFirst());
  264. ::new (&DestBucket->getSecond())
  265. ValueT(__sanitizer::move(B->getSecond()));
  266. incrementNumEntries();
  267. // Free the value.
  268. B->getSecond().~ValueT();
  269. }
  270. B->getFirst().~KeyT();
  271. }
  272. }
  273. template <typename OtherBaseT>
  274. void copyFrom(
  275. const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) {
  276. CHECK_NE(&other, this);
  277. CHECK_EQ(getNumBuckets(), other.getNumBuckets());
  278. setNumEntries(other.getNumEntries());
  279. setNumTombstones(other.getNumTombstones());
  280. if (__sanitizer::is_trivially_copyable<KeyT>::value &&
  281. __sanitizer::is_trivially_copyable<ValueT>::value)
  282. internal_memcpy(reinterpret_cast<void *>(getBuckets()),
  283. other.getBuckets(), getNumBuckets() * sizeof(BucketT));
  284. else
  285. for (uptr i = 0; i < getNumBuckets(); ++i) {
  286. ::new (&getBuckets()[i].getFirst())
  287. KeyT(other.getBuckets()[i].getFirst());
  288. if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) &&
  289. !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey()))
  290. ::new (&getBuckets()[i].getSecond())
  291. ValueT(other.getBuckets()[i].getSecond());
  292. }
  293. }
  294. static unsigned getHashValue(const KeyT &Val) {
  295. return KeyInfoT::getHashValue(Val);
  296. }
  297. template <typename LookupKeyT>
  298. static unsigned getHashValue(const LookupKeyT &Val) {
  299. return KeyInfoT::getHashValue(Val);
  300. }
  301. static const KeyT getEmptyKey() { return KeyInfoT::getEmptyKey(); }
  302. static const KeyT getTombstoneKey() { return KeyInfoT::getTombstoneKey(); }
  303. private:
  304. unsigned getNumEntries() const {
  305. return static_cast<const DerivedT *>(this)->getNumEntries();
  306. }
  307. void setNumEntries(unsigned Num) {
  308. static_cast<DerivedT *>(this)->setNumEntries(Num);
  309. }
  310. void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
  311. void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
  312. unsigned getNumTombstones() const {
  313. return static_cast<const DerivedT *>(this)->getNumTombstones();
  314. }
  315. void setNumTombstones(unsigned Num) {
  316. static_cast<DerivedT *>(this)->setNumTombstones(Num);
  317. }
  318. void incrementNumTombstones() { setNumTombstones(getNumTombstones() + 1); }
  319. void decrementNumTombstones() { setNumTombstones(getNumTombstones() - 1); }
  320. const BucketT *getBuckets() const {
  321. return static_cast<const DerivedT *>(this)->getBuckets();
  322. }
  323. BucketT *getBuckets() { return static_cast<DerivedT *>(this)->getBuckets(); }
  324. unsigned getNumBuckets() const {
  325. return static_cast<const DerivedT *>(this)->getNumBuckets();
  326. }
  327. BucketT *getBucketsEnd() { return getBuckets() + getNumBuckets(); }
  328. const BucketT *getBucketsEnd() const {
  329. return getBuckets() + getNumBuckets();
  330. }
  331. void grow(unsigned AtLeast) { static_cast<DerivedT *>(this)->grow(AtLeast); }
  332. template <typename KeyArg, typename... ValueArgs>
  333. BucketT *InsertIntoBucket(BucketT *TheBucket, KeyArg &&Key,
  334. ValueArgs &&...Values) {
  335. TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
  336. TheBucket->getFirst() = __sanitizer::forward<KeyArg>(Key);
  337. ::new (&TheBucket->getSecond())
  338. ValueT(__sanitizer::forward<ValueArgs>(Values)...);
  339. return TheBucket;
  340. }
  341. template <typename LookupKeyT>
  342. BucketT *InsertIntoBucketWithLookup(BucketT *TheBucket, KeyT &&Key,
  343. ValueT &&Value, LookupKeyT &Lookup) {
  344. TheBucket = InsertIntoBucketImpl(Key, Lookup, TheBucket);
  345. TheBucket->getFirst() = __sanitizer::move(Key);
  346. ::new (&TheBucket->getSecond()) ValueT(__sanitizer::move(Value));
  347. return TheBucket;
  348. }
  349. template <typename LookupKeyT>
  350. BucketT *InsertIntoBucketImpl(const KeyT &Key, const LookupKeyT &Lookup,
  351. BucketT *TheBucket) {
  352. // If the load of the hash table is more than 3/4, or if fewer than 1/8 of
  353. // the buckets are empty (meaning that many are filled with tombstones),
  354. // grow the table.
  355. //
  356. // The later case is tricky. For example, if we had one empty bucket with
  357. // tons of tombstones, failing lookups (e.g. for insertion) would have to
  358. // probe almost the entire table until it found the empty bucket. If the
  359. // table completely filled with tombstones, no lookup would ever succeed,
  360. // causing infinite loops in lookup.
  361. unsigned NewNumEntries = getNumEntries() + 1;
  362. unsigned NumBuckets = getNumBuckets();
  363. if (UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
  364. this->grow(NumBuckets * 2);
  365. LookupBucketFor(Lookup, TheBucket);
  366. NumBuckets = getNumBuckets();
  367. } else if (UNLIKELY(NumBuckets - (NewNumEntries + getNumTombstones()) <=
  368. NumBuckets / 8)) {
  369. this->grow(NumBuckets);
  370. LookupBucketFor(Lookup, TheBucket);
  371. }
  372. CHECK(TheBucket);
  373. // Only update the state after we've grown our bucket space appropriately
  374. // so that when growing buckets we have self-consistent entry count.
  375. incrementNumEntries();
  376. // If we are writing over a tombstone, remember this.
  377. const KeyT EmptyKey = getEmptyKey();
  378. if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey))
  379. decrementNumTombstones();
  380. return TheBucket;
  381. }
  382. /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in
  383. /// FoundBucket. If the bucket contains the key and a value, this returns
  384. /// true, otherwise it returns a bucket with an empty marker or tombstone and
  385. /// returns false.
  386. template <typename LookupKeyT>
  387. bool LookupBucketFor(const LookupKeyT &Val,
  388. const BucketT *&FoundBucket) const {
  389. const BucketT *BucketsPtr = getBuckets();
  390. const unsigned NumBuckets = getNumBuckets();
  391. if (NumBuckets == 0) {
  392. FoundBucket = nullptr;
  393. return false;
  394. }
  395. // FoundTombstone - Keep track of whether we find a tombstone while probing.
  396. const BucketT *FoundTombstone = nullptr;
  397. const KeyT EmptyKey = getEmptyKey();
  398. const KeyT TombstoneKey = getTombstoneKey();
  399. CHECK(!KeyInfoT::isEqual(Val, EmptyKey));
  400. CHECK(!KeyInfoT::isEqual(Val, TombstoneKey));
  401. unsigned BucketNo = getHashValue(Val) & (NumBuckets - 1);
  402. unsigned ProbeAmt = 1;
  403. while (true) {
  404. const BucketT *ThisBucket = BucketsPtr + BucketNo;
  405. // Found Val's bucket? If so, return it.
  406. if (LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
  407. FoundBucket = ThisBucket;
  408. return true;
  409. }
  410. // If we found an empty bucket, the key doesn't exist in the set.
  411. // Insert it and return the default value.
  412. if (LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) {
  413. // If we've already seen a tombstone while probing, fill it in instead
  414. // of the empty bucket we eventually probed to.
  415. FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
  416. return false;
  417. }
  418. // If this is a tombstone, remember it. If Val ends up not in the map, we
  419. // prefer to return it than something that would require more probing.
  420. if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) &&
  421. !FoundTombstone)
  422. FoundTombstone = ThisBucket; // Remember the first tombstone found.
  423. // Otherwise, it's a hash collision or a tombstone, continue quadratic
  424. // probing.
  425. BucketNo += ProbeAmt++;
  426. BucketNo &= (NumBuckets - 1);
  427. }
  428. }
  429. template <typename LookupKeyT>
  430. bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) {
  431. const BucketT *ConstFoundBucket;
  432. bool Result = const_cast<const DenseMapBase *>(this)->LookupBucketFor(
  433. Val, ConstFoundBucket);
  434. FoundBucket = const_cast<BucketT *>(ConstFoundBucket);
  435. return Result;
  436. }
  437. public:
  438. /// Return the approximate size (in bytes) of the actual map.
  439. /// This is just the raw memory used by DenseMap.
  440. /// If entries are pointers to objects, the size of the referenced objects
  441. /// are not included.
  442. uptr getMemorySize() const {
  443. return RoundUpTo(getNumBuckets() * sizeof(BucketT), GetPageSizeCached());
  444. }
  445. };
  446. /// Equality comparison for DenseMap.
  447. ///
  448. /// Iterates over elements of LHS confirming that each (key, value) pair in LHS
  449. /// is also in RHS, and that no additional pairs are in RHS.
  450. /// Equivalent to N calls to RHS.find and N value comparisons. Amortized
  451. /// complexity is linear, worst case is O(N^2) (if every hash collides).
  452. template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
  453. typename BucketT>
  454. bool operator==(
  455. const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
  456. const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
  457. if (LHS.size() != RHS.size())
  458. return false;
  459. bool R = true;
  460. LHS.forEach(
  461. [&](const typename DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT,
  462. BucketT>::value_type &KV) -> bool {
  463. const auto *I = RHS.find(KV.first);
  464. if (!I || I->second != KV.second) {
  465. R = false;
  466. return false;
  467. }
  468. return true;
  469. });
  470. return R;
  471. }
  472. /// Inequality comparison for DenseMap.
  473. ///
  474. /// Equivalent to !(LHS == RHS). See operator== for performance notes.
  475. template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
  476. typename BucketT>
  477. bool operator!=(
  478. const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
  479. const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
  480. return !(LHS == RHS);
  481. }
  482. template <typename KeyT, typename ValueT,
  483. typename KeyInfoT = DenseMapInfo<KeyT>,
  484. typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
  485. class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
  486. KeyT, ValueT, KeyInfoT, BucketT> {
  487. friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
  488. // Lift some types from the dependent base class into this class for
  489. // simplicity of referring to them.
  490. using BaseT = DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
  491. BucketT *Buckets = nullptr;
  492. unsigned NumEntries = 0;
  493. unsigned NumTombstones = 0;
  494. unsigned NumBuckets = 0;
  495. public:
  496. /// Create a DenseMap with an optional \p InitialReserve that guarantee that
  497. /// this number of elements can be inserted in the map without grow()
  498. explicit DenseMap(unsigned InitialReserve) { init(InitialReserve); }
  499. constexpr DenseMap() = default;
  500. DenseMap(const DenseMap &other) : BaseT() {
  501. init(0);
  502. copyFrom(other);
  503. }
  504. DenseMap(DenseMap &&other) : BaseT() {
  505. init(0);
  506. swap(other);
  507. }
  508. ~DenseMap() {
  509. this->destroyAll();
  510. deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets);
  511. }
  512. void swap(DenseMap &RHS) {
  513. Swap(Buckets, RHS.Buckets);
  514. Swap(NumEntries, RHS.NumEntries);
  515. Swap(NumTombstones, RHS.NumTombstones);
  516. Swap(NumBuckets, RHS.NumBuckets);
  517. }
  518. DenseMap &operator=(const DenseMap &other) {
  519. if (&other != this)
  520. copyFrom(other);
  521. return *this;
  522. }
  523. DenseMap &operator=(DenseMap &&other) {
  524. this->destroyAll();
  525. deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT));
  526. init(0);
  527. swap(other);
  528. return *this;
  529. }
  530. void copyFrom(const DenseMap &other) {
  531. this->destroyAll();
  532. deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets);
  533. if (allocateBuckets(other.NumBuckets)) {
  534. this->BaseT::copyFrom(other);
  535. } else {
  536. NumEntries = 0;
  537. NumTombstones = 0;
  538. }
  539. }
  540. void init(unsigned InitNumEntries) {
  541. auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
  542. if (allocateBuckets(InitBuckets)) {
  543. this->BaseT::initEmpty();
  544. } else {
  545. NumEntries = 0;
  546. NumTombstones = 0;
  547. }
  548. }
  549. void grow(unsigned AtLeast) {
  550. unsigned OldNumBuckets = NumBuckets;
  551. BucketT *OldBuckets = Buckets;
  552. allocateBuckets(RoundUpToPowerOfTwo(Max<unsigned>(64, AtLeast)));
  553. CHECK(Buckets);
  554. if (!OldBuckets) {
  555. this->BaseT::initEmpty();
  556. return;
  557. }
  558. this->moveFromOldBuckets(OldBuckets, OldBuckets + OldNumBuckets);
  559. // Free the old table.
  560. deallocate_buffer(OldBuckets, sizeof(BucketT) * OldNumBuckets);
  561. }
  562. private:
  563. unsigned getNumEntries() const { return NumEntries; }
  564. void setNumEntries(unsigned Num) { NumEntries = Num; }
  565. unsigned getNumTombstones() const { return NumTombstones; }
  566. void setNumTombstones(unsigned Num) { NumTombstones = Num; }
  567. BucketT *getBuckets() const { return Buckets; }
  568. unsigned getNumBuckets() const { return NumBuckets; }
  569. bool allocateBuckets(unsigned Num) {
  570. NumBuckets = Num;
  571. if (NumBuckets == 0) {
  572. Buckets = nullptr;
  573. return false;
  574. }
  575. uptr Size = sizeof(BucketT) * NumBuckets;
  576. if (Size * 2 <= GetPageSizeCached()) {
  577. // We always allocate at least a page, so use entire space.
  578. unsigned Log2 = MostSignificantSetBitIndex(GetPageSizeCached() / Size);
  579. Size <<= Log2;
  580. NumBuckets <<= Log2;
  581. CHECK_EQ(Size, sizeof(BucketT) * NumBuckets);
  582. CHECK_GT(Size * 2, GetPageSizeCached());
  583. }
  584. Buckets = static_cast<BucketT *>(allocate_buffer(Size));
  585. return true;
  586. }
  587. static void *allocate_buffer(uptr Size) {
  588. return MmapOrDie(RoundUpTo(Size, GetPageSizeCached()), "DenseMap");
  589. }
  590. static void deallocate_buffer(void *Ptr, uptr Size) {
  591. UnmapOrDie(Ptr, RoundUpTo(Size, GetPageSizeCached()));
  592. }
  593. };
  594. } // namespace __sanitizer
  595. #endif // SANITIZER_DENSE_MAP_H