* bfd-in.h (bfd_hash_table): Add count field.

* bfd-in2.h: Regenerate.
* hash.c (higher_prime_number): New.
(bfd_hash_table_inint_n): Init count field.
(bfd_hash_lookup): Grow table as needed.
This commit is contained in:
DJ Delorie
2006-05-01 19:36:27 +00:00
parent 8608915fb1
commit aa149cf7d1
4 changed files with 112 additions and 1 deletions

View File

@@ -1,3 +1,11 @@
2006-05-01 DJ Delorie <dj@redhat.com>
* bfd-in.h (bfd_hash_table): Add count field.
* bfd-in2.h: Regenerate.
* hash.c (higher_prime_number): New.
(bfd_hash_table_inint_n): Init count field.
(bfd_hash_lookup): Grow table as needed.
2006-04-27 Kaz Kojima <kkojima@rr.iij4u.or.jp>
PR binutils/2584

View File

@@ -376,6 +376,8 @@ struct bfd_hash_table
struct bfd_hash_entry **table;
/* The number of slots in the hash table. */
unsigned int size;
/* The number of entries in the hash table. */
unsigned int count;
/* The size of elements. */
unsigned int entsize;
/* A function used to create new elements in the hash table. The

View File

@@ -383,6 +383,8 @@ struct bfd_hash_table
struct bfd_hash_entry **table;
/* The number of slots in the hash table. */
unsigned int size;
/* The number of entries in the hash table. */
unsigned int count;
/* The size of elements. */
unsigned int entsize;
/* A function used to create new elements in the hash table. The

View File

@@ -298,7 +298,72 @@ SUBSUBSECTION
*/
/* The default number of entries to use when creating a hash table. */
#define DEFAULT_SIZE 4051
#define DEFAULT_SIZE (4093)
/* The following function returns a nearest prime number which is
greater than N, and near a power of two. Copied from libiberty. */
static unsigned long
higher_prime_number (unsigned long n)
{
/* These are primes that are near, but slightly smaller than, a
power of two. */
static const unsigned long primes[] = {
(unsigned long) 7,
(unsigned long) 13,
(unsigned long) 31,
(unsigned long) 61,
(unsigned long) 127,
(unsigned long) 251,
(unsigned long) 509,
(unsigned long) 1021,
(unsigned long) 2039,
(unsigned long) 4093,
(unsigned long) 8191,
(unsigned long) 16381,
(unsigned long) 32749,
(unsigned long) 65521,
(unsigned long) 131071,
(unsigned long) 262139,
(unsigned long) 524287,
(unsigned long) 1048573,
(unsigned long) 2097143,
(unsigned long) 4194301,
(unsigned long) 8388593,
(unsigned long) 16777213,
(unsigned long) 33554393,
(unsigned long) 67108859,
(unsigned long) 134217689,
(unsigned long) 268435399,
(unsigned long) 536870909,
(unsigned long) 1073741789,
(unsigned long) 2147483647,
/* 4294967291L */
((unsigned long) 2147483647) + ((unsigned long) 2147483644),
};
const unsigned long *low = &primes[0];
const unsigned long *high = &primes[sizeof(primes) / sizeof(primes[0])];
while (low != high)
{
const unsigned long *mid = low + (high - low) / 2;
if (n >= *mid)
low = mid + 1;
else
high = mid;
}
/* If we've run out of primes, abort. */
if (n > *low)
{
fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
abort ();
}
return *low;
}
static size_t bfd_default_hash_table_size = DEFAULT_SIZE;
/* Create a new hash table, given a number of entries. */
@@ -330,6 +395,7 @@ bfd_hash_table_init_n (struct bfd_hash_table *table,
memset ((void *) table->table, 0, alloc);
table->size = size;
table->entsize = entsize;
table->count = 0;
table->newfunc = newfunc;
return TRUE;
}
@@ -402,6 +468,7 @@ bfd_hash_lookup (struct bfd_hash_table *table,
if (copy)
{
char *new;
table->count ++;
new = objalloc_alloc ((struct objalloc *) table->memory, len + 1);
if (!new)
@@ -417,6 +484,38 @@ bfd_hash_lookup (struct bfd_hash_table *table,
hashp->next = table->table[index];
table->table[index] = hashp;
if (table->count > table->size * 3 / 4)
{
int newsize = higher_prime_number (table->size);
struct bfd_hash_entry **newtable;
unsigned int hi;
unsigned int alloc;
alloc = newsize * sizeof (struct bfd_hash_entry *);
newtable = ((struct bfd_hash_entry **)
objalloc_alloc ((struct objalloc *) table->memory, alloc));
memset ((PTR) newtable, 0, alloc);
for (hi = 0; hi < table->size; hi ++)
while (table->table[hi])
{
struct bfd_hash_entry *chain = table->table[hi];
struct bfd_hash_entry *chain_end = chain;
int index;
while (chain_end->next && chain_end->next->hash == chain->hash)
chain_end = chain_end->next;
table->table[hi] = chain_end->next;
index = chain->hash % newsize;
chain_end->next = newtable[index];
newtable[index] = chain;
}
table->table = newtable;
table->size = newsize;
}
return hashp;
}