//
// The LLVM Compiler Infrastructure
//
-// This file was developed by Chris Lattner and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
static inline T* getEmptyKey() { return reinterpret_cast<T*>(-1); }
static inline T* getTombstoneKey() { return reinterpret_cast<T*>(-2); }
static unsigned getHashValue(const T *PtrVal) {
- return (unsigned(uintptr_t(PtrVal)) >> 4) ^
- (unsigned(uintptr_t(PtrVal)) >> 9);
+ return (unsigned((uintptr_t)PtrVal) >> 4) ^
+ (unsigned((uintptr_t)PtrVal) >> 9);
}
static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
static bool isPod() { return true; }
unsigned NumEntries;
unsigned NumTombstones;
public:
+ typedef BucketT value_type;
+
DenseMap(const DenseMap& other) {
NumBuckets = 0;
CopyFrom(other);
~DenseMap() {
const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) {
- if (P->first != EmptyKey && P->first != TombstoneKey)
+ if (!KeyInfoT::isEqual(P->first, EmptyKey) &&
+ !KeyInfoT::isEqual(P->first, TombstoneKey))
P->second.~ValueT();
P->first.~KeyT();
}
bool empty() const { return NumEntries == 0; }
unsigned size() const { return NumEntries; }
+
+ /// Grow the densemap so that it has at least Size buckets. Does not shrink
+ void resize(size_t Size) { grow(Size); }
void clear() {
// If the capacity of the array is huge, and the # elements used is small,
const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) {
- if (P->first != EmptyKey) {
- if (P->first != TombstoneKey) {
+ if (!KeyInfoT::isEqual(P->first, EmptyKey)) {
+ if (!KeyInfoT::isEqual(P->first, TombstoneKey)) {
P->second.~ValueT();
--NumEntries;
}
++NumTombstones;
return true;
}
-
- ValueT &operator[](const KeyT &Key) {
+
+ value_type& FindAndConstruct(const KeyT &Key) {
BucketT *TheBucket;
if (LookupBucketFor(Key, TheBucket))
- return TheBucket->second;
-
- return InsertIntoBucket(Key, ValueT(), TheBucket)->second;
+ return *TheBucket;
+
+ return *InsertIntoBucket(Key, ValueT(), TheBucket);
+ }
+
+ ValueT &operator[](const KeyT &Key) {
+ return FindAndConstruct(Key).second;
}
DenseMap& operator=(const DenseMap& other) {
if (NumBuckets != 0 && (!KeyInfoT::isPod() || !ValueInfoT::isPod())) {
const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) {
- if (P->first != EmptyKey && P->first != TombstoneKey)
+ if (!KeyInfoT::isEqual(P->first, EmptyKey) &&
+ !KeyInfoT::isEqual(P->first, TombstoneKey))
P->second.~ValueT();
P->first.~KeyT();
}
else
for (size_t i = 0; i < other.NumBuckets; ++i) {
new (Buckets[i].first) KeyT(other.Buckets[i].first);
- if (Buckets[i].first != getEmptyKey() &&
- Buckets[i].first != getTombstoneKey())
+ if (!KeyInfoT::isEqual(Buckets[i].first, getEmptyKey()) &&
+ !KeyInfoT::isEqual(Buckets[i].first, getTombstoneKey()))
new (&Buckets[i].second) ValueT(other.Buckets[i].second);
}
NumBuckets = other.NumBuckets;
// causing infinite loops in lookup.
if (NumEntries*4 >= NumBuckets*3 ||
NumBuckets-(NumEntries+NumTombstones) < NumBuckets/8) {
- this->grow();
+ this->grow(NumBuckets * 2);
LookupBucketFor(Key, TheBucket);
}
++NumEntries;
// If we are writing over a tombstone, remember this.
- if (TheBucket->first != getEmptyKey())
+ if (!KeyInfoT::isEqual(TheBucket->first, getEmptyKey()))
--NumTombstones;
TheBucket->first = Key;
BucketT *FoundTombstone = 0;
const KeyT EmptyKey = getEmptyKey();
const KeyT TombstoneKey = getTombstoneKey();
- assert(Val != EmptyKey && Val != TombstoneKey &&
+ assert(!KeyInfoT::isEqual(Val, EmptyKey) &&
+ !KeyInfoT::isEqual(Val, TombstoneKey) &&
"Empty/Tombstone value shouldn't be inserted into map!");
while (1) {
new (&Buckets[i].first) KeyT(EmptyKey);
}
- void grow() {
+ void grow(unsigned AtLeast) {
unsigned OldNumBuckets = NumBuckets;
BucketT *OldBuckets = Buckets;
// Double the number of buckets.
- NumBuckets <<= 1;
+ while (NumBuckets <= AtLeast)
+ NumBuckets <<= 1;
NumTombstones = 0;
Buckets = reinterpret_cast<BucketT*>(new char[sizeof(BucketT)*NumBuckets]);
// Insert all the old elements.
const KeyT TombstoneKey = getTombstoneKey();
for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) {
- if (B->first != EmptyKey && B->first != TombstoneKey) {
+ if (!KeyInfoT::isEqual(B->first, EmptyKey) &&
+ !KeyInfoT::isEqual(B->first, TombstoneKey)) {
// Insert the key/value into the new table.
BucketT *DestBucket;
bool FoundVal = LookupBucketFor(B->first, DestBucket);
// Free the old buckets.
const KeyT TombstoneKey = getTombstoneKey();
for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) {
- if (B->first != EmptyKey && B->first != TombstoneKey) {
+ if (!KeyInfoT::isEqual(B->first, EmptyKey) &&
+ !KeyInfoT::isEqual(B->first, TombstoneKey)) {
// Free the value.
B->second.~ValueT();
}