]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libiberty/hashtab.c
hashtab.c: Remove debugging variables (all_searches, all_collisions, all_expansions).
[thirdparty/gcc.git] / libiberty / hashtab.c
index 3f5b3030422f19185b687fdc485a58dd6c4517d3..ea9f9d38ac760e63f973f63a2849aebbf593ffa8 100644 (file)
@@ -46,25 +46,9 @@ Boston, MA 02111-1307, USA.  */
 #include "libiberty.h"
 #include "hashtab.h"
 
-/* The following variable is used for debugging. Its value is number
-   of all calls of `find_hash_table_entry' for all hash tables. */
-
-static int all_searches = 0;
-
-/* The following variable is used for debugging. Its value is number
-   of collisions fixed for time of work with all hash tables. */
-
-static int all_collisions = 0;
-
-/* The following variable is used for debugging. Its value is number
-   of all table expansions fixed for time of work with all hash
-   tables. */
-
-static int all_expansions = 0;
-
 /* This macro defines reserved value for empty table entry. */
 
-#define EMPTY_ENTRY    NULL
+#define EMPTY_ENTRY    ((void *) 0)
 
 /* This macro defines reserved value for table entry which contained
    a deleted element. */
@@ -75,19 +59,27 @@ static int all_expansions = 0;
    greater than given source number. */
 
 static unsigned long
-higher_prime_number (number)
-     unsigned long number;
+higher_prime_number (n)
+     unsigned long n;
 {
   unsigned long i;
 
-  for (number = (number / 2) * 2 + 3;; number += 2)
+  n |= 0x01;  /* Force N to be odd.  */
+  if (n < 9)
+    return n; /* All odd numbers < 9 are prime.  */
+
+ next:
+  n += 2;
+  i = 3;
+  do
     {
-      for (i = 3; i * i <= number; i += 2)
-        if (number % i == 0)
-          break;
-      if (i * i > number)
-        return number;
+      if (n % i == 0)
+       goto next;
+      i += 2;
     }
+  while ((i * i) <= n);
+
+  return n;
 }
 
 /* This function creates table with length slightly longer than given
@@ -95,26 +87,20 @@ higher_prime_number (number)
    hash table entries are EMPTY_ENTRY).  The function returns the
    created hash table. */
 
-hash_table_t
-create_hash_table (size, hash_function, eq_function)
+htab_t
+htab_create (size, hash_f, eq_f)
      size_t size;
-     unsigned (*hash_function) PARAMS ((hash_table_entry_t));
-     int (*eq_function) PARAMS ((hash_table_entry_t, hash_table_entry_t));
+     htab_hash hash_f;
+     htab_eq eq_f;
 {
-  hash_table_t result;
+  htab_t result;
 
   size = higher_prime_number (size);
-  result = (hash_table_t) xmalloc (sizeof (*result));
-  result->entries
-    = (hash_table_entry_t *) xmalloc (size * sizeof (hash_table_entry_t));
+  result = (htab_t) xcalloc (1, sizeof (struct htab));
+  result->entries = (void **) xcalloc (size, sizeof (void *));
   result->size = size;
-  result->hash_function = hash_function;
-  result->eq_function = eq_function;
-  result->number_of_elements = 0;
-  result->number_of_deleted_elements = 0;
-  result->searches = 0;
-  result->collisions = 0;
-  memset (result->entries, 0, size * sizeof (hash_table_entry_t));
+  result->hash_f = hash_f;
+  result->eq_f = eq_f;
   return result;
 }
 
@@ -122,8 +108,8 @@ create_hash_table (size, hash_function, eq_function)
    Naturally the hash table must already exist. */
 
 void
-delete_hash_table (htab)
-     hash_table_t htab;
+htab_delete (htab)
+     htab_t htab;
 {
   free (htab->entries);
   free (htab);
@@ -132,10 +118,10 @@ delete_hash_table (htab)
 /* This function clears all entries in the given hash table.  */
 
 void
-empty_hash_table (htab)
-     hash_table_t htab;
+htab_empty (htab)
+     htab_t htab;
 {
-  memset (htab->entries, 0, htab->size * sizeof (hash_table_entry_t));
+  memset (htab->entries, 0, htab->size * sizeof (void *));
 }
 
 /* The following function changes size of memory allocated for the
@@ -145,121 +131,166 @@ empty_hash_table (htab)
    table entries is changed. */
 
 static void
-expand_hash_table (htab)
-     hash_table_t htab;
+htab_expand (htab)
+     htab_t htab;
 {
-  hash_table_t new_htab;
-  hash_table_entry_t *entry_ptr;
-  hash_table_entry_t *new_entry_ptr;
-
-  new_htab = create_hash_table (htab->number_of_elements * 2,
-                                htab->hash_function, htab->eq_function);
-  for (entry_ptr = htab->entries; entry_ptr < htab->entries + htab->size;
-       entry_ptr++)
-    if (*entry_ptr != EMPTY_ENTRY && *entry_ptr != DELETED_ENTRY)
-      {
-        new_entry_ptr = find_hash_table_entry (new_htab, *entry_ptr, 1);
-        *new_entry_ptr = (*entry_ptr);
-      }
-  free (htab->entries);
-  *htab = (*new_htab);
-  free (new_htab);
+  void **oentries;
+  void **olimit;
+  void **p;
+
+  oentries = htab->entries;
+  olimit = oentries + htab->size;
+
+  htab->size = higher_prime_number (htab->size * 2);
+  htab->entries = xcalloc (htab->size, sizeof (void **));
+
+  htab->n_elements -= htab->n_deleted;
+  htab->n_deleted = 0;
+
+  p = oentries;
+  do
+    {
+      void *x = *p;
+      if (x != EMPTY_ENTRY && x != DELETED_ENTRY)
+       {
+         void **q = htab_find_slot (htab, x, 1);
+         *q = x;
+       }
+      p++;
+    }
+  while (p < olimit);
+  free (oentries);
 }
 
-/* This function searches for hash table entry which contains element
-   equal to given value or empty entry in which given value can be
-   placed (if the element with given value does not exist in the
-   table).  The function works in two regimes.  The first regime is
-   used only for search.  The second is used for search and
-   reservation empty entry for given value.  The table is expanded if
-   occupancy (taking into accout also deleted elements) is more than
-   75%.  Naturally the hash table must already exist.  If reservation
-   flag is TRUE then the element with given value should be inserted
-   into the table entry before another call of
-   `find_hash_table_entry'. */
-
-hash_table_entry_t *
-find_hash_table_entry (htab, element, reserve)
-     hash_table_t htab;
-     hash_table_entry_t element;
-     int reserve;
+/* This function searches for a hash table entry equal to the given
+   element.  It cannot be used to insert or delete an element.  */
+
+void *
+htab_find (htab, element)
+     htab_t htab;
+     const void *element;
 {
-  hash_table_entry_t *entry_ptr;
-  hash_table_entry_t *first_deleted_entry_ptr;
-  unsigned index, hash_value, secondary_hash_value;
+  unsigned int index, hash, hash2;
+  size_t size;
+
+  htab->searches++;
+  size = htab->size;
+  hash = (*htab->hash_f) (element);
+  hash2 = 1 + hash % (size - 2);
+  index = hash % size;
 
-  if (htab->size * 3 <= htab->number_of_elements * 4)
+  for (;;)
     {
-      all_expansions++;
-      expand_hash_table (htab);
+      void *entry = htab->entries[index];
+      if (entry == EMPTY_ENTRY)
+       return NULL;
+      else if (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element))
+       return entry;
+
+      htab->collisions++;
+      index += hash2;
+      if (index >= size)
+       index -= size;
     }
-  hash_value = (*htab->hash_function) (element);
-  secondary_hash_value = 1 + hash_value % (htab->size - 2);
-  index = hash_value % htab->size;
+}
+
+/* This function searches for a hash table slot containing an entry
+   equal to the given element.  To delete an entry, call this with
+   INSERT = 0, then call htab_clear_slot on the slot returned (possibly
+   after doing some checks).  To insert an entry, call this with
+   INSERT = 1, then write the value you want into the returned slot.  */
+
+void **
+htab_find_slot (htab, element, insert)
+     htab_t htab;
+     const void *element;
+     int insert;
+{
+  void **first_deleted_slot;
+  unsigned int index, hash, hash2;
+  size_t size;
+
+  if (insert && htab->size * 3 <= htab->n_elements * 4)
+    htab_expand (htab);
+
+  size = htab->size;
+  hash = (*htab->hash_f) (element);
+  hash2 = 1 + hash % (size - 2);
+  index = hash % size;
+
   htab->searches++;
-  all_searches++;
-  first_deleted_entry_ptr = NULL;
-  for (;;htab->collisions++, all_collisions++)
+  first_deleted_slot = NULL;
+
+  for (;;)
     {
-      entry_ptr = htab->entries + index;
-      if (*entry_ptr == EMPTY_ENTRY)
-        {
-          if (reserve)
+      void *entry = htab->entries[index];
+      if (entry == EMPTY_ENTRY)
+       {
+         if (!insert)
+           return NULL;
+
+         htab->n_elements++;
+
+         if (first_deleted_slot)
            {
-             htab->number_of_elements++;
-             if (first_deleted_entry_ptr != NULL)
-               {
-                 entry_ptr = first_deleted_entry_ptr;
-                 *entry_ptr = EMPTY_ENTRY;
-               }
+             *first_deleted_slot = EMPTY_ENTRY;
+             return first_deleted_slot;
            }
-          break;
-        }
-      else if (*entry_ptr != DELETED_ENTRY)
-        {
-          if ((*htab->eq_function) (*entry_ptr, element))
-            break;
-        }
-      else if (first_deleted_entry_ptr == NULL)
-       first_deleted_entry_ptr = entry_ptr;
-      index += secondary_hash_value;
-      if (index >= htab->size)
-        index -= htab->size;
+
+         return &htab->entries[index];
+       }
+
+      if (entry == DELETED_ENTRY)
+       {
+         if (!first_deleted_slot)
+           first_deleted_slot = &htab->entries[index];
+       }
+      else
+       {
+         if ((*htab->eq_f) (entry, element))
+           return &htab->entries[index];
+       }
+      
+      htab->collisions++;
+      index += hash2;
+      if (index >= size)
+       index -= size;
     }
-  return entry_ptr;
 }
 
-/* This function deletes element with given value from hash table.
-   The hash table entry value will be `DELETED_ENTRY' after the
-   function call.  Naturally the hash table must already exist.  Hash
-   table entry for given value should be not empty (or deleted). */
+/* This function deletes an element with the given value from hash
+   table.  If there is no matching element in the hash table, this
+   function does nothing.  */
 
 void
-remove_element_from_hash_table_entry (htab, element)
-     hash_table_t htab;
-     hash_table_entry_t element;
+htab_remove_elt (htab, element)
+     htab_t htab;
+     void *element;
 {
-  hash_table_entry_t *entry_ptr;
+  void **slot;
 
-  entry_ptr = find_hash_table_entry (htab, element, 0);
-  *entry_ptr = DELETED_ENTRY;
-  htab->number_of_deleted_elements++;
+  slot = htab_find_slot (htab, element, 0);
+  if (*slot == EMPTY_ENTRY)
+    return;
+
+  *slot = DELETED_ENTRY;
+  htab->n_deleted++;
 }
 
-/* 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.  */
+/* 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.  */
 
 void
-clear_hash_table_slot (htab, slot)
-     hash_table_t htab;
-     hash_table_entry_t *slot;
+htab_clear_slot (htab, slot)
+     htab_t htab;
+     void **slot;
 {
   if (slot < htab->entries || slot >= htab->entries + htab->size
       || *slot == EMPTY_ENTRY || *slot == DELETED_ENTRY)
     abort ();
   *slot = DELETED_ENTRY;
-  htab->number_of_deleted_elements++;
+  htab->n_deleted++;
 }
 
 /* This function scans over the entire hash table calling
@@ -268,24 +299,29 @@ clear_hash_table_slot (htab, slot)
    argument.  */
 
 void
-traverse_hash_table (htab, callback, info)
-     hash_table_t htab;
-     int (*callback) PARAMS ((hash_table_entry_t, void *));
+htab_traverse (htab, callback, info)
+     htab_t htab;
+     htab_trav callback;
      void *info;
 {
-  hash_table_entry_t *entry_ptr;
-  for (entry_ptr = htab->entries; entry_ptr < htab->entries + htab->size;
-       entry_ptr++)
-    if (*entry_ptr != EMPTY_ENTRY && *entry_ptr != DELETED_ENTRY)
-      if (!callback (*entry_ptr, info))
-       break;
+  void **slot, **limit;
+  slot = htab->entries;
+  limit = slot + htab->size;
+  do
+    {
+      void *x = *slot;
+      if (x != EMPTY_ENTRY && x != DELETED_ENTRY)
+       if (!(*callback) (x, info))
+         break;
+    }
+  while (++slot < limit);
 }
 
 /* The following function returns current size of given hash table. */
 
 size_t
-hash_table_size (htab)
-     hash_table_t htab;
+htab_size (htab)
+     htab_t htab;
 {
   return htab->size;
 }
@@ -294,37 +330,23 @@ hash_table_size (htab)
    hash table. */
 
 size_t
-hash_table_elements_number (htab)
-     hash_table_t htab;
+htab_elements (htab)
+     htab_t htab;
 {
-  return htab->number_of_elements - htab->number_of_deleted_elements;
+  return htab->n_elements - htab->n_deleted;
 }
 
 /* The following function returns number of percents of fixed
    collisions during all work with given hash table. */
 
-int
-hash_table_collisions (htab)
-     hash_table_t htab;
+double
+htab_collisions (htab)
+     htab_t htab;
 {
   int searches;
 
   searches = htab->searches;
   if (searches == 0)
-    searches++;
-  return htab->collisions * 100 / searches;
-}
-
-/* The following function returns number of percents of fixed
-   collisions during all work with all hash tables. */
-
-int
-all_hash_table_collisions ()
-{
-  int searches;
-
-  searches = all_searches;
-  if (searches == 0)
-    searches++;
-  return all_collisions * 100 / searches;
+    return 0.0;
+  return (double)htab->collisions / (double)searches;
 }