re PR c++/11131 (Unrelated declaration removes inline flag from function)
[official-gcc.git] / gcc / hashtable.c
blob5254882379da4ef0864ab63e699572b87e84c141
1 /* Hash tables.
2 Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2, or (at your option) any
7 later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 In other words, you are welcome to use, share and improve this program.
19 You are forbidden to forbid anyone else to use, share and improve
20 what you give them. Help stamp out software-hoarding! */
22 #include "config.h"
23 #include "system.h"
24 #include "hashtable.h"
26 /* The code below is a specialization of Vladimir Makarov's expandable
27 hash tables (see libiberty/hashtab.c). The abstraction penalty was
28 too high to continue using the generic form. This code knows
29 intrinsically how to calculate a hash value, and how to compare an
30 existing entry with a potential new one. Also, the ability to
31 delete members from the table has been removed. */
33 static unsigned int calc_hash (const unsigned char *, unsigned int);
34 static void ht_expand (hash_table *);
35 static double approx_sqrt (double);
37 /* Calculate the hash of the string STR of length LEN. */
39 static unsigned int
40 calc_hash (const unsigned char *str, unsigned int len)
42 unsigned int n = len;
43 unsigned int r = 0;
44 #define HASHSTEP(r, c) ((r) * 67 + ((c) - 113));
46 while (n--)
47 r = HASHSTEP (r, *str++);
49 return r + len;
50 #undef HASHSTEP
53 /* Initialize an identifier hashtable. */
55 hash_table *
56 ht_create (unsigned int order)
58 unsigned int nslots = 1 << order;
59 hash_table *table;
61 table = xmalloc (sizeof (hash_table));
62 memset (table, 0, sizeof (hash_table));
64 /* Strings need no alignment. */
65 _obstack_begin (&table->stack, 0, 0,
66 (void *(*) (long)) xmalloc,
67 (void (*) (void *)) free);
69 obstack_alignment_mask (&table->stack) = 0;
71 table->entries = xcalloc (nslots, sizeof (hashnode));
72 table->nslots = nslots;
73 return table;
76 /* Frees all memory associated with a hash table. */
78 void
79 ht_destroy (hash_table *table)
81 obstack_free (&table->stack, NULL);
82 free (table->entries);
83 free (table);
86 /* Returns the hash entry for the a STR of length LEN. If that string
87 already exists in the table, returns the existing entry, and, if
88 INSERT is CPP_ALLOCED, frees the last obstack object. If the
89 identifier hasn't been seen before, and INSERT is CPP_NO_INSERT,
90 returns NULL. Otherwise insert and returns a new entry. A new
91 string is alloced if INSERT is CPP_ALLOC, otherwise INSERT is
92 CPP_ALLOCED and the item is assumed to be at the top of the
93 obstack. */
94 hashnode
95 ht_lookup (hash_table *table, const unsigned char *str, unsigned int len,
96 enum ht_lookup_option insert)
98 unsigned int hash = calc_hash (str, len);
99 unsigned int hash2;
100 unsigned int index;
101 size_t sizemask;
102 hashnode node;
104 sizemask = table->nslots - 1;
105 index = hash & sizemask;
107 /* hash2 must be odd, so we're guaranteed to visit every possible
108 location in the table during rehashing. */
109 hash2 = ((hash * 17) & sizemask) | 1;
110 table->searches++;
112 for (;;)
114 node = table->entries[index];
116 if (node == NULL)
117 break;
119 if (node->hash_value == hash && HT_LEN (node) == len
120 && !memcmp (HT_STR (node), str, len))
122 if (insert == HT_ALLOCED)
123 /* The string we search for was placed at the end of the
124 obstack. Release it. */
125 obstack_free (&table->stack, (void *) str);
126 return node;
129 index = (index + hash2) & sizemask;
130 table->collisions++;
133 if (insert == HT_NO_INSERT)
134 return NULL;
136 node = (*table->alloc_node) (table);
137 table->entries[index] = node;
139 HT_LEN (node) = len;
140 node->hash_value = hash;
141 if (insert == HT_ALLOC)
142 HT_STR (node) = obstack_copy0 (&table->stack, str, len);
143 else
144 HT_STR (node) = str;
146 if (++table->nelements * 4 >= table->nslots * 3)
147 /* Must expand the string table. */
148 ht_expand (table);
150 return node;
153 /* Double the size of a hash table, re-hashing existing entries. */
155 static void
156 ht_expand (hash_table *table)
158 hashnode *nentries, *p, *limit;
159 unsigned int size, sizemask;
161 size = table->nslots * 2;
162 nentries = xcalloc (size, sizeof (hashnode));
163 sizemask = size - 1;
165 p = table->entries;
166 limit = p + table->nslots;
168 if (*p)
170 unsigned int index, hash, hash2;
172 hash = (*p)->hash_value;
173 hash2 = ((hash * 17) & sizemask) | 1;
174 index = hash & sizemask;
176 for (;;)
178 if (! nentries[index])
180 nentries[index] = *p;
181 break;
184 index = (index + hash2) & sizemask;
187 while (++p < limit);
189 free (table->entries);
190 table->entries = nentries;
191 table->nslots = size;
194 /* For all nodes in TABLE, callback CB with parameters TABLE->PFILE,
195 the node, and V. */
196 void
197 ht_forall (hash_table *table, ht_cb cb, const void *v)
199 hashnode *p, *limit;
201 p = table->entries;
202 limit = p + table->nslots;
204 if (*p)
206 if ((*cb) (table->pfile, *p, v) == 0)
207 break;
209 while (++p < limit);
212 /* Dump allocation statistics to stderr. */
214 void
215 ht_dump_statistics (hash_table *table)
217 size_t nelts, nids, overhead, headers;
218 size_t total_bytes, longest, sum_of_squares;
219 double exp_len, exp_len2, exp2_len;
220 hashnode *p, *limit;
222 #define SCALE(x) ((unsigned long) ((x) < 1024*10 \
223 ? (x) \
224 : ((x) < 1024*1024*10 \
225 ? (x) / 1024 \
226 : (x) / (1024*1024))))
227 #define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M'))
229 total_bytes = longest = sum_of_squares = nids = 0;
230 p = table->entries;
231 limit = p + table->nslots;
233 if (*p)
235 size_t n = HT_LEN (*p);
237 total_bytes += n;
238 sum_of_squares += n * n;
239 if (n > longest)
240 longest = n;
241 nids++;
243 while (++p < limit);
245 nelts = table->nelements;
246 overhead = obstack_memory_used (&table->stack) - total_bytes;
247 headers = table->nslots * sizeof (hashnode);
249 fprintf (stderr, "\nString pool\nentries\t\t%lu\n",
250 (unsigned long) nelts);
251 fprintf (stderr, "identifiers\t%lu (%.2f%%)\n",
252 (unsigned long) nids, nids * 100.0 / nelts);
253 fprintf (stderr, "slots\t\t%lu\n",
254 (unsigned long) table->nslots);
255 fprintf (stderr, "bytes\t\t%lu%c (%lu%c overhead)\n",
256 SCALE (total_bytes), LABEL (total_bytes),
257 SCALE (overhead), LABEL (overhead));
258 fprintf (stderr, "table size\t%lu%c\n",
259 SCALE (headers), LABEL (headers));
261 exp_len = (double)total_bytes / (double)nelts;
262 exp2_len = exp_len * exp_len;
263 exp_len2 = (double) sum_of_squares / (double) nelts;
265 fprintf (stderr, "coll/search\t%.4f\n",
266 (double) table->collisions / (double) table->searches);
267 fprintf (stderr, "ins/search\t%.4f\n",
268 (double) nelts / (double) table->searches);
269 fprintf (stderr, "avg. entry\t%.2f bytes (+/- %.2f)\n",
270 exp_len, approx_sqrt (exp_len2 - exp2_len));
271 fprintf (stderr, "longest entry\t%lu\n",
272 (unsigned long) longest);
273 #undef SCALE
274 #undef LABEL
277 /* Return the approximate positive square root of a number N. This is for
278 statistical reports, not code generation. */
279 static double
280 approx_sqrt (double x)
282 double s, d;
284 if (x < 0)
285 abort ();
286 if (x == 0)
287 return 0;
289 s = x;
292 d = (s * s - x) / (2 * s);
293 s -= d;
295 while (d > .0001);
296 return s;