123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443 |
- /* An expandable hash tables datatype.
- Copyright (C) 1999-2015 Free Software Foundation, Inc.
- Contributed by Vladimir Makarov <vmakarov@cygnus.com>.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
- /* The hash table code copied from include/hashtab.[hc] and adjusted,
- so that the hash table entries are in the flexible array at the end
- of the control structure, no callbacks are used and the elements in the
- table are of the hash_entry_type type.
- Before including this file, define hash_entry_type type and
- htab_alloc and htab_free functions. After including it, define
- htab_hash and htab_eq inline functions. */
- /* This package implements basic hash table functionality. It is possible
- to search for an entry, create an entry and destroy an entry.
- Elements in the table are generic pointers.
- The size of the table is not fixed; if the occupancy of the table
- grows too high the hash table will be expanded.
- The abstract data implementation is based on generalized Algorithm D
- from Knuth's book "The art of computer programming". Hash table is
- expanded by creation of new hash table and transferring elements from
- the old table to the new table. */
- /* The type for a hash code. */
- typedef unsigned int hashval_t;
- static inline hashval_t htab_hash (hash_entry_type);
- static inline bool htab_eq (hash_entry_type, hash_entry_type);
- /* This macro defines reserved value for empty table entry. */
- #define HTAB_EMPTY_ENTRY ((hash_entry_type) 0)
- /* This macro defines reserved value for table entry which contained
- a deleted element. */
- #define HTAB_DELETED_ENTRY ((hash_entry_type) 1)
- /* Hash tables are of the following type. The structure
- (implementation) of this type is not needed for using the hash
- tables. All work with hash table should be executed only through
- functions mentioned below. The size of this structure is subject to
- change. */
- struct htab {
- /* Current size (in entries) of the hash table. */
- size_t size;
- /* Current number of elements including also deleted elements. */
- size_t n_elements;
- /* Current number of deleted elements in the table. */
- size_t n_deleted;
- /* Current size (in entries) of the hash table, as an index into the
- table of primes. */
- unsigned int size_prime_index;
- /* Table itself. */
- hash_entry_type entries[];
- };
- typedef struct htab *htab_t;
- /* An enum saying whether we insert into the hash table or not. */
- enum insert_option {NO_INSERT, INSERT};
- /* Table of primes and multiplicative inverses.
- Note that these are not minimally reduced inverses. Unlike when generating
- code to divide by a constant, we want to be able to use the same algorithm
- all the time. All of these inverses (are implied to) have bit 32 set.
- For the record, the function that computed the table is in
- libiberty/hashtab.c. */
- struct prime_ent
- {
- hashval_t prime;
- hashval_t inv;
- hashval_t inv_m2; /* inverse of prime-2 */
- hashval_t shift;
- };
- static struct prime_ent const prime_tab[] = {
- { 7, 0x24924925, 0x9999999b, 2 },
- { 13, 0x3b13b13c, 0x745d1747, 3 },
- { 31, 0x08421085, 0x1a7b9612, 4 },
- { 61, 0x0c9714fc, 0x15b1e5f8, 5 },
- { 127, 0x02040811, 0x0624dd30, 6 },
- { 251, 0x05197f7e, 0x073260a5, 7 },
- { 509, 0x01824366, 0x02864fc8, 8 },
- { 1021, 0x00c0906d, 0x014191f7, 9 },
- { 2039, 0x0121456f, 0x0161e69e, 10 },
- { 4093, 0x00300902, 0x00501908, 11 },
- { 8191, 0x00080041, 0x00180241, 12 },
- { 16381, 0x000c0091, 0x00140191, 13 },
- { 32749, 0x002605a5, 0x002a06e6, 14 },
- { 65521, 0x000f00e2, 0x00110122, 15 },
- { 131071, 0x00008001, 0x00018003, 16 },
- { 262139, 0x00014002, 0x0001c004, 17 },
- { 524287, 0x00002001, 0x00006001, 18 },
- { 1048573, 0x00003001, 0x00005001, 19 },
- { 2097143, 0x00004801, 0x00005801, 20 },
- { 4194301, 0x00000c01, 0x00001401, 21 },
- { 8388593, 0x00001e01, 0x00002201, 22 },
- { 16777213, 0x00000301, 0x00000501, 23 },
- { 33554393, 0x00001381, 0x00001481, 24 },
- { 67108859, 0x00000141, 0x000001c1, 25 },
- { 134217689, 0x000004e1, 0x00000521, 26 },
- { 268435399, 0x00000391, 0x000003b1, 27 },
- { 536870909, 0x00000019, 0x00000029, 28 },
- { 1073741789, 0x0000008d, 0x00000095, 29 },
- { 2147483647, 0x00000003, 0x00000007, 30 },
- /* Avoid "decimal constant so large it is unsigned" for 4294967291. */
- { 0xfffffffb, 0x00000006, 0x00000008, 31 }
- };
- /* The following function returns an index into the above table of the
- nearest prime number which is greater than N, and near a power of two. */
- static unsigned int
- higher_prime_index (unsigned long n)
- {
- unsigned int low = 0;
- unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]);
- while (low != high)
- {
- unsigned int mid = low + (high - low) / 2;
- if (n > prime_tab[mid].prime)
- low = mid + 1;
- else
- high = mid;
- }
- /* If we've run out of primes, abort. */
- if (n > prime_tab[low].prime)
- abort ();
- return low;
- }
- /* Return the current size of given hash table. */
- static inline size_t
- htab_size (htab_t htab)
- {
- return htab->size;
- }
- /* Return the current number of elements in given hash table. */
- static inline size_t
- htab_elements (htab_t htab)
- {
- return htab->n_elements - htab->n_deleted;
- }
- /* Return X % Y. */
- static inline hashval_t
- htab_mod_1 (hashval_t x, hashval_t y, hashval_t inv, int shift)
- {
- /* The multiplicative inverses computed above are for 32-bit types, and
- requires that we be able to compute a highpart multiply. */
- if (sizeof (hashval_t) * __CHAR_BIT__ <= 32)
- {
- hashval_t t1, t2, t3, t4, q, r;
- t1 = ((unsigned long long)x * inv) >> 32;
- t2 = x - t1;
- t3 = t2 >> 1;
- t4 = t1 + t3;
- q = t4 >> shift;
- r = x - (q * y);
- return r;
- }
- /* Otherwise just use the native division routines. */
- return x % y;
- }
- /* Compute the primary hash for HASH given HTAB's current size. */
- static inline hashval_t
- htab_mod (hashval_t hash, htab_t htab)
- {
- const struct prime_ent *p = &prime_tab[htab->size_prime_index];
- return htab_mod_1 (hash, p->prime, p->inv, p->shift);
- }
- /* Compute the secondary hash for HASH given HTAB's current size. */
- static inline hashval_t
- htab_mod_m2 (hashval_t hash, htab_t htab)
- {
- const struct prime_ent *p = &prime_tab[htab->size_prime_index];
- return 1 + htab_mod_1 (hash, p->prime - 2, p->inv_m2, p->shift);
- }
- /* Create hash table of size SIZE. */
- static htab_t
- htab_create (size_t size)
- {
- htab_t result;
- unsigned int size_prime_index;
- size_prime_index = higher_prime_index (size);
- size = prime_tab[size_prime_index].prime;
- result = (htab_t) htab_alloc (sizeof (struct htab)
- + size * sizeof (hash_entry_type));
- result->size = size;
- result->n_elements = 0;
- result->n_deleted = 0;
- result->size_prime_index = size_prime_index;
- memset (result->entries, 0, size * sizeof (hash_entry_type));
- return result;
- }
- /* Similar to htab_find_slot, but without several unwanted side effects:
- - Does not call htab_eq when it finds an existing entry.
- - Does not change the count of elements in the hash table.
- This function also assumes there are no deleted entries in the table.
- HASH is the hash value for the element to be inserted. */
- static hash_entry_type *
- find_empty_slot_for_expand (htab_t htab, hashval_t hash)
- {
- hashval_t index = htab_mod (hash, htab);
- size_t size = htab_size (htab);
- hash_entry_type *slot = htab->entries + index;
- hashval_t hash2;
- if (*slot == HTAB_EMPTY_ENTRY)
- return slot;
- else if (*slot == HTAB_DELETED_ENTRY)
- abort ();
- hash2 = htab_mod_m2 (hash, htab);
- for (;;)
- {
- index += hash2;
- if (index >= size)
- index -= size;
- slot = htab->entries + index;
- if (*slot == HTAB_EMPTY_ENTRY)
- return slot;
- else if (*slot == HTAB_DELETED_ENTRY)
- abort ();
- }
- }
- /* The following function changes size of memory allocated for the
- entries and repeatedly inserts the table elements. The occupancy
- of the table after the call will be about 50%. Naturally the hash
- table must already exist. Remember also that the place of the
- table entries is changed. */
- static htab_t
- htab_expand (htab_t htab)
- {
- htab_t nhtab;
- hash_entry_type *olimit;
- hash_entry_type *p;
- size_t osize, elts;
- osize = htab->size;
- olimit = htab->entries + osize;
- elts = htab_elements (htab);
- /* Resize only when table after removal of unused elements is either
- too full or too empty. */
- if (elts * 2 > osize || (elts * 8 < osize && osize > 32))
- nhtab = htab_create (elts * 2);
- else
- nhtab = htab_create (osize - 1);
- nhtab->n_elements = htab->n_elements - htab->n_deleted;
- p = htab->entries;
- do
- {
- hash_entry_type x = *p;
- if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
- *find_empty_slot_for_expand (nhtab, htab_hash (x)) = x;
- p++;
- }
- while (p < olimit);
- htab_free (htab);
- return nhtab;
- }
- /* This function searches for a hash table entry equal to the given
- element. It cannot be used to insert or delete an element. */
- static hash_entry_type
- htab_find (htab_t htab, const hash_entry_type element)
- {
- hashval_t index, hash2, hash = htab_hash (element);
- size_t size;
- hash_entry_type entry;
- size = htab_size (htab);
- index = htab_mod (hash, htab);
- entry = htab->entries[index];
- if (entry == HTAB_EMPTY_ENTRY
- || (entry != HTAB_DELETED_ENTRY && htab_eq (entry, element)))
- return entry;
- hash2 = htab_mod_m2 (hash, htab);
- for (;;)
- {
- index += hash2;
- if (index >= size)
- index -= size;
- entry = htab->entries[index];
- if (entry == HTAB_EMPTY_ENTRY
- || (entry != HTAB_DELETED_ENTRY && htab_eq (entry, element)))
- return entry;
- }
- }
- /* This function searches for a hash table slot containing an entry
- equal to the given element. To delete an entry, call this with
- insert=NO_INSERT, then call htab_clear_slot on the slot returned
- (possibly after doing some checks). To insert an entry, call this
- with insert=INSERT, then write the value you want into the returned
- slot. */
- static hash_entry_type *
- htab_find_slot (htab_t *htabp, const hash_entry_type element,
- enum insert_option insert)
- {
- hash_entry_type *first_deleted_slot;
- hashval_t index, hash2, hash = htab_hash (element);
- size_t size;
- hash_entry_type entry;
- htab_t htab = *htabp;
- size = htab_size (htab);
- if (insert == INSERT && size * 3 <= htab->n_elements * 4)
- {
- htab = *htabp = htab_expand (htab);
- size = htab_size (htab);
- }
- index = htab_mod (hash, htab);
- first_deleted_slot = NULL;
- entry = htab->entries[index];
- if (entry == HTAB_EMPTY_ENTRY)
- goto empty_entry;
- else if (entry == HTAB_DELETED_ENTRY)
- first_deleted_slot = &htab->entries[index];
- else if (htab_eq (entry, element))
- return &htab->entries[index];
- hash2 = htab_mod_m2 (hash, htab);
- for (;;)
- {
- index += hash2;
- if (index >= size)
- index -= size;
- entry = htab->entries[index];
- if (entry == HTAB_EMPTY_ENTRY)
- goto empty_entry;
- else if (entry == HTAB_DELETED_ENTRY)
- {
- if (!first_deleted_slot)
- first_deleted_slot = &htab->entries[index];
- }
- else if (htab_eq (entry, element))
- return &htab->entries[index];
- }
- empty_entry:
- if (insert == NO_INSERT)
- return NULL;
- if (first_deleted_slot)
- {
- htab->n_deleted--;
- *first_deleted_slot = HTAB_EMPTY_ENTRY;
- return first_deleted_slot;
- }
- htab->n_elements++;
- return &htab->entries[index];
- }
- /* This function clears a specified slot in a hash table. It is
- useful when you've already done the lookup and don't want to do it
- again. */
- static inline void
- htab_clear_slot (htab_t htab, hash_entry_type *slot)
- {
- if (slot < htab->entries || slot >= htab->entries + htab_size (htab)
- || *slot == HTAB_EMPTY_ENTRY || *slot == HTAB_DELETED_ENTRY)
- abort ();
- *slot = HTAB_DELETED_ENTRY;
- htab->n_deleted++;
- }
- /* Returns a hash code for pointer P. Simplified version of evahash */
- static inline hashval_t
- hash_pointer (const void *p)
- {
- uintptr_t v = (uintptr_t) p;
- if (sizeof (v) > sizeof (hashval_t))
- v ^= v >> (sizeof (uintptr_t) / 2 * __CHAR_BIT__);
- return v;
- }
|