Index: gcc/ChangeLog

2012-11-30  Lawrence Crowl  <crowl@google.com>

	* hash-table.h (class hash_table):
	Correct many methods with parameter types compare_type to the correct
	value_type.  (Correct code was unlikely to notice the change.)
	(hash_table::elements_with_deleted) New.

	* ggc-common.c (htab_t saving_htab):
	Change type to hash_table.  Update dependent calls and types.
	(htab_t loc_hash): Likewise.
	(htab_t ptr_hash): Likewise.
	(call_count): Rename ggc_call_count.
	(call_alloc): Rename ggc_call_alloc.
	(loc_descriptor): Rename make_loc_descriptor.
	(add_statistics): Rename ggc_add_statistics.

	* Makefile.in: Update to changes above.

Index: gcc/hash-table.h
===================================================================
--- gcc/hash-table.h	(revision 193902)
+++ gcc/hash-table.h	(working copy)
@@ -380,19 +380,19 @@ public:
   void create (size_t initial_slots);
   bool is_created ();
   void dispose ();
-  value_type *find (const compare_type *comparable);
+  value_type *find (const value_type *value);
   value_type *find_with_hash (const compare_type *comparable, hashval_t hash);
-  value_type **find_slot (const compare_type *comparable,
-			  enum insert_option insert);
+  value_type **find_slot (const value_type *value, enum insert_option insert);
   value_type **find_slot_with_hash (const compare_type *comparable,
 				    hashval_t hash, enum insert_option insert);
   void empty ();
   void clear_slot (value_type **slot);
-  void remove_elt (const compare_type *comparable);
+  void remove_elt (const value_type *value);
   void remove_elt_with_hash (const compare_type *comparable, hashval_t hash);
-  size_t size();
-  size_t elements();
-  double collisions();
+  size_t size ();
+  size_t elements ();
+  size_t elements_with_deleted ();
+  double collisions ();

   template <typename Argument,
 	    int (*Callback) (value_type **slot, Argument argument)>
@@ -431,9 +431,9 @@ hash_table <Descriptor, Allocator>::is_c
 template <typename Descriptor,
 	  template <typename Type> class Allocator>
 inline typename Descriptor::value_type *
-hash_table <Descriptor, Allocator>::find (const compare_type *comparable)
+hash_table <Descriptor, Allocator>::find (const value_type *value)
 {
-  return find_with_hash (comparable, Descriptor::hash (comparable));
+  return find_with_hash (value, Descriptor::hash (value));
 }


@@ -443,9 +443,9 @@ template <typename Descriptor,
 	  template <typename Type> class Allocator>
 inline typename Descriptor::value_type **
 hash_table <Descriptor, Allocator>
-::find_slot (const compare_type *comparable, enum insert_option insert)
+::find_slot (const value_type *value, enum insert_option insert)
 {
-  return find_slot_with_hash (comparable, Descriptor::hash
(comparable), insert);
+  return find_slot_with_hash (value, Descriptor::hash (value), insert);
 }


@@ -454,9 +454,9 @@ hash_table <Descriptor, Allocator>
 template <typename Descriptor,
 	  template <typename Type> class Allocator>
 inline void
-hash_table <Descriptor, Allocator>::remove_elt (const compare_type *comparable)
+hash_table <Descriptor, Allocator>::remove_elt (const value_type *value)
 {
-  remove_elt_with_hash (comparable, Descriptor::hash (comparable));
+  remove_elt_with_hash (value, Descriptor::hash (value));
 }


@@ -476,12 +476,23 @@ hash_table <Descriptor, Allocator>::size
 template <typename Descriptor,
 	  template <typename Type> class Allocator>
 inline size_t
-hash_table <Descriptor, Allocator>::elements()
+hash_table <Descriptor, Allocator>::elements ()
 {
   return htab->n_elements - htab->n_deleted;
 }


+/* Return the current number of elements in this hash table. */
+
+template <typename Descriptor,
+	  template <typename Type> class Allocator>
+inline size_t
+hash_table <Descriptor, Allocator>::elements_with_deleted ()
+{
+  return htab->n_elements;
+}
+
+
   /* Return the fraction of fixed collisions during all work with given
      hash table. */

Index: gcc/ggc-common.c
===================================================================
--- gcc/ggc-common.c	(revision 193902)
+++ gcc/ggc-common.c	(working copy)
@@ -24,7 +24,7 @@ along with GCC; see the file COPYING3.
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "ggc.h"
 #include "ggc-internal.h"
 #include "diagnostic-core.h"
@@ -47,10 +47,6 @@ static ggc_statistics *ggc_stats;
 struct traversal_state;

 static int ggc_htab_delete (void **, void *);
-static hashval_t saving_htab_hash (const void *);
-static int saving_htab_eq (const void *, const void *);
-static int call_count (void **, void *);
-static int call_alloc (void **, void *);
 static int compare_ptr_data (const void *, const void *);
 static void relocate_ptrs (void *, void *);
 static void write_pch_globals (const struct ggc_root_tab * const *tab,
@@ -291,8 +287,6 @@ ggc_print_common_statistics (FILE *strea
 
 /* Functions for saving and restoring GCable memory to disk.  */

-static htab_t saving_htab;
-
 struct ptr_data
 {
   void *obj;
@@ -306,6 +300,30 @@ struct ptr_data

 #define POINTER_HASH(x) (hashval_t)((long)x >> 3)

+/* Helper for hashing saving_htab.  */
+
+struct saving_hasher : typed_free_remove <ptr_data>
+{
+  typedef ptr_data value_type;
+  typedef void compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+saving_hasher::hash (const value_type *p)
+{
+  return POINTER_HASH (p->obj);
+}
+
+inline bool
+saving_hasher::equal (const value_type *p1, const compare_type *p2)
+{
+  return p1->obj == p2;
+}
+
+static hash_table <saving_hasher> saving_htab;
+
 /* Register an object in the hash table.  */

 int
@@ -319,8 +337,7 @@ gt_pch_note_object (void *obj, void *not
     return 0;

   slot = (struct ptr_data **)
-    htab_find_slot_with_hash (saving_htab, obj, POINTER_HASH (obj),
-			      INSERT);
+    saving_htab.find_slot_with_hash (obj, POINTER_HASH (obj), INSERT);
   if (*slot != NULL)
     {
       gcc_assert ((*slot)->note_ptr_fn == note_ptr_fn
@@ -352,26 +369,12 @@ gt_pch_note_reorder (void *obj, void *no
     return;

   data = (struct ptr_data *)
-    htab_find_with_hash (saving_htab, obj, POINTER_HASH (obj));
+    saving_htab.find_with_hash (obj, POINTER_HASH (obj));
   gcc_assert (data && data->note_ptr_cookie == note_ptr_cookie);

   data->reorder_fn = reorder_fn;
 }

-/* Hash and equality functions for saving_htab, callbacks for htab_create.  */
-
-static hashval_t
-saving_htab_hash (const void *p)
-{
-  return POINTER_HASH (((const struct ptr_data *)p)->obj);
-}
-
-static int
-saving_htab_eq (const void *p1, const void *p2)
-{
-  return ((const struct ptr_data *)p1)->obj == p2;
-}
-
 /* Handy state for the traversal functions.  */

 struct traversal_state
@@ -385,11 +388,10 @@ struct traversal_state

 /* Callbacks for htab_traverse.  */

-static int
-call_count (void **slot, void *state_p)
+int
+ggc_call_count (ptr_data **slot, traversal_state *state)
 {
-  struct ptr_data *d = (struct ptr_data *)*slot;
-  struct traversal_state *state = (struct traversal_state *)state_p;
+  struct ptr_data *d = *slot;

   ggc_pch_count_object (state->d, d->obj, d->size,
 			d->note_ptr_fn == gt_pch_p_S,
@@ -398,11 +400,10 @@ call_count (void **slot, void *state_p)
   return 1;
 }

-static int
-call_alloc (void **slot, void *state_p)
+int
+ggc_call_alloc (ptr_data **slot, traversal_state *state)
 {
-  struct ptr_data *d = (struct ptr_data *)*slot;
-  struct traversal_state *state = (struct traversal_state *)state_p;
+  struct ptr_data *d = *slot;

   d->new_addr = ggc_pch_alloc_object (state->d, d->obj, d->size,
 				      d->note_ptr_fn == gt_pch_p_S,
@@ -436,7 +437,7 @@ relocate_ptrs (void *ptr_p, void *state_
     return;

   result = (struct ptr_data *)
-    htab_find_with_hash (saving_htab, *ptr, POINTER_HASH (*ptr));
+    saving_htab.find_with_hash (*ptr, POINTER_HASH (*ptr));
   gcc_assert (result);
   *ptr = result->new_addr;
 }
@@ -465,7 +466,7 @@ write_pch_globals (const struct ggc_root
 	  else
 	    {
 	      new_ptr = (struct ptr_data *)
-		htab_find_with_hash (saving_htab, ptr, POINTER_HASH (ptr));
+		saving_htab.find_with_hash (ptr, POINTER_HASH (ptr));
 	      if (fwrite (&new_ptr->new_addr, sizeof (void *), 1, state->f)
 		  != 1)
 		fatal_error ("can%'t write PCH file: %m");
@@ -499,7 +500,7 @@ gt_pch_save (FILE *f)
   gt_pch_save_stringpool ();

   timevar_push (TV_PCH_PTR_REALLOC);
-  saving_htab = htab_create (50000, saving_htab_hash, saving_htab_eq, free);
+  saving_htab.create (50000);

   for (rt = gt_ggc_rtab; *rt; rt++)
     for (rti = *rt; rti->base != NULL; rti++)
@@ -515,7 +516,7 @@ gt_pch_save (FILE *f)
   state.f = f;
   state.d = init_ggc_pch ();
   state.count = 0;
-  htab_traverse (saving_htab, call_count, &state);
+  saving_htab.traverse <traversal_state *, ggc_call_count> (&state);

   mmi.size = ggc_pch_total_size (state.d);

@@ -531,7 +532,7 @@ gt_pch_save (FILE *f)
   state.ptrs = XNEWVEC (struct ptr_data *, state.count);
   state.ptrs_i = 0;

-  htab_traverse (saving_htab, call_alloc, &state);
+  saving_htab.traverse <traversal_state *, ggc_call_alloc> (&state);
   timevar_pop (TV_PCH_PTR_REALLOC);

   timevar_push (TV_PCH_PTR_SORT);
@@ -594,7 +595,7 @@ gt_pch_save (FILE *f)
   gt_pch_fixup_stringpool ();

   free (state.ptrs);
-  htab_delete (saving_htab);
+  saving_htab.dispose ();
 }

 /* Read the state of the compiler back in from F.  */
@@ -854,30 +855,32 @@ struct loc_descriptor
   size_t collected;
 };

-/* Hashtable used for statistics.  */
-static htab_t loc_hash;
+/* Hash table helper.  */

-/* Hash table helpers functions.  */
-static hashval_t
-hash_descriptor (const void *p)
+struct loc_desc_hasher : typed_noop_remove <loc_descriptor>
 {
-  const struct loc_descriptor *const d = (const struct loc_descriptor *) p;
+  typedef loc_descriptor value_type;
+  typedef loc_descriptor compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};

+inline hashval_t
+loc_desc_hasher::hash (const value_type *d)
+{
   return htab_hash_pointer (d->function) | d->line;
 }

-static int
-eq_descriptor (const void *p1, const void *p2)
+inline bool
+loc_desc_hasher::equal (const value_type *d, const compare_type *d2)
 {
-  const struct loc_descriptor *const d = (const struct loc_descriptor *) p1;
-  const struct loc_descriptor *const d2 = (const struct loc_descriptor *) p2;
-
   return (d->file == d2->file && d->line == d2->line
 	  && d->function == d2->function);
 }

-/* Hashtable converting address of allocated field to loc descriptor.  */
-static htab_t ptr_hash;
+/* Hashtable used for statistics.  */
+static hash_table <loc_desc_hasher> loc_hash;
+
 struct ptr_hash_entry
 {
   void *ptr;
@@ -885,26 +888,34 @@ struct ptr_hash_entry
   size_t size;
 };

-/* Hash table helpers functions.  */
-static hashval_t
-hash_ptr (const void *p)
+/* Helper for ptr_hash table.  */
+
+struct ptr_hash_hasher : typed_noop_remove <ptr_hash_entry>
 {
-  const struct ptr_hash_entry *const d = (const struct ptr_hash_entry *) p;
+  typedef ptr_hash_entry value_type;
+  typedef void compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};

+inline hashval_t
+ptr_hash_hasher::hash (const value_type *d)
+{
   return htab_hash_pointer (d->ptr);
 }

-static int
-eq_ptr (const void *p1, const void *p2)
+inline bool
+ptr_hash_hasher::equal (const value_type *p, const compare_type *p2)
 {
-  const struct ptr_hash_entry *const p = (const struct ptr_hash_entry *) p1;
-
   return (p->ptr == p2);
 }

+/* Hashtable converting address of allocated field to loc descriptor.  */
+static hash_table <ptr_hash_hasher> ptr_hash;
+
 /* Return descriptor for given call site, create new one if needed.  */
 static struct loc_descriptor *
-loc_descriptor (const char *name, int line, const char *function)
+make_loc_descriptor (const char *name, int line, const char *function)
 {
   struct loc_descriptor loc;
   struct loc_descriptor **slot;
@@ -912,10 +923,10 @@ loc_descriptor (const char *name, int li
   loc.file = name;
   loc.line = line;
   loc.function = function;
-  if (!loc_hash)
-    loc_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
+  if (!loc_hash.is_created ())
+    loc_hash.create (10);

-  slot = (struct loc_descriptor **) htab_find_slot (loc_hash, &loc, INSERT);
+  slot = loc_hash.find_slot (&loc, INSERT);
   if (*slot)
     return *slot;
   *slot = XCNEW (struct loc_descriptor);
@@ -930,16 +941,16 @@ void
 ggc_record_overhead (size_t allocated, size_t overhead, void *ptr,
 		     const char *name, int line, const char *function)
 {
-  struct loc_descriptor *loc = loc_descriptor (name, line, function);
+  struct loc_descriptor *loc = make_loc_descriptor (name, line, function);
   struct ptr_hash_entry *p = XNEW (struct ptr_hash_entry);
-  PTR *slot;
+  ptr_hash_entry **slot;

   p->ptr = ptr;
   p->loc = loc;
   p->size = allocated + overhead;
-  if (!ptr_hash)
-    ptr_hash = htab_create (10, hash_ptr, eq_ptr, NULL);
-  slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer
(ptr), INSERT);
+  if (!ptr_hash.is_created ())
+    ptr_hash.create (10);
+  slot = ptr_hash.find_slot_with_hash (ptr, htab_hash_pointer (ptr), INSERT);
   gcc_assert (!*slot);
   *slot = p;

@@ -950,14 +961,14 @@ ggc_record_overhead (size_t allocated, s

 /* Helper function for prune_overhead_list.  See if SLOT is still marked and
    remove it from hashtable if it is not.  */
-static int
-ggc_prune_ptr (void **slot, void *b ATTRIBUTE_UNUSED)
+int
+ggc_prune_ptr (ptr_hash_entry **slot, void *b ATTRIBUTE_UNUSED)
 {
-  struct ptr_hash_entry *p = (struct ptr_hash_entry *) *slot;
+  struct ptr_hash_entry *p = *slot;
   if (!ggc_marked_p (p->ptr))
     {
       p->loc->collected += p->size;
-      htab_clear_slot (ptr_hash, slot);
+      ptr_hash.clear_slot (slot);
       free (p);
     }
   return 1;
@@ -968,15 +979,15 @@ ggc_prune_ptr (void **slot, void *b ATTR
 void
 ggc_prune_overhead_list (void)
 {
-  htab_traverse (ptr_hash, ggc_prune_ptr, NULL);
+  ptr_hash.traverse <void *, ggc_prune_ptr> (NULL);
 }

 /* Notice that the pointer has been freed.  */
 void
 ggc_free_overhead (void *ptr)
 {
-  PTR *slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer (ptr),
-					NO_INSERT);
+  ptr_hash_entry **slot;
+  slot = ptr_hash.find_slot_with_hash (ptr, htab_hash_pointer (ptr),
NO_INSERT);
   struct ptr_hash_entry *p;
   /* The pointer might be not found if a PCH read happened between allocation
      and ggc_free () call.  FIXME: account memory properly in the presence of
@@ -985,7 +996,7 @@ ggc_free_overhead (void *ptr)
       return;
   p = (struct ptr_hash_entry *) *slot;
   p->loc->freed += p->size;
-  htab_clear_slot (ptr_hash, slot);
+  ptr_hash.clear_slot (slot);
   free (p);
 }

@@ -1024,11 +1035,10 @@ cmp_statistic (const void *loc1, const v

 /* Collect array of the descriptors from hashtable.  */
 static struct loc_descriptor **loc_array;
-static int
-add_statistics (void **slot, void *b)
+int
+ggc_add_statistics (loc_descriptor **slot, int *n)
 {
-  int *n = (int *)b;
-  loc_array[*n] = (struct loc_descriptor *) *slot;
+  loc_array[*n] = *slot;
   (*n)++;
   return 1;
 }
@@ -1049,12 +1059,13 @@ dump_ggc_loc_statistics (bool final)
   ggc_force_collect = true;
   ggc_collect ();

-  loc_array = XCNEWVEC (struct loc_descriptor *, loc_hash->n_elements);
+  loc_array = XCNEWVEC (struct loc_descriptor *,
+			loc_hash.elements_with_deleted ());
   fprintf (stderr,
"-------------------------------------------------------\n");
   fprintf (stderr, "\n%-48s %10s       %10s       %10s       %10s
  %10s\n",
 	   "source location", "Garbage", "Freed", "Leak", "Overhead", "Times");
   fprintf (stderr,
"-------------------------------------------------------\n");
-  htab_traverse (loc_hash, add_statistics, &nentries);
+  loc_hash.traverse <int *, ggc_add_statistics> (&nentries);
   qsort (loc_array, nentries, sizeof (*loc_array),
 	 final ? final_cmp_statistic : cmp_statistic);
   for (i = 0; i < nentries; i++)
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 193902)
+++ gcc/Makefile.in	(working copy)
@@ -2108,7 +2108,7 @@ trans-mem.o : trans-mem.c $(CONFIG_H) $(
 	gt-trans-mem.h

 ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h		\
-	$(GGC_H) $(HASHTAB_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) hosthooks.h	\
+	$(GGC_H) $(HASH_TABLE_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) hosthooks.h \
 	$(HOSTHOOKS_DEF_H) $(VEC_H) $(PLUGIN_H) $(GGC_INTERNAL_H) $(TIMEVAR_H)

 ggc-page.o: ggc-page.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
