1*9880d681SAndroid Build Coastguard Worker //===--- StringMap.cpp - String Hash table map implementation -------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the StringMap class.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringMap.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Compiler.h"
17*9880d681SAndroid Build Coastguard Worker #include <cassert>
18*9880d681SAndroid Build Coastguard Worker using namespace llvm;
19*9880d681SAndroid Build Coastguard Worker
20*9880d681SAndroid Build Coastguard Worker /// Returns the number of buckets to allocate to ensure that the DenseMap can
21*9880d681SAndroid Build Coastguard Worker /// accommodate \p NumEntries without need to grow().
getMinBucketToReserveForEntries(unsigned NumEntries)22*9880d681SAndroid Build Coastguard Worker static unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
23*9880d681SAndroid Build Coastguard Worker // Ensure that "NumEntries * 4 < NumBuckets * 3"
24*9880d681SAndroid Build Coastguard Worker if (NumEntries == 0)
25*9880d681SAndroid Build Coastguard Worker return 0;
26*9880d681SAndroid Build Coastguard Worker // +1 is required because of the strict equality.
27*9880d681SAndroid Build Coastguard Worker // For example if NumEntries is 48, we need to return 401.
28*9880d681SAndroid Build Coastguard Worker return NextPowerOf2(NumEntries * 4 / 3 + 1);
29*9880d681SAndroid Build Coastguard Worker }
30*9880d681SAndroid Build Coastguard Worker
StringMapImpl(unsigned InitSize,unsigned itemSize)31*9880d681SAndroid Build Coastguard Worker StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) {
32*9880d681SAndroid Build Coastguard Worker ItemSize = itemSize;
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker // If a size is specified, initialize the table with that many buckets.
35*9880d681SAndroid Build Coastguard Worker if (InitSize) {
36*9880d681SAndroid Build Coastguard Worker // The table will grow when the number of entries reach 3/4 of the number of
37*9880d681SAndroid Build Coastguard Worker // buckets. To guarantee that "InitSize" number of entries can be inserted
38*9880d681SAndroid Build Coastguard Worker // in the table without growing, we allocate just what is needed here.
39*9880d681SAndroid Build Coastguard Worker init(getMinBucketToReserveForEntries(InitSize));
40*9880d681SAndroid Build Coastguard Worker return;
41*9880d681SAndroid Build Coastguard Worker }
42*9880d681SAndroid Build Coastguard Worker
43*9880d681SAndroid Build Coastguard Worker // Otherwise, initialize it with zero buckets to avoid the allocation.
44*9880d681SAndroid Build Coastguard Worker TheTable = nullptr;
45*9880d681SAndroid Build Coastguard Worker NumBuckets = 0;
46*9880d681SAndroid Build Coastguard Worker NumItems = 0;
47*9880d681SAndroid Build Coastguard Worker NumTombstones = 0;
48*9880d681SAndroid Build Coastguard Worker }
49*9880d681SAndroid Build Coastguard Worker
init(unsigned InitSize)50*9880d681SAndroid Build Coastguard Worker void StringMapImpl::init(unsigned InitSize) {
51*9880d681SAndroid Build Coastguard Worker assert((InitSize & (InitSize-1)) == 0 &&
52*9880d681SAndroid Build Coastguard Worker "Init Size must be a power of 2 or zero!");
53*9880d681SAndroid Build Coastguard Worker NumBuckets = InitSize ? InitSize : 16;
54*9880d681SAndroid Build Coastguard Worker NumItems = 0;
55*9880d681SAndroid Build Coastguard Worker NumTombstones = 0;
56*9880d681SAndroid Build Coastguard Worker
57*9880d681SAndroid Build Coastguard Worker TheTable = (StringMapEntryBase **)calloc(NumBuckets+1,
58*9880d681SAndroid Build Coastguard Worker sizeof(StringMapEntryBase **) +
59*9880d681SAndroid Build Coastguard Worker sizeof(unsigned));
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker // Allocate one extra bucket, set it to look filled so the iterators stop at
62*9880d681SAndroid Build Coastguard Worker // end.
63*9880d681SAndroid Build Coastguard Worker TheTable[NumBuckets] = (StringMapEntryBase*)2;
64*9880d681SAndroid Build Coastguard Worker }
65*9880d681SAndroid Build Coastguard Worker
66*9880d681SAndroid Build Coastguard Worker
67*9880d681SAndroid Build Coastguard Worker /// LookupBucketFor - Look up the bucket that the specified string should end
68*9880d681SAndroid Build Coastguard Worker /// up in. If it already exists as a key in the map, the Item pointer for the
69*9880d681SAndroid Build Coastguard Worker /// specified bucket will be non-null. Otherwise, it will be null. In either
70*9880d681SAndroid Build Coastguard Worker /// case, the FullHashValue field of the bucket will be set to the hash value
71*9880d681SAndroid Build Coastguard Worker /// of the string.
LookupBucketFor(StringRef Name)72*9880d681SAndroid Build Coastguard Worker unsigned StringMapImpl::LookupBucketFor(StringRef Name) {
73*9880d681SAndroid Build Coastguard Worker unsigned HTSize = NumBuckets;
74*9880d681SAndroid Build Coastguard Worker if (HTSize == 0) { // Hash table unallocated so far?
75*9880d681SAndroid Build Coastguard Worker init(16);
76*9880d681SAndroid Build Coastguard Worker HTSize = NumBuckets;
77*9880d681SAndroid Build Coastguard Worker }
78*9880d681SAndroid Build Coastguard Worker unsigned FullHashValue = HashString(Name);
79*9880d681SAndroid Build Coastguard Worker unsigned BucketNo = FullHashValue & (HTSize-1);
80*9880d681SAndroid Build Coastguard Worker unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
81*9880d681SAndroid Build Coastguard Worker
82*9880d681SAndroid Build Coastguard Worker unsigned ProbeAmt = 1;
83*9880d681SAndroid Build Coastguard Worker int FirstTombstone = -1;
84*9880d681SAndroid Build Coastguard Worker while (1) {
85*9880d681SAndroid Build Coastguard Worker StringMapEntryBase *BucketItem = TheTable[BucketNo];
86*9880d681SAndroid Build Coastguard Worker // If we found an empty bucket, this key isn't in the table yet, return it.
87*9880d681SAndroid Build Coastguard Worker if (LLVM_LIKELY(!BucketItem)) {
88*9880d681SAndroid Build Coastguard Worker // If we found a tombstone, we want to reuse the tombstone instead of an
89*9880d681SAndroid Build Coastguard Worker // empty bucket. This reduces probing.
90*9880d681SAndroid Build Coastguard Worker if (FirstTombstone != -1) {
91*9880d681SAndroid Build Coastguard Worker HashTable[FirstTombstone] = FullHashValue;
92*9880d681SAndroid Build Coastguard Worker return FirstTombstone;
93*9880d681SAndroid Build Coastguard Worker }
94*9880d681SAndroid Build Coastguard Worker
95*9880d681SAndroid Build Coastguard Worker HashTable[BucketNo] = FullHashValue;
96*9880d681SAndroid Build Coastguard Worker return BucketNo;
97*9880d681SAndroid Build Coastguard Worker }
98*9880d681SAndroid Build Coastguard Worker
99*9880d681SAndroid Build Coastguard Worker if (BucketItem == getTombstoneVal()) {
100*9880d681SAndroid Build Coastguard Worker // Skip over tombstones. However, remember the first one we see.
101*9880d681SAndroid Build Coastguard Worker if (FirstTombstone == -1) FirstTombstone = BucketNo;
102*9880d681SAndroid Build Coastguard Worker } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) {
103*9880d681SAndroid Build Coastguard Worker // If the full hash value matches, check deeply for a match. The common
104*9880d681SAndroid Build Coastguard Worker // case here is that we are only looking at the buckets (for item info
105*9880d681SAndroid Build Coastguard Worker // being non-null and for the full hash value) not at the items. This
106*9880d681SAndroid Build Coastguard Worker // is important for cache locality.
107*9880d681SAndroid Build Coastguard Worker
108*9880d681SAndroid Build Coastguard Worker // Do the comparison like this because Name isn't necessarily
109*9880d681SAndroid Build Coastguard Worker // null-terminated!
110*9880d681SAndroid Build Coastguard Worker char *ItemStr = (char*)BucketItem+ItemSize;
111*9880d681SAndroid Build Coastguard Worker if (Name == StringRef(ItemStr, BucketItem->getKeyLength())) {
112*9880d681SAndroid Build Coastguard Worker // We found a match!
113*9880d681SAndroid Build Coastguard Worker return BucketNo;
114*9880d681SAndroid Build Coastguard Worker }
115*9880d681SAndroid Build Coastguard Worker }
116*9880d681SAndroid Build Coastguard Worker
117*9880d681SAndroid Build Coastguard Worker // Okay, we didn't find the item. Probe to the next bucket.
118*9880d681SAndroid Build Coastguard Worker BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker // Use quadratic probing, it has fewer clumping artifacts than linear
121*9880d681SAndroid Build Coastguard Worker // probing and has good cache behavior in the common case.
122*9880d681SAndroid Build Coastguard Worker ++ProbeAmt;
123*9880d681SAndroid Build Coastguard Worker }
124*9880d681SAndroid Build Coastguard Worker }
125*9880d681SAndroid Build Coastguard Worker
126*9880d681SAndroid Build Coastguard Worker
127*9880d681SAndroid Build Coastguard Worker /// FindKey - Look up the bucket that contains the specified key. If it exists
128*9880d681SAndroid Build Coastguard Worker /// in the map, return the bucket number of the key. Otherwise return -1.
129*9880d681SAndroid Build Coastguard Worker /// This does not modify the map.
FindKey(StringRef Key) const130*9880d681SAndroid Build Coastguard Worker int StringMapImpl::FindKey(StringRef Key) const {
131*9880d681SAndroid Build Coastguard Worker unsigned HTSize = NumBuckets;
132*9880d681SAndroid Build Coastguard Worker if (HTSize == 0) return -1; // Really empty table?
133*9880d681SAndroid Build Coastguard Worker unsigned FullHashValue = HashString(Key);
134*9880d681SAndroid Build Coastguard Worker unsigned BucketNo = FullHashValue & (HTSize-1);
135*9880d681SAndroid Build Coastguard Worker unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
136*9880d681SAndroid Build Coastguard Worker
137*9880d681SAndroid Build Coastguard Worker unsigned ProbeAmt = 1;
138*9880d681SAndroid Build Coastguard Worker while (1) {
139*9880d681SAndroid Build Coastguard Worker StringMapEntryBase *BucketItem = TheTable[BucketNo];
140*9880d681SAndroid Build Coastguard Worker // If we found an empty bucket, this key isn't in the table yet, return.
141*9880d681SAndroid Build Coastguard Worker if (LLVM_LIKELY(!BucketItem))
142*9880d681SAndroid Build Coastguard Worker return -1;
143*9880d681SAndroid Build Coastguard Worker
144*9880d681SAndroid Build Coastguard Worker if (BucketItem == getTombstoneVal()) {
145*9880d681SAndroid Build Coastguard Worker // Ignore tombstones.
146*9880d681SAndroid Build Coastguard Worker } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) {
147*9880d681SAndroid Build Coastguard Worker // If the full hash value matches, check deeply for a match. The common
148*9880d681SAndroid Build Coastguard Worker // case here is that we are only looking at the buckets (for item info
149*9880d681SAndroid Build Coastguard Worker // being non-null and for the full hash value) not at the items. This
150*9880d681SAndroid Build Coastguard Worker // is important for cache locality.
151*9880d681SAndroid Build Coastguard Worker
152*9880d681SAndroid Build Coastguard Worker // Do the comparison like this because NameStart isn't necessarily
153*9880d681SAndroid Build Coastguard Worker // null-terminated!
154*9880d681SAndroid Build Coastguard Worker char *ItemStr = (char*)BucketItem+ItemSize;
155*9880d681SAndroid Build Coastguard Worker if (Key == StringRef(ItemStr, BucketItem->getKeyLength())) {
156*9880d681SAndroid Build Coastguard Worker // We found a match!
157*9880d681SAndroid Build Coastguard Worker return BucketNo;
158*9880d681SAndroid Build Coastguard Worker }
159*9880d681SAndroid Build Coastguard Worker }
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Worker // Okay, we didn't find the item. Probe to the next bucket.
162*9880d681SAndroid Build Coastguard Worker BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Worker // Use quadratic probing, it has fewer clumping artifacts than linear
165*9880d681SAndroid Build Coastguard Worker // probing and has good cache behavior in the common case.
166*9880d681SAndroid Build Coastguard Worker ++ProbeAmt;
167*9880d681SAndroid Build Coastguard Worker }
168*9880d681SAndroid Build Coastguard Worker }
169*9880d681SAndroid Build Coastguard Worker
170*9880d681SAndroid Build Coastguard Worker /// RemoveKey - Remove the specified StringMapEntry from the table, but do not
171*9880d681SAndroid Build Coastguard Worker /// delete it. This aborts if the value isn't in the table.
RemoveKey(StringMapEntryBase * V)172*9880d681SAndroid Build Coastguard Worker void StringMapImpl::RemoveKey(StringMapEntryBase *V) {
173*9880d681SAndroid Build Coastguard Worker const char *VStr = (char*)V + ItemSize;
174*9880d681SAndroid Build Coastguard Worker StringMapEntryBase *V2 = RemoveKey(StringRef(VStr, V->getKeyLength()));
175*9880d681SAndroid Build Coastguard Worker (void)V2;
176*9880d681SAndroid Build Coastguard Worker assert(V == V2 && "Didn't find key?");
177*9880d681SAndroid Build Coastguard Worker }
178*9880d681SAndroid Build Coastguard Worker
179*9880d681SAndroid Build Coastguard Worker /// RemoveKey - Remove the StringMapEntry for the specified key from the
180*9880d681SAndroid Build Coastguard Worker /// table, returning it. If the key is not in the table, this returns null.
RemoveKey(StringRef Key)181*9880d681SAndroid Build Coastguard Worker StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) {
182*9880d681SAndroid Build Coastguard Worker int Bucket = FindKey(Key);
183*9880d681SAndroid Build Coastguard Worker if (Bucket == -1) return nullptr;
184*9880d681SAndroid Build Coastguard Worker
185*9880d681SAndroid Build Coastguard Worker StringMapEntryBase *Result = TheTable[Bucket];
186*9880d681SAndroid Build Coastguard Worker TheTable[Bucket] = getTombstoneVal();
187*9880d681SAndroid Build Coastguard Worker --NumItems;
188*9880d681SAndroid Build Coastguard Worker ++NumTombstones;
189*9880d681SAndroid Build Coastguard Worker assert(NumItems + NumTombstones <= NumBuckets);
190*9880d681SAndroid Build Coastguard Worker
191*9880d681SAndroid Build Coastguard Worker return Result;
192*9880d681SAndroid Build Coastguard Worker }
193*9880d681SAndroid Build Coastguard Worker
194*9880d681SAndroid Build Coastguard Worker
195*9880d681SAndroid Build Coastguard Worker
196*9880d681SAndroid Build Coastguard Worker /// RehashTable - Grow the table, redistributing values into the buckets with
197*9880d681SAndroid Build Coastguard Worker /// the appropriate mod-of-hashtable-size.
RehashTable(unsigned BucketNo)198*9880d681SAndroid Build Coastguard Worker unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
199*9880d681SAndroid Build Coastguard Worker unsigned NewSize;
200*9880d681SAndroid Build Coastguard Worker unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
201*9880d681SAndroid Build Coastguard Worker
202*9880d681SAndroid Build Coastguard Worker // If the hash table is now more than 3/4 full, or if fewer than 1/8 of
203*9880d681SAndroid Build Coastguard Worker // the buckets are empty (meaning that many are filled with tombstones),
204*9880d681SAndroid Build Coastguard Worker // grow/rehash the table.
205*9880d681SAndroid Build Coastguard Worker if (LLVM_UNLIKELY(NumItems * 4 > NumBuckets * 3)) {
206*9880d681SAndroid Build Coastguard Worker NewSize = NumBuckets*2;
207*9880d681SAndroid Build Coastguard Worker } else if (LLVM_UNLIKELY(NumBuckets - (NumItems + NumTombstones) <=
208*9880d681SAndroid Build Coastguard Worker NumBuckets / 8)) {
209*9880d681SAndroid Build Coastguard Worker NewSize = NumBuckets;
210*9880d681SAndroid Build Coastguard Worker } else {
211*9880d681SAndroid Build Coastguard Worker return BucketNo;
212*9880d681SAndroid Build Coastguard Worker }
213*9880d681SAndroid Build Coastguard Worker
214*9880d681SAndroid Build Coastguard Worker unsigned NewBucketNo = BucketNo;
215*9880d681SAndroid Build Coastguard Worker // Allocate one extra bucket which will always be non-empty. This allows the
216*9880d681SAndroid Build Coastguard Worker // iterators to stop at end.
217*9880d681SAndroid Build Coastguard Worker StringMapEntryBase **NewTableArray =
218*9880d681SAndroid Build Coastguard Worker (StringMapEntryBase **)calloc(NewSize+1, sizeof(StringMapEntryBase *) +
219*9880d681SAndroid Build Coastguard Worker sizeof(unsigned));
220*9880d681SAndroid Build Coastguard Worker unsigned *NewHashArray = (unsigned *)(NewTableArray + NewSize + 1);
221*9880d681SAndroid Build Coastguard Worker NewTableArray[NewSize] = (StringMapEntryBase*)2;
222*9880d681SAndroid Build Coastguard Worker
223*9880d681SAndroid Build Coastguard Worker // Rehash all the items into their new buckets. Luckily :) we already have
224*9880d681SAndroid Build Coastguard Worker // the hash values available, so we don't have to rehash any strings.
225*9880d681SAndroid Build Coastguard Worker for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
226*9880d681SAndroid Build Coastguard Worker StringMapEntryBase *Bucket = TheTable[I];
227*9880d681SAndroid Build Coastguard Worker if (Bucket && Bucket != getTombstoneVal()) {
228*9880d681SAndroid Build Coastguard Worker // Fast case, bucket available.
229*9880d681SAndroid Build Coastguard Worker unsigned FullHash = HashTable[I];
230*9880d681SAndroid Build Coastguard Worker unsigned NewBucket = FullHash & (NewSize-1);
231*9880d681SAndroid Build Coastguard Worker if (!NewTableArray[NewBucket]) {
232*9880d681SAndroid Build Coastguard Worker NewTableArray[FullHash & (NewSize-1)] = Bucket;
233*9880d681SAndroid Build Coastguard Worker NewHashArray[FullHash & (NewSize-1)] = FullHash;
234*9880d681SAndroid Build Coastguard Worker if (I == BucketNo)
235*9880d681SAndroid Build Coastguard Worker NewBucketNo = NewBucket;
236*9880d681SAndroid Build Coastguard Worker continue;
237*9880d681SAndroid Build Coastguard Worker }
238*9880d681SAndroid Build Coastguard Worker
239*9880d681SAndroid Build Coastguard Worker // Otherwise probe for a spot.
240*9880d681SAndroid Build Coastguard Worker unsigned ProbeSize = 1;
241*9880d681SAndroid Build Coastguard Worker do {
242*9880d681SAndroid Build Coastguard Worker NewBucket = (NewBucket + ProbeSize++) & (NewSize-1);
243*9880d681SAndroid Build Coastguard Worker } while (NewTableArray[NewBucket]);
244*9880d681SAndroid Build Coastguard Worker
245*9880d681SAndroid Build Coastguard Worker // Finally found a slot. Fill it in.
246*9880d681SAndroid Build Coastguard Worker NewTableArray[NewBucket] = Bucket;
247*9880d681SAndroid Build Coastguard Worker NewHashArray[NewBucket] = FullHash;
248*9880d681SAndroid Build Coastguard Worker if (I == BucketNo)
249*9880d681SAndroid Build Coastguard Worker NewBucketNo = NewBucket;
250*9880d681SAndroid Build Coastguard Worker }
251*9880d681SAndroid Build Coastguard Worker }
252*9880d681SAndroid Build Coastguard Worker
253*9880d681SAndroid Build Coastguard Worker free(TheTable);
254*9880d681SAndroid Build Coastguard Worker
255*9880d681SAndroid Build Coastguard Worker TheTable = NewTableArray;
256*9880d681SAndroid Build Coastguard Worker NumBuckets = NewSize;
257*9880d681SAndroid Build Coastguard Worker NumTombstones = 0;
258*9880d681SAndroid Build Coastguard Worker return NewBucketNo;
259*9880d681SAndroid Build Coastguard Worker }
260