1 /*-----------------------------------------------------------------------------
3 * (c) The AQUA Project, Glasgow University, 1995-1998
4 * (c) The GHC Team, 1999
6 * Dynamically expanding linear hash tables, as described in
7 * Per-\AAke Larson, ``Dynamic Hash Tables,'' CACM 31(4), April 1988,
9 * -------------------------------------------------------------------------- */
12 Replaced with ghc/rts/Hash.c in the new RTS
21 #define HSEGSIZE 1024 /* Size of a single hash table segment */
22 /* Also the minimum size of a hash table */
23 #define HDIRSIZE 1024 /* Size of the segment directory */
24 /* Maximum hash table size is HSEGSIZE * HDIRSIZE */
25 #define HLOAD 5 /* Maximum average load of a single hash bucket */
27 #define HCHUNK (1024 * sizeof(W_) / sizeof(HashList))
28 /* Number of HashList cells to allocate in one go */
31 /* Linked list of (key, data) pairs for separate chaining */
35 struct hashlist *next; /* Next cell in bucket chain (same hash value) */
38 typedef struct hashlist HashList;
41 int split; /* Next bucket to split when expanding */
42 int max; /* Max bucket of smaller table */
43 int mask1; /* Mask for doing the mod of h_1 (smaller table) */
44 int mask2; /* Mask for doing the mod of h_2 (larger table) */
45 int kcount; /* Number of keys */
46 int bcount; /* Number of buckets */
47 HashList **dir[HDIRSIZE]; /* Directory of segments */
50 /* -----------------------------------------------------------------------------
51 * Hash first using the smaller table. If the bucket is less than the
52 * next bucket to be split, re-hash using the larger table.
53 * -------------------------------------------------------------------------- */
56 hash(HashTable *table, W_ key)
60 /* Strip the boring zero bits */
61 key /= sizeof(StgWord);
63 /* Mod the size of the hash table (a power of 2) */
64 bucket = key & table->mask1;
66 if (bucket < table->split) {
67 /* Mod the size of the expanded hash table (also a power of 2) */
68 bucket = key & table->mask2;
73 /* -----------------------------------------------------------------------------
74 * Allocate a new segment of the dynamically growing hash table.
75 * -------------------------------------------------------------------------- */
78 allocSegment(HashTable *table, int segment)
80 table->dir[segment] = stgMallocBytes(HSEGSIZE * sizeof(HashList *),
85 /* -----------------------------------------------------------------------------
86 * Expand the larger hash table by one bucket, and split one bucket
87 * from the smaller table into two parts. Only the bucket referenced
88 * by @table->split@ is affected by the expansion.
89 * -------------------------------------------------------------------------- */
92 expand(HashTable *table)
103 if (table->split + table->max >= HDIRSIZE * HSEGSIZE)
104 /* Wow! That's big. Too big, so don't expand. */
107 /* Calculate indices of bucket to split */
108 oldsegment = table->split / HSEGSIZE;
109 oldindex = table->split % HSEGSIZE;
111 newbucket = table->max + table->split;
113 /* And the indices of the new bucket */
114 newsegment = newbucket / HSEGSIZE;
115 newindex = newbucket % HSEGSIZE;
118 allocSegment(table, newsegment);
120 if (++table->split == table->max) {
123 table->mask1 = table->mask2;
124 table->mask2 = table->mask2 << 1 | 1;
128 /* Split the bucket, paying no attention to the original order */
131 for (hl = table->dir[oldsegment][oldindex]; hl != NULL; hl = next) {
133 if (hash(table, hl->key) == newbucket) {
141 table->dir[oldsegment][oldindex] = old;
142 table->dir[newsegment][newindex] = new;
148 lookupHashTable(HashTable *table, StgWord key)
155 bucket = hash(table, key);
156 segment = bucket / HSEGSIZE;
157 index = bucket % HSEGSIZE;
159 for (hl = table->dir[segment][index]; hl != NULL; hl = hl->next)
167 /* -----------------------------------------------------------------------------
168 * We allocate the hashlist cells in large chunks to cut down on malloc
169 * overhead. Although we keep a free list of hashlist cells, we make
170 * no effort to actually return the space to the malloc arena.
171 * -------------------------------------------------------------------------- */
173 static HashList *freeList = NULL;
180 if ((hl = freeList) != NULL) {
183 hl = stgMallocBytes(HCHUNK * sizeof(HashList), "allocHashList");
186 for (p = freeList; p < hl + HCHUNK - 1; p++)
194 freeHashList(HashList *hl)
201 insertHashTable(HashTable *table, StgWord key, void *data)
208 /* We want no duplicates */
209 ASSERT(lookupHashTable(table, key) == NULL);
211 /* When the average load gets too high, we expand the table */
212 if (++table->kcount >= HLOAD * table->bcount)
215 bucket = hash(table, key);
216 segment = bucket / HSEGSIZE;
217 index = bucket % HSEGSIZE;
219 hl = allocHashList();
223 hl->next = table->dir[segment][index];
224 table->dir[segment][index] = hl;
229 removeHashTable(HashTable *table, StgWord key, void *data)
235 HashList *prev = NULL;
237 bucket = hash(table, key);
238 segment = bucket / HSEGSIZE;
239 index = bucket % HSEGSIZE;
241 for (hl = table->dir[segment][index]; hl != NULL; hl = hl->next) {
242 if (hl->key == key && (data == NULL || hl->data == data)) {
244 table->dir[segment][index] = hl->next;
246 prev->next = hl->next;
254 ASSERT(data == NULL);
258 /* -----------------------------------------------------------------------------
259 * When we free a hash table, we are also good enough to free the
260 * data part of each (key, data) pair, as long as our caller can tell
262 * -------------------------------------------------------------------------- */
265 freeHashTable(HashTable *table, void (*freeDataFun)(void *) )
272 /* The last bucket with something in it is table->max + table->split - 1 */
273 segment = (table->max + table->split - 1) / HSEGSIZE;
274 index = (table->max + table->split - 1) % HSEGSIZE;
276 while (segment >= 0) {
278 for (hl = table->dir[segment][index]; hl != NULL; hl = next) {
280 if (freeDataFun != NULL)
281 (*freeDataFun)(hl->data);
286 free(table->dir[segment]);
288 index = HSEGSIZE - 1;
293 /* -----------------------------------------------------------------------------
294 * When we initialize a hash table, we set up the first segment as well,
295 * initializing all of the first segment's hash buckets to NULL.
296 * -------------------------------------------------------------------------- */
304 table = stgMallocBytes(sizeof(HashTable),"allocHashTable");
306 allocSegment(table, 0);
308 for (hb = table->dir[0]; hb < table->dir[0] + HSEGSIZE; hb++)
312 table->max = HSEGSIZE;
313 table->mask1 = HSEGSIZE - 1;
314 table->mask2 = 2 * HSEGSIZE - 1;
316 table->bcount = HSEGSIZE;