#ifndef LLVM_ADT_DENSEMAP_H
#define LLVM_ADT_DENSEMAP_H
-#include "llvm/Support/Compiler.h"
+#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include "llvm/Support/type_traits.h"
-#include "llvm/ADT/DenseMapInfo.h"
#include <algorithm>
-#include <iterator>
-#include <new>
-#include <utility>
#include <cassert>
#include <climits>
#include <cstddef>
#include <cstring>
+#include <iterator>
+#include <new>
+#include <utility>
namespace llvm {
void clear() {
if (getNumEntries() == 0 && getNumTombstones() == 0) return;
-
+
// If the capacity of the array is huge, and the # elements used is small,
// shrink the array.
if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true);
}
+#if LLVM_HAS_RVALUE_REFERENCES
+ // Inserts key,value pair into the map if the key isn't already in the map.
+ // If the key is already in the map, it returns false and doesn't update the
+ // value.
+ std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(KV.first, TheBucket))
+ return std::make_pair(iterator(TheBucket, getBucketsEnd(), true),
+ false); // Already in map.
+
+ // Otherwise, insert the new element.
+ TheBucket = InsertIntoBucket(std::move(KV.first),
+ std::move(KV.second),
+ TheBucket);
+ return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true);
+ }
+#endif
+
/// insert - Range insertion of pairs.
template<typename InputIt>
void insert(InputIt I, InputIt E) {
return FindAndConstruct(Key).second;
}
-#if LLVM_USE_RVALUE_REFERENCES
+#if LLVM_HAS_RVALUE_REFERENCES
value_type& FindAndConstruct(KeyT &&Key) {
BucketT *TheBucket;
if (LookupBucketFor(Key, TheBucket))
return *TheBucket;
- return *InsertIntoBucket(Key, ValueT(), TheBucket);
+ return *InsertIntoBucket(std::move(Key), ValueT(), TheBucket);
}
ValueT &operator[](KeyT &&Key) {
- return FindAndConstruct(Key).second;
+ return FindAndConstruct(std::move(Key)).second;
}
#endif
return TheBucket;
}
-#if LLVM_USE_RVALUE_REFERENCES
+#if LLVM_HAS_RVALUE_REFERENCES
BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value,
BucketT *TheBucket) {
TheBucket = InsertIntoBucketImpl(Key, TheBucket);
NumBuckets = getNumBuckets();
}
if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) {
- this->grow(NumBuckets);
+ this->grow(NumBuckets * 2);
LookupBucketFor(Key, TheBucket);
}
+ assert(TheBucket);
// Only update the state after we've grown our bucket space appropriately
// so that when growing buckets we have self-consistent entry count.
incrementNumEntries();
// If we are writing over a tombstone, remember this.
- if (!KeyInfoT::isEqual(TheBucket->first, getEmptyKey()))
+ const KeyT EmptyKey = getEmptyKey();
+ if (!KeyInfoT::isEqual(TheBucket->first, EmptyKey))
decrementNumTombstones();
return TheBucket;
if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) {
// If we've already seen a tombstone while probing, fill it in instead
// of the empty bucket we eventually probed to.
- if (FoundTombstone) ThisBucket = FoundTombstone;
FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
return false;
}
init(NumInitBuckets);
}
- DenseMap(const DenseMap &other) {
+ DenseMap(const DenseMap &other) : BaseT() {
init(0);
copyFrom(other);
}
-#if LLVM_USE_RVALUE_REFERENCES
- DenseMap(DenseMap &&other) {
+#if LLVM_HAS_RVALUE_REFERENCES
+ DenseMap(DenseMap &&other) : BaseT() {
init(0);
swap(other);
}
return *this;
}
-#if LLVM_USE_RVALUE_REFERENCES
+#if LLVM_HAS_RVALUE_REFERENCES
DenseMap& operator=(DenseMap &&other) {
this->destroyAll();
operator delete(Buckets);
}
void init(unsigned InitBuckets) {
+ assert(!KeyInfoT::isEqual(this->getEmptyKey(), this->getTombstoneKey()) &&
+ "Bad implementation of KeyInfoT: empty key and tombstone key "
+ "should be different");
if (allocateBuckets(InitBuckets)) {
this->BaseT::initEmpty();
} else {
unsigned OldNumBuckets = NumBuckets;
BucketT *OldBuckets = Buckets;
- allocateBuckets(std::max<unsigned>(64, NextPowerOf2(AtLeast)));
+ allocateBuckets(std::max<unsigned>(64, static_cast<unsigned>(NextPowerOf2(AtLeast-1))));
assert(Buckets);
if (!OldBuckets) {
this->BaseT::initEmpty();
copyFrom(other);
}
-#if LLVM_USE_RVALUE_REFERENCES
+#if LLVM_HAS_RVALUE_REFERENCES
SmallDenseMap(SmallDenseMap &&other) {
init(0);
swap(other);
return *this;
}
-#if LLVM_USE_RVALUE_REFERENCES
+#if LLVM_HAS_RVALUE_REFERENCES
SmallDenseMap& operator=(SmallDenseMap &&other) {
this->destroyAll();
deallocateBuckets();
}
void grow(unsigned AtLeast) {
- if (AtLeast > InlineBuckets)
- AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast));
+ if (AtLeast >= InlineBuckets)
+ AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast-1));
if (Small) {
- if (AtLeast <= InlineBuckets)
+ if (AtLeast < InlineBuckets)
return; // Nothing to do.
// First move the inline buckets into a temporary storage.
++Ptr;
}
};
-
+
template<typename KeyT, typename ValueT, typename KeyInfoT>
static inline size_t
capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT> &X) {