llvm.org GIT mirror llvm / 04a3115
Fix a really subtle bug where the entire hash table could fill with tombstones, causing subsequent insertions to infinitely loop. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33972 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 13 years ago
1 changed file(s) with 23 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
2727 //static bool isPod()
2828 };
2929
30 // Provide DenseMapKeyInfo for all pointers.
3031 template
3132 struct DenseMapKeyInfo {
3233 static inline T* getEmptyKey() { return (T*)-1; }
5051 BucketT *Buckets;
5152
5253 unsigned NumEntries;
54 unsigned NumTombstones;
5355 DenseMap(const DenseMap &); // not implemented.
5456 public:
5557 explicit DenseMap(unsigned NumInitBuckets = 64) {
9597 }
9698 }
9799 assert(NumEntries == 0 && "Node count imbalance!");
100 NumTombstones = 0;
98101 }
99102
100103 /// count - Return true if the specified key is in the map.
128131 TheBucket->second.~ValueT();
129132 TheBucket->first = getTombstoneKey();
130133 --NumEntries;
134 ++NumTombstones;
131135 return true;
132136 }
133137 bool erase(iterator I) {
135139 TheBucket->second.~ValueT();
136140 TheBucket->first = getTombstoneKey();
137141 --NumEntries;
142 ++NumTombstones;
138143 return true;
139144 }
140145
149154 private:
150155 BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value,
151156 BucketT *TheBucket) {
152 // If the load of the hash table is more than 3/4, grow it.
153 if (NumEntries*4 >= NumBuckets*3) {
157 // If the load of the hash table is more than 3/4, or if fewer than 1/8 of
158 // the buckets are empty (meaning that many are filled with tombstones),
159 // grow the table.
160 //
161 // The later case is tricky. For example, if we had one empty bucket with
162 // tons of tombstones, failing lookups (e.g. for insertion) would have to
163 // probe almost the entire table until it found the empty bucket. If the
164 // table completely filled with tombstones, no lookup would ever succeed,
165 // causing infinite loops in lookup.
166 if (NumEntries*4 >= NumBuckets*3 ||
167 NumBuckets-(NumEntries+NumTombstones) < NumBuckets/8) {
154168 this->grow();
155169 LookupBucketFor(Key, TheBucket);
156170 }
157171 ++NumEntries;
172
173 // If we are writing over a tombstone, remember this.
174 if (TheBucket->first != getEmptyKey())
175 --NumTombstones;
176
158177 TheBucket->first = Key;
159178 new (&TheBucket->second) ValueT(Value);
160179 return TheBucket;
217236
218237 void init(unsigned InitBuckets) {
219238 NumEntries = 0;
239 NumTombstones = 0;
220240 NumBuckets = InitBuckets;
221241 assert(InitBuckets && (InitBuckets & InitBuckets-1) == 0 &&
222242 "# initial buckets must be a power of two!");
233253
234254 // Double the number of buckets.
235255 NumBuckets <<= 1;
256 NumTombstones = 0;
236257 Buckets = (BucketT*)new char[sizeof(BucketT)*NumBuckets];
237258
238259 // Initialize all the keys to EmptyKey.