diff mbox

[cxx-conversion] various hash tables, part 1/2

Message ID CAGqM8fbWKr4wpVWzvZBR8baZbGtnKgjnntgjHzrrOvXOk6B34A@mail.gmail.com
State New
Headers show

Commit Message

Lawrence Crowl Dec. 2, 2012, 1:47 a.m. UTC
Change various hash tables from htab_t to hash_table.
Each file is independent.

attribs.c scoped_attributes::attribute_hash
bitmap.c bitmap_desc_hash
dwarf2cfi.c trace_index
dwarf2out.c break_out_includes::cu_hash_table
dwarf2out.c copy_decls_for_unworthy_types::decl_table
dwarf2out.c optimize_external_refs::map
dwarf2out.c output_comp_unit::extern_map
dwarf2out.c output_comdat_type_unit::extern_map
dwarf2out.c output_macinfo::macinfo_htab
dwarf2out.c optimize_location_lists::htab
dwarf2out.c dwarf2out_finish::comdat_type_table
except.c ehspec_hash_type
except.c assign_filter_values::ttypes
except.c assign_filter_values::ehspec
except.c sjlj_assign_call_site_values::ar_hash
except.c convert_to_eh_region_ranges::ar_hash
trans-mem.c tm_new_mem_hash
tree-browser.c TB_up_ht
tree-eh.c finally_tree

Move the declaration of hash_table <alloc_pool_hasher> alloc_pool_hash
in alloc-pool.c to after the method definitions for its parameter
class.


Tested on x86-64.

Okay for branch?


 tree-ssa-loop.o : tree-ssa-loop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
@@ -2534,7 +2534,7 @@ omp-low.o : omp-low.c $(CONFIG_H) $(SYST
    $(TREE_PASS_H) $(GGC_H) $(EXCEPT_H) $(SPLAY_TREE_H) $(OPTABS_H) \
    $(CFGLOOP_H) tree-iterator.h gt-omp-low.h
 tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
-   coretypes.h $(TREE_H) $(TREE_PRETTY_PRINT_H)
+   coretypes.h $(HASH_TABLE_H) $(TREE_H) $(TREE_PRETTY_PRINT_H)
 omega.o : omega.c $(OMEGA_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h \
    $(TREE_H) $(DIAGNOSTIC_CORE_H)
 tree-chrec.o : tree-chrec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h \
@@ -2761,7 +2761,8 @@ stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H)
 except.o : except.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(TREE_H) $(FLAGS_H) $(EXCEPT_H) $(FUNCTION_H) $(EXPR_H) $(LIBFUNCS_H) \
    langhooks.h insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
-   dwarf2asm.h $(DWARF2OUT_H) toplev.h $(DIAGNOSTIC_CORE_H)
$(HASHTAB_H) intl.h $(GGC_H) \
+   dwarf2asm.h $(DWARF2OUT_H) toplev.h $(DIAGNOSTIC_CORE_H) $(HASH_TABLE_H) \
+   intl.h $(GGC_H) \
    gt-except.h $(CGRAPH_H) $(DIAGNOSTIC_H) $(DWARF2_H) \
    $(TARGET_H) $(TM_P_H) $(TREE_PASS_H) $(TREE_FLOW_H) \
    $(TREE_PRETTY_PRINT_H) sbitmap.h $(COMMON_TARGET_H) $(CFGLOOP_H)
@@ -2815,12 +2816,12 @@ dwarf2out.o : dwarf2out.c $(CONFIG_H) $(
    $(TM_H) $(TREE_H) version.h $(RTL_H) $(DWARF2_H) debug.h $(FLAGS_H) \
    insn-config.h output.h $(DIAGNOSTIC_H) hard-reg-set.h $(REGS_H) $(EXPR_H) \
    toplev.h $(DIAGNOSTIC_CORE_H) $(DWARF2OUT_H) reload.h \
-   $(GGC_H) $(EXCEPT_H) dwarf2asm.h $(TM_P_H) langhooks.h $(HASHTAB_H) \
+   $(GGC_H) $(EXCEPT_H) dwarf2asm.h $(TM_P_H) langhooks.h $(HASH_TABLE_H) \
    gt-dwarf2out.h $(TARGET_H) $(CGRAPH_H) $(MD5_H) $(INPUT_H) $(FUNCTION_H) \
    $(GIMPLE_H) ira.h lra.h $(TREE_FLOW_H) \
    $(TREE_PRETTY_PRINT_H) $(COMMON_TARGET_H) $(OPTS_H)
-dwarf2cfi.o : dwarf2cfi.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
-   version.h $(RTL_H) $(EXPR_H) $(REGS_H) $(FUNCTION_H) output.h \
+dwarf2cfi.o : dwarf2cfi.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(HASH_TABLE_H) \
+   $(TM_H) version.h $(RTL_H) $(EXPR_H) $(REGS_H) $(FUNCTION_H) output.h \
    gt-dwarf2cfi.h debug.h $(DWARF2_H) dwarf2asm.h $(DWARF2OUT_H)
$(COMMON_TARGET_H) \
    $(GGC_H) $(TM_P_H) $(TARGET_H) $(TREE_PASS_H) $(BASIC_BLOCK_H) $(EXCEPT_H)
 dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
@@ -3089,7 +3090,7 @@ value-prof.o : value-prof.c $(CONFIG_H)
 loop-doloop.o : loop-doloop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h
dumpfile.h $(TM_H) \
    $(RTL_H) $(FLAGS_H) $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TM_P_H) \
    $(DIAGNOSTIC_CORE_H) $(CFGLOOP_H) $(PARAMS_H) $(TARGET_H)
-alloc-pool.o : alloc-pool.c $(CONFIG_H) $(SYSTEM_H) alloc-pool.h $(HASHTAB_H)
+alloc-pool.o : alloc-pool.c $(CONFIG_H) $(SYSTEM_H) alloc-pool.h
$(HASH_TABLE_H)
 auto-inc-dec.o : auto-inc-dec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) $(RTL_H) $(TM_P_H) hard-reg-set.h $(BASIC_BLOCK_H) insn-config.h \
    $(REGS_H) $(FLAGS_H) $(FUNCTION_H) $(EXCEPT_H)
$(DIAGNOSTIC_CORE_H) $(RECOG_H) \
@@ -3171,7 +3172,7 @@ reginfo.o : reginfo.c $(CONFIG_H) $(SYST
    $(FUNCTION_H) output.h $(TM_P_H) $(EXPR_H) $(HASHTAB_H) \
    $(TARGET_H) $(TREE_PASS_H) $(DF_H) ira.h
 bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM_H)  coretypes.h \
-   $(GGC_H) gt-bitmap.h $(BITMAP_H) $(OBSTACK_H) $(HASHTAB_H)
+   $(GGC_H) gt-bitmap.h $(BITMAP_H) $(OBSTACK_H) $(HASH_TABLE_H)
 vec.o : vec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(VEC_H) $(GGC_H) \
    $(DIAGNOSTIC_CORE_H) $(HASHTAB_H)
 hash-table.o : hash-table.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \

Comments

Diego Novillo Dec. 3, 2012, 7:15 p.m. UTC | #1
On Sat, Dec 1, 2012 at 8:47 PM, Lawrence Crowl <crowl@googlers.com> wrote:

> +inline bool
> +attribute_hasher::equal (const value_type *spec, const compare_type *str)
> +{
> +  return (!strncmp (spec->name, str->str, str->length)

I have a slight preference for strncmp() == 0.  It's easier to read (I
realize that you are just cut-n-pasting old code here :)

> @@ -76,13 +82,11 @@ bitmap_descriptor (const char *file, int
>    loc.function = function;
>    loc.line = line;
>
> -  if (!bitmap_desc_hash)
> -    bitmap_desc_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
> +  if (!bitmap_desc_hash.is_created ())
> +    bitmap_desc_hash.create (10);
>
> -  slot = (struct bitmap_descriptor **)
> -    htab_find_slot_with_hash (bitmap_desc_hash, &loc,
> -                             htab_hash_pointer (file) + line,
> -                             INSERT);
> +  slot = bitmap_desc_hash
> +        .find_slot_with_hash (&loc, htab_hash_pointer (file) + line, INSERT);

I'd rather split the argument list here.

>  }
>
> -static int
> -htab_cu_eq (const void *of1, const void *of2)
> +inline bool
> +cu_hash_table_entry_hasher::equal (const value_type *entry1,
> +                                  const compare_type *entry2)

No static?


> -static hashval_t
> -ttypes_filter_hash (const void *pentry)
> +inline hashval_t
> +ttypes_filter_hasher::hash (const value_type *entry)
>  {
> -  const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
>    return TREE_HASH (entry->t);

The patch seems to have changed the types here.  Is it value_type or
ttypes_filter?

Looks OK otherwise.


Diego.
Lawrence Crowl Dec. 3, 2012, 7:24 p.m. UTC | #2
On 12/3/12, Diego Novillo <dnovillo@google.com> wrote:
> On Sat, Dec 1, 2012 at 8:47 PM, Lawrence Crowl <crowl@googlers.com> wrote:
>
>> +inline bool
>> +attribute_hasher::equal (const value_type *spec, const compare_type
>> *str)
>> +{
>> +  return (!strncmp (spec->name, str->str, str->length)
>
> I have a slight preference for strncmp() == 0.  It's easier to read (I
> realize that you are just cut-n-pasting old code here :)

Done.

>> @@ -76,13 +82,11 @@ bitmap_descriptor (const char *file, int
>>    loc.function = function;
>>    loc.line = line;
>>
>> -  if (!bitmap_desc_hash)
>> -    bitmap_desc_hash = htab_create (10, hash_descriptor, eq_descriptor,
>> NULL);
>> +  if (!bitmap_desc_hash.is_created ())
>> +    bitmap_desc_hash.create (10);
>>
>> -  slot = (struct bitmap_descriptor **)
>> -    htab_find_slot_with_hash (bitmap_desc_hash, &loc,
>> -                             htab_hash_pointer (file) + line,
>> -                             INSERT);
>> +  slot = bitmap_desc_hash
>> +        .find_slot_with_hash (&loc, htab_hash_pointer (file) + line,
>> INSERT);
>
> I'd rather split the argument list here.

Done, though it becomes three lines instead of two.

>
>>  }
>>
>> -static int
>> -htab_cu_eq (const void *of1, const void *of2)
>> +inline bool
>> +cu_hash_table_entry_hasher::equal (const value_type *entry1,
>> +                                  const compare_type *entry2)
>
> No static?

The in-class declaration has the static keyword.  (It's still a
global symbol though, not local.)

>> -static hashval_t
>> -ttypes_filter_hash (const void *pentry)
>> +inline hashval_t
>> +ttypes_filter_hasher::hash (const value_type *entry)
>>  {
>> -  const struct ttypes_filter *entry = (const struct ttypes_filter *)
>> pentry;
>>    return TREE_HASH (entry->t);
>
> The patch seems to have changed the types here.  Is it value_type or
> ttypes_filter?

The hasher class defines value_type as a typedef to ttypes_filter.
There has been no change in actual type.

> Looks OK otherwise.

Okay, I'll put it in the commit queue.
Diego Novillo Dec. 3, 2012, 7:27 p.m. UTC | #3
On 2012-12-03 14:24 , Lawrence Crowl wrote:

>>
>>>   }
>>>
>>> -static int
>>> -htab_cu_eq (const void *of1, const void *of2)
>>> +inline bool
>>> +cu_hash_table_entry_hasher::equal (const value_type *entry1,
>>> +                                  const compare_type *entry2)
>>
>> No static?
>
> The in-class declaration has the static keyword.  (It's still a
> global symbol though, not local.)

Ah, right.  I've seen other cases where the patch removes the 'static' 
qualifier in free functions, though (in the second patch too).  Did you 
need to make those functions externally available?



Diego.
Lawrence Crowl Dec. 3, 2012, 7:50 p.m. UTC | #4
On 12/3/12, Diego Novillo <dnovillo@google.com> wrote:
> On 2012-12-03 14:24 , Lawrence Crowl wrote:
>>>> -static int
>>>> -htab_cu_eq (const void *of1, const void *of2)
>>>> +inline bool
>>>> +cu_hash_table_entry_hasher::equal (const value_type *entry1,
>>>> +                                  const compare_type *entry2)
>>>
>>> No static?
>>
>> The in-class declaration has the static keyword.  (It's still a
>> global symbol though, not local.)
>
> Ah, right.  I've seen other cases where the patch removes the
> 'static' qualifier in free functions, though (in the second patch
> too).  Did you need to make those functions externally available?

In C++03, any function argument to a template needs to be externally
available.  These functions are parameters to the traverse templates.
Diego Novillo Dec. 3, 2012, 7:55 p.m. UTC | #5
On Mon, Dec 3, 2012 at 2:50 PM, Lawrence Crowl <crowl@googlers.com> wrote:
> On 12/3/12, Diego Novillo <dnovillo@google.com> wrote:
>> On 2012-12-03 14:24 , Lawrence Crowl wrote:
>>>>> -static int
>>>>> -htab_cu_eq (const void *of1, const void *of2)
>>>>> +inline bool
>>>>> +cu_hash_table_entry_hasher::equal (const value_type *entry1,
>>>>> +                                  const compare_type *entry2)
>>>>
>>>> No static?
>>>
>>> The in-class declaration has the static keyword.  (It's still a
>>> global symbol though, not local.)
>>
>> Ah, right.  I've seen other cases where the patch removes the
>> 'static' qualifier in free functions, though (in the second patch
>> too).  Did you need to make those functions externally available?
>
> In C++03, any function argument to a template needs to be externally
> available.  These functions are parameters to the traverse templates.

Oh, right.  Ignore all my other static-related comments then.


Diego.
diff mbox

Patch

Index: gcc/ChangeLog

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

	* alloc-pool.c (static hash_table <alloc_pool_hasher> alloc_pool_hash):
	Move declaration to after the type's method definitons.

	* attribs.c (htab_t scoped_attributes::attribute_hash):
	Change type to hash_table.  Update dependent calls and types.

	* bitmap.c (htab_t bitmap_desc_hash):
	Change type to hash_table.  Update dependent calls and types.

	* dwarf2cfi.c (htab_t trace_index):
	Change type to hash_table.  Update dependent calls and types.

	* dwarf2out.c (htab_t break_out_includes::cu_hash_table):
	Change type to hash_table.  Update dependent calls and types.
	(htab_t copy_decls_for_unworthy_types::decl_table): Likewise.
	(htab_t optimize_external_refs::map): Likewise.
	(htab_t output_comp_unit::extern_map): Likewise.
	(htab_t output_comdat_type_unit::extern_map): Likewise.
	(htab_t output_macinfo::macinfo_htab): Likewise.
	(htab_t optimize_location_lists::htab): Likewise.
	(htab_t dwarf2out_finish::comdat_type_table): Likewise.

	* except.c (htab_t ehspec_hash_type):
	Change type to hash_table.  Update dependent calls and types.
	(assign_filter_values::ttypes): Likewise.
	(assign_filter_values::ehspec): Likewise.
	(sjlj_assign_call_site_values::ar_hash): Likewise.
	(convert_to_eh_region_ranges::ar_hash): Likewise.

	* trans-mem.c (htab_t tm_new_mem_hash):
	Change type to hash_table.  Update dependent calls and types.

	* tree-browser.c (htab_t TB_up_ht):
	Change type to hash_table.  Update dependent calls and types.

	* tree-eh.c (htab_t finally_tree):
	Change type to hash_table.  Update dependent calls and types.

	* Makefile.in: Update to changes above.

Index: gcc/attribs.c
===================================================================
--- gcc/attribs.c	(revision 193902)
+++ gcc/attribs.c	(working copy)
@@ -31,7 +31,7 @@  along with GCC; see the file COPYING3.
 #include "cpplib.h"
 #include "target.h"
 #include "langhooks.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "plugin.h"

 /* Table of the tables of attributes (common, language, format, machine)
@@ -46,13 +46,45 @@  struct substring
   int length;
 };

+/* Simple hash function to avoid need to scan whole string.  */
+
+static inline hashval_t
+substring_hash (const char *str, int l)
+{
+  return str[0] + str[l - 1] * 256 + l * 65536;
+}
+
+/* Used for attribute_hash.  */
+
+struct attribute_hasher : typed_noop_remove <attribute_spec>
+{
+  typedef attribute_spec value_type;
+  typedef substring compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+attribute_hasher::hash (const value_type *spec)
+{
+  const int l = strlen (spec->name);
+  return substring_hash (spec->name, l);
+}
+
+inline bool
+attribute_hasher::equal (const value_type *spec, const compare_type *str)
+{
+  return (!strncmp (spec->name, str->str, str->length)
+	  && !spec->name[str->length]);
+}
+
 /* Scoped attribute name representation.  */

 struct scoped_attributes
 {
   const char *ns;
   vec<attribute_spec> attributes;
-  htab_t attribute_hash;
+  hash_table <attribute_hasher> attribute_hash;
 };

 /* The table of scope attributes.  */
@@ -85,36 +117,6 @@  extract_attribute_substring (struct subs
     }
 }

-/* Simple hash function to avoid need to scan whole string.  */
-
-static inline hashval_t
-substring_hash (const char *str, int l)
-{
-  return str[0] + str[l - 1] * 256 + l * 65536;
-}
-
-/* Used for attribute_hash.  */
-
-static hashval_t
-hash_attr (const void *p)
-{
-  const struct attribute_spec *const spec = (const struct attribute_spec *) p;
-  const int l = strlen (spec->name);
-
-  return substring_hash (spec->name, l);
-}
-
-/* Used for attribute_hash.  */
-
-static int
-eq_attr (const void *p, const void *q)
-{
-  const struct attribute_spec *const spec = (const struct attribute_spec *) p;
-  const struct substring *const str = (const struct substring *) q;
-
-  return (!strncmp (spec->name, str->str, str->length) &&
!spec->name[str->length]);
-}
-
 /* Insert an array of attributes ATTRIBUTES into a namespace.  This
    array must be NULL terminated.  NS is the name of attribute
    namespace.  The function returns the namespace into which the
@@ -141,7 +143,7 @@  register_scoped_attributes (const struct
       sa.ns = ns;
       sa.attributes.create (64);
       result = attributes_table.safe_push (sa);
-      result->attribute_hash = htab_create (200, hash_attr, eq_attr, NULL);
+      result->attribute_hash.create (200);
     }

   /* Really add the attributes to their namespace now.  */
@@ -274,11 +276,11 @@  register_scoped_attribute (const struct
 			   scoped_attributes *name_space)
 {
   struct substring str;
-  void **slot;
+  attribute_spec **slot;

   gcc_assert (attr != NULL && name_space != NULL);

-  gcc_assert (name_space->attribute_hash != NULL);
+  gcc_assert (name_space->attribute_hash.is_created ());

   str.str = attr->name;
   str.length = strlen (str.str);
@@ -287,11 +289,11 @@  register_scoped_attribute (const struct
      in the form '__text__'.  */
   gcc_assert (str.length > 0 && str.str[0] != '_');

-  slot = htab_find_slot_with_hash (name_space->attribute_hash, &str,
-				   substring_hash (str.str, str.length),
-				   INSERT);
+  slot = name_space->attribute_hash
+	 .find_slot_with_hash (&str, substring_hash (str.str, str.length),
+			       INSERT);
   gcc_assert (!*slot || attr->name[0] == '*');
-  *slot = (void *) CONST_CAST (struct attribute_spec *, attr);
+  *slot = CONST_CAST (struct attribute_spec *, attr);
 }

 /* Return the spec for the scoped attribute with namespace NS and
@@ -313,8 +315,7 @@  lookup_scoped_attribute_spec (const_tree
   attr.str = IDENTIFIER_POINTER (name);
   attr.length = IDENTIFIER_LENGTH (name);
   extract_attribute_substring (&attr);
-  return (const struct attribute_spec *)
-    htab_find_with_hash (attrs->attribute_hash, &attr,
+  return attrs->attribute_hash.find_with_hash (&attr,
 			 substring_hash (attr.str, attr.length));
 }

Index: gcc/bitmap.c
===================================================================
--- gcc/bitmap.c	(revision 193902)
+++ gcc/bitmap.c	(working copy)
@@ -23,7 +23,7 @@  along with GCC; see the file COPYING3.
 #include "obstack.h"
 #include "ggc.h"
 #include "bitmap.h"
-#include "hashtab.h"
+#include "hash-table.h"

 /* Store information about each particular bitmap.  */
 struct bitmap_descriptor
@@ -39,35 +39,41 @@  struct bitmap_descriptor
   int search_iter;
 };

-/* Hashtable mapping bitmap names to descriptors.  */
-static htab_t bitmap_desc_hash;
-
 /* Hashtable helpers.  */
-static hashval_t
-hash_descriptor (const void *p)
-{
-  const struct bitmap_descriptor *const d =
-    (const struct bitmap_descriptor *) p;
-  return htab_hash_pointer (d->file) + d->line;
-}
+
 struct loc
 {
   const char *file;
   const char *function;
   int line;
 };
-static int
-eq_descriptor (const void *p1, const void *p2)
+
+struct bitmap_desc_hasher : typed_noop_remove <bitmap_descriptor>
+{
+  typedef bitmap_descriptor value_type;
+  typedef loc compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+bitmap_desc_hasher::hash (const value_type *d)
+{
+  return htab_hash_pointer (d->file) + d->line;
+}
+
+inline bool
+bitmap_desc_hasher::equal (const value_type *d, const compare_type *l)
 {
-  const struct bitmap_descriptor *const d =
-    (const struct bitmap_descriptor *) p1;
-  const struct loc *const l = (const struct loc *) p2;
   return d->file == l->file && d->function == l->function && d->line
== l->line;
 }

+/* Hashtable mapping bitmap names to descriptors.  */
+static hash_table <bitmap_desc_hasher> bitmap_desc_hash;
+
 /* For given file and line, return descriptor, create new if needed.  */
 static struct bitmap_descriptor *
-bitmap_descriptor (const char *file, int line, const char *function)
+make_bitmap_descriptor (const char *file, int line, const char *function)
 {
   struct bitmap_descriptor **slot;
   struct loc loc;
@@ -76,13 +82,11 @@  bitmap_descriptor (const char *file, int
   loc.function = function;
   loc.line = line;

-  if (!bitmap_desc_hash)
-    bitmap_desc_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
+  if (!bitmap_desc_hash.is_created ())
+    bitmap_desc_hash.create (10);

-  slot = (struct bitmap_descriptor **)
-    htab_find_slot_with_hash (bitmap_desc_hash, &loc,
-			      htab_hash_pointer (file) + line,
-			      INSERT);
+  slot = bitmap_desc_hash
+	 .find_slot_with_hash (&loc, htab_hash_pointer (file) + line, INSERT);
   if (*slot)
     return *slot;
   *slot = XCNEW (struct bitmap_descriptor);
@@ -96,7 +100,7 @@  bitmap_descriptor (const char *file, int
 void
 bitmap_register (bitmap b MEM_STAT_DECL)
 {
-  b->desc = bitmap_descriptor (ALONE_FINAL_PASS_MEM_STAT);
+  b->desc = make_bitmap_descriptor (ALONE_FINAL_PASS_MEM_STAT);
   b->desc->created++;
 }

@@ -2122,13 +2126,12 @@  struct output_info
   int count;
 };

-/* Called via htab_traverse.  Output bitmap descriptor pointed out by SLOT
-   and update statistics.  */
-static int
-print_statistics (void **slot, void *b)
+/* Called via hash_table::traverse.  Output bitmap descriptor pointed out by
+   SLOT and update statistics.  */
+int
+print_statistics (bitmap_descriptor **slot, output_info *i)
 {
-  struct bitmap_descriptor *d = (struct bitmap_descriptor *) *slot;
-  struct output_info *i = (struct output_info *) b;
+  struct bitmap_descriptor *d = *slot;
   char s[4096];

   if (d->allocated)
@@ -2158,7 +2161,7 @@  dump_bitmap_statistics (void)
   if (! GATHER_STATISTICS)
     return;

-  if (!bitmap_desc_hash)
+  if (!bitmap_desc_hash.is_created ())
     return;

   fprintf (stderr, "\nBitmap                                     Overall "
@@ -2167,7 +2170,7 @@  dump_bitmap_statistics (void)
   fprintf (stderr,
"---------------------------------------------------------------------------------\n");
   info.count = 0;
   info.size = 0;
-  htab_traverse (bitmap_desc_hash, print_statistics, &info);
+  bitmap_desc_hash.traverse <output_info *, print_statistics> (&info);
   fprintf (stderr,
"---------------------------------------------------------------------------------\n");
   fprintf (stderr, "%-40s %9d %15"HOST_WIDEST_INT_PRINT"d\n",
 	   "Total", info.count, info.size);
Index: gcc/alloc-pool.c
===================================================================
--- gcc/alloc-pool.c	(revision 193902)
+++ gcc/alloc-pool.c	(working copy)
@@ -83,6 +83,7 @@  struct alloc_pool_descriptor
   int elt_size;
 };

+/* Hashtable helpers.  */
 struct alloc_pool_hasher : typed_noop_remove <alloc_pool_descriptor>
 {
   typedef alloc_pool_descriptor value_type;
@@ -91,10 +92,6 @@  struct alloc_pool_hasher : typed_noop_re
   static inline bool equal (const value_type *, const compare_type *);
 };

-/* Hashtable mapping alloc_pool names to descriptors.  */
-static hash_table <alloc_pool_hasher>  alloc_pool_hash;
-
-/* Hashtable helpers.  */
 inline hashval_t
 alloc_pool_hasher::hash (const value_type *d)
 {
@@ -108,6 +105,9 @@  alloc_pool_hasher::equal (const value_ty
   return d->name == p2;
 }

+/* Hashtable mapping alloc_pool names to descriptors.  */
+static hash_table <alloc_pool_hasher>  alloc_pool_hash;
+
 /* For given name, return descriptor, create new if needed.  */
 static struct alloc_pool_descriptor *
 allocate_pool_descriptor (const char *name)
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 193902)
+++ gcc/dwarf2out.c	(working copy)
@@ -86,7 +86,7 @@  along with GCC; see the file COPYING3.
 #include "target.h"
 #include "common/common-target.h"
 #include "langhooks.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "cgraph.h"
 #include "input.h"
 #include "gimple.h"
@@ -3016,17 +3016,9 @@  static dw_die_ref remove_child_or_replac
                                                          dw_die_ref,
                                                          dw_die_ref);
 static void break_out_comdat_types (dw_die_ref);
-static dw_die_ref copy_ancestor_tree (dw_die_ref, dw_die_ref, htab_t);
-static void copy_decls_walk (dw_die_ref, dw_die_ref, htab_t);
 static void copy_decls_for_unworthy_types (dw_die_ref);

-static hashval_t htab_cu_hash (const void *);
-static int htab_cu_eq (const void *, const void *);
-static void htab_cu_del (void *);
-static int check_duplicate_cu (dw_die_ref, htab_t, unsigned *);
-static void record_comdat_symbol_number (dw_die_ref, htab_t, unsigned);
 static void add_sibling_attributes (dw_die_ref);
-static void build_abbrev_table (dw_die_ref, htab_t);
 static void output_location_lists (dw_die_ref);
 static int constant_size (unsigned HOST_WIDE_INT);
 static unsigned long size_of_die (dw_die_ref);
@@ -6490,31 +6482,34 @@  struct cu_hash_table_entry
   struct cu_hash_table_entry *next;
 };

-/* Routines to manipulate hash table of CUs.  */
-static hashval_t
-htab_cu_hash (const void *of)
+/* Helpers to manipulate hash table of CUs.  */
+
+struct cu_hash_table_entry_hasher
 {
-  const struct cu_hash_table_entry *const entry =
-    (const struct cu_hash_table_entry *) of;
+  typedef cu_hash_table_entry value_type;
+  typedef die_struct compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+  static inline void remove (value_type *);
+};

+inline hashval_t
+cu_hash_table_entry_hasher::hash (const value_type *entry)
+{
   return htab_hash_string (entry->cu->die_id.die_symbol);
 }

-static int
-htab_cu_eq (const void *of1, const void *of2)
+inline bool
+cu_hash_table_entry_hasher::equal (const value_type *entry1,
+				   const compare_type *entry2)
 {
-  const struct cu_hash_table_entry *const entry1 =
-    (const struct cu_hash_table_entry *) of1;
-  const struct die_struct *const entry2 = (const struct die_struct *) of2;
-
   return !strcmp (entry1->cu->die_id.die_symbol, entry2->die_id.die_symbol);
 }

-static void
-htab_cu_del (void *what)
+inline void
+cu_hash_table_entry_hasher::remove (value_type *entry)
 {
-  struct cu_hash_table_entry *next,
-    *entry = (struct cu_hash_table_entry *) what;
+  struct cu_hash_table_entry *next;

   while (entry)
     {
@@ -6524,19 +6519,21 @@  htab_cu_del (void *what)
     }
 }

+typedef hash_table <cu_hash_table_entry_hasher> cu_hash_type;
+
 /* Check whether we have already seen this CU and set up SYM_NUM
    accordingly.  */
 static int
-check_duplicate_cu (dw_die_ref cu, htab_t htable, unsigned int *sym_num)
+check_duplicate_cu (dw_die_ref cu, cu_hash_type htable, unsigned int *sym_num)
 {
   struct cu_hash_table_entry dummy;
   struct cu_hash_table_entry **slot, *entry, *last = &dummy;

   dummy.max_comdat_num = 0;

-  slot = (struct cu_hash_table_entry **)
-    htab_find_slot_with_hash (htable, cu, htab_hash_string
(cu->die_id.die_symbol),
-	INSERT);
+  slot = htable.find_slot_with_hash (cu,
+				     htab_hash_string (cu->die_id.die_symbol),
+				     INSERT);
   entry = *slot;

   for (; entry; last = entry, entry = entry->next)
@@ -6562,13 +6559,14 @@  check_duplicate_cu (dw_die_ref cu, htab_

 /* Record SYM_NUM to record of CU in HTABLE.  */
 static void
-record_comdat_symbol_number (dw_die_ref cu, htab_t htable, unsigned
int sym_num)
+record_comdat_symbol_number (dw_die_ref cu, cu_hash_type htable,
+			     unsigned int sym_num)
 {
   struct cu_hash_table_entry **slot, *entry;

-  slot = (struct cu_hash_table_entry **)
-    htab_find_slot_with_hash (htable, cu, htab_hash_string
(cu->die_id.die_symbol),
-	NO_INSERT);
+  slot = htable.find_slot_with_hash (cu,
+				     htab_hash_string (cu->die_id.die_symbol),
+				     NO_INSERT);
   entry = *slot;

   entry->max_comdat_num = sym_num;
@@ -6584,7 +6582,7 @@  break_out_includes (dw_die_ref die)
   dw_die_ref c;
   dw_die_ref unit = NULL;
   limbo_die_node *node, **pnode;
-  htab_t cu_hash_table;
+  cu_hash_type cu_hash_table;

   c = die->die_child;
   if (c) do {
@@ -6617,7 +6615,7 @@  break_out_includes (dw_die_ref die)
 #endif

   assign_symbol_names (die);
-  cu_hash_table = htab_create (10, htab_cu_hash, htab_cu_eq, htab_cu_del);
+  cu_hash_table.create (10);
   for (node = limbo_die_list, pnode = &limbo_die_list;
        node;
        node = node->next)
@@ -6637,7 +6635,7 @@  break_out_includes (dw_die_ref die)
 		comdat_symbol_number);
 	}
     }
-  htab_delete (cu_hash_table);
+  cu_hash_table.dispose ();
 }

 /* Return non-zero if this DIE is a declaration.  */
@@ -6812,6 +6810,94 @@  clone_as_declaration (dw_die_ref die)
   return clone;
 }

+
+/* Structure to map a DIE in one CU to its copy in a comdat type unit.  */
+
+struct decl_table_entry
+{
+  dw_die_ref orig;
+  dw_die_ref copy;
+};
+
+/* Helpers to manipulate hash table of copied declarations.  */
+
+/* Hashtable helpers.  */
+
+struct decl_table_entry_hasher : typed_free_remove <decl_table_entry>
+{
+  typedef decl_table_entry value_type;
+  typedef die_struct compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+decl_table_entry_hasher::hash (const value_type *entry)
+{
+  return htab_hash_pointer (entry->orig);
+}
+
+inline bool
+decl_table_entry_hasher::equal (const value_type *entry1,
+				const compare_type *entry2)
+{
+  return entry1->orig == entry2;
+}
+
+typedef hash_table <decl_table_entry_hasher> decl_hash_type;
+
+/* Copy DIE and its ancestors, up to, but not including, the compile unit
+   or type unit entry, to a new tree.  Adds the new tree to UNIT and returns
+   a pointer to the copy of DIE.  If DECL_TABLE is provided, it is used
+   to check if the ancestor has already been copied into UNIT.  */
+
+static dw_die_ref
+copy_ancestor_tree (dw_die_ref unit, dw_die_ref die, decl_hash_type decl_table)
+{
+  dw_die_ref parent = die->die_parent;
+  dw_die_ref new_parent = unit;
+  dw_die_ref copy;
+  decl_table_entry **slot = NULL;
+  struct decl_table_entry *entry = NULL;
+
+  if (decl_table.is_created ())
+    {
+      /* Check if the entry has already been copied to UNIT.  */
+      slot = decl_table.find_slot_with_hash (die, htab_hash_pointer (die),
+					     INSERT);
+      if (*slot != HTAB_EMPTY_ENTRY)
+        {
+          entry = *slot;
+          return entry->copy;
+        }
+
+      /* Record in DECL_TABLE that DIE has been copied to UNIT.  */
+      entry = XCNEW (struct decl_table_entry);
+      entry->orig = die;
+      entry->copy = NULL;
+      *slot = entry;
+    }
+
+  if (parent != NULL)
+    {
+      dw_die_ref spec = get_AT_ref (parent, DW_AT_specification);
+      if (spec != NULL)
+        parent = spec;
+      if (!is_unit_die (parent))
+        new_parent = copy_ancestor_tree (unit, parent, decl_table);
+    }
+
+  copy = clone_as_declaration (die);
+  add_child_die (new_parent, copy);
+
+  if (decl_table.is_created ())
+    {
+      /* Record the pointer to the copy.  */
+      entry->copy = copy;
+    }
+
+  return copy;
+}
 /* Copy the declaration context to the new type unit DIE.  This includes
    any surrounding namespace or type declarations.  If the DIE has an
    AT_specification attribute, it also includes attributes and children
@@ -6859,7 +6945,7 @@  copy_declaration_context (dw_die_ref uni
   if (decl->die_parent != NULL
       && !is_unit_die (decl->die_parent))
     {
-      new_decl = copy_ancestor_tree (unit, decl, NULL);
+      new_decl = copy_ancestor_tree (unit, decl, decl_hash_type ());
       if (new_decl != NULL)
         {
           remove_AT (new_decl, DW_AT_signature);
@@ -7058,106 +7144,16 @@  break_out_comdat_types (dw_die_ref die)
   } while (next != NULL);
 }

-/* Structure to map a DIE in one CU to its copy in a comdat type unit.  */
-
-struct decl_table_entry
-{
-  dw_die_ref orig;
-  dw_die_ref copy;
-};
-
-/* Routines to manipulate hash table of copied declarations.  */
-
-static hashval_t
-htab_decl_hash (const void *of)
-{
-  const struct decl_table_entry *const entry =
-    (const struct decl_table_entry *) of;
-
-  return htab_hash_pointer (entry->orig);
-}
-
-static int
-htab_decl_eq (const void *of1, const void *of2)
-{
-  const struct decl_table_entry *const entry1 =
-    (const struct decl_table_entry *) of1;
-  const struct die_struct *const entry2 = (const struct die_struct *) of2;
-
-  return entry1->orig == entry2;
-}
-
-static void
-htab_decl_del (void *what)
-{
-  struct decl_table_entry *entry = (struct decl_table_entry *) what;
-
-  free (entry);
-}
-
-/* Copy DIE and its ancestors, up to, but not including, the compile unit
-   or type unit entry, to a new tree.  Adds the new tree to UNIT and returns
-   a pointer to the copy of DIE.  If DECL_TABLE is provided, it is used
-   to check if the ancestor has already been copied into UNIT.  */
-
-static dw_die_ref
-copy_ancestor_tree (dw_die_ref unit, dw_die_ref die, htab_t decl_table)
-{
-  dw_die_ref parent = die->die_parent;
-  dw_die_ref new_parent = unit;
-  dw_die_ref copy;
-  void **slot = NULL;
-  struct decl_table_entry *entry = NULL;
-
-  if (decl_table)
-    {
-      /* Check if the entry has already been copied to UNIT.  */
-      slot = htab_find_slot_with_hash (decl_table, die,
-                                       htab_hash_pointer (die), INSERT);
-      if (*slot != HTAB_EMPTY_ENTRY)
-        {
-          entry = (struct decl_table_entry *) *slot;
-          return entry->copy;
-        }
-
-      /* Record in DECL_TABLE that DIE has been copied to UNIT.  */
-      entry = XCNEW (struct decl_table_entry);
-      entry->orig = die;
-      entry->copy = NULL;
-      *slot = entry;
-    }
-
-  if (parent != NULL)
-    {
-      dw_die_ref spec = get_AT_ref (parent, DW_AT_specification);
-      if (spec != NULL)
-        parent = spec;
-      if (!is_unit_die (parent))
-        new_parent = copy_ancestor_tree (unit, parent, decl_table);
-    }
-
-  copy = clone_as_declaration (die);
-  add_child_die (new_parent, copy);
-
-  if (decl_table != NULL)
-    {
-      /* Record the pointer to the copy.  */
-      entry->copy = copy;
-    }
-
-  return copy;
-}
-
 /* Like clone_tree, but additionally enter all the children into
    the hash table decl_table.  */

 static dw_die_ref
-clone_tree_hash (dw_die_ref die, htab_t decl_table)
+clone_tree_hash (dw_die_ref die, decl_hash_type decl_table)
 {
   dw_die_ref c;
   dw_die_ref clone = clone_die (die);
   struct decl_table_entry *entry;
-  void **slot = htab_find_slot_with_hash (decl_table, die,
+  decl_table_entry **slot = decl_table.find_slot_with_hash (die,
 					  htab_hash_pointer (die), INSERT);
   /* Assert that DIE isn't in the hash table yet.  If it would be there
      before, the ancestors would be necessarily there as well, therefore
@@ -7179,7 +7175,7 @@  clone_tree_hash (dw_die_ref die, htab_t
    type_unit).  */

 static void
-copy_decls_walk (dw_die_ref unit, dw_die_ref die, htab_t decl_table)
+copy_decls_walk (dw_die_ref unit, dw_die_ref die, decl_hash_type decl_table)
 {
   dw_die_ref c;
   dw_attr_ref a;
@@ -7190,20 +7186,20 @@  copy_decls_walk (dw_die_ref unit, dw_die
       if (AT_class (a) == dw_val_class_die_ref)
         {
           dw_die_ref targ = AT_ref (a);
-          void **slot;
+          decl_table_entry **slot;
           struct decl_table_entry *entry;

           if (targ->die_mark != 0 || targ->comdat_type_p)
             continue;

-          slot = htab_find_slot_with_hash (decl_table, targ,
-                                           htab_hash_pointer (targ), INSERT);
+          slot = decl_table.find_slot_with_hash (targ,
htab_hash_pointer (targ),
+						 INSERT);

           if (*slot != HTAB_EMPTY_ENTRY)
             {
               /* TARG has already been copied, so we just need to
                  modify the reference to point to the copy.  */
-              entry = (struct decl_table_entry *) *slot;
+              entry = *slot;
               a->dw_attr_val.v.val_die_ref.die = entry->copy;
             }
           else
@@ -7270,12 +7266,12 @@  copy_decls_walk (dw_die_ref unit, dw_die
 static void
 copy_decls_for_unworthy_types (dw_die_ref unit)
 {
-  htab_t decl_table;
+  decl_hash_type decl_table;

   mark_dies (unit);
-  decl_table = htab_create (10, htab_decl_hash, htab_decl_eq, htab_decl_del);
+  decl_table.create (10);
   copy_decls_walk (unit, unit, decl_table);
-  htab_delete (decl_table);
+  decl_table.dispose ();
   unmark_dies (unit);
 }

@@ -7330,37 +7326,42 @@  struct external_ref
   unsigned n_refs;
 };

-/* Hash an external_ref.  */
+/* Hashtable helpers.  */

-static hashval_t
-hash_external_ref (const void *p)
+struct external_ref_hasher : typed_free_remove <external_ref>
+{
+  typedef external_ref value_type;
+  typedef external_ref compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+external_ref_hasher::hash (const value_type *r)
 {
-  const struct external_ref *r = (const struct external_ref *)p;
   return htab_hash_pointer (r->type);
 }

-/* Compare external_refs.  */
-
-static int
-external_ref_eq (const void *p1, const void *p2)
+inline bool
+external_ref_hasher::equal (const value_type *r1, const compare_type *r2)
 {
-  const struct external_ref *r1 = (const struct external_ref *)p1;
-  const struct external_ref *r2 = (const struct external_ref *)p2;
   return r1->type == r2->type;
 }

+typedef hash_table <external_ref_hasher> external_ref_hash_type;
+
 /* Return a pointer to the external_ref for references to DIE.  */

 static struct external_ref *
-lookup_external_ref (htab_t map, dw_die_ref die)
+lookup_external_ref (external_ref_hash_type map, dw_die_ref die)
 {
   struct external_ref ref, *ref_p;
-  void ** slot;
+  external_ref **slot;

   ref.type = die;
-  slot = htab_find_slot (map, &ref, INSERT);
+  slot = map.find_slot (&ref, INSERT);
   if (*slot != HTAB_EMPTY_ENTRY)
-    return (struct external_ref *) *slot;
+    return *slot;

   ref_p = XCNEW (struct external_ref);
   ref_p->type = die;
@@ -7374,7 +7375,7 @@  lookup_external_ref (htab_t map, dw_die_
    references, remember how many we've seen.  */

 static void
-optimize_external_refs_1 (dw_die_ref die, htab_t map)
+optimize_external_refs_1 (dw_die_ref die, external_ref_hash_type map)
 {
   dw_die_ref c;
   dw_attr_ref a;
@@ -7407,17 +7408,17 @@  optimize_external_refs_1 (dw_die_ref die
    points to an external_ref, DATA is the CU we're processing.  If we don't
    already have a local stub, and we have multiple refs, build a stub.  */

-static int
-build_local_stub (void **slot, void *data)
+int
+dwarf2_build_local_stub (external_ref **slot, dw_die_ref data)
 {
-  struct external_ref *ref_p = (struct external_ref *)*slot;
+  struct external_ref *ref_p = *slot;

   if (ref_p->stub == NULL && ref_p->n_refs > 1 && !dwarf_strict)
     {
       /* We have multiple references to this type, so build a small stub.
 	 Both of these forms are a bit dodgy from the perspective of the
 	 DWARF standard, since technically they should have names.  */
-      dw_die_ref cu = (dw_die_ref) data;
+      dw_die_ref cu = data;
       dw_die_ref type = ref_p->type;
       dw_die_ref stub = NULL;

@@ -7445,12 +7446,13 @@  build_local_stub (void **slot, void *dat
    them which will be applied in build_abbrev_table.  This is useful because
    references to local DIEs are smaller.  */

-static htab_t
+static external_ref_hash_type
 optimize_external_refs (dw_die_ref die)
 {
-  htab_t map = htab_create (10, hash_external_ref, external_ref_eq, free);
+  external_ref_hash_type map;
+  map.create (10);
   optimize_external_refs_1 (die, map);
-  htab_traverse (map, build_local_stub, die);
+  map.traverse <dw_die_ref, dwarf2_build_local_stub> (die);
   return map;
 }

@@ -7460,7 +7462,7 @@  optimize_external_refs (dw_die_ref die)
    die are visited recursively.  */

 static void
-build_abbrev_table (dw_die_ref die, htab_t extern_map)
+build_abbrev_table (dw_die_ref die, external_ref_hash_type extern_map)
 {
   unsigned long abbrev_id;
   unsigned int n_alloc;
@@ -8589,7 +8591,7 @@  output_comp_unit (dw_die_ref die, int ou
 {
   const char *secname, *oldsym;
   char *tmp;
-  htab_t extern_map;
+  external_ref_hash_type extern_map;

   /* Unless we are outputting main CU, we may throw away empty ones.  */
   if (!output_if_empty && die->die_child == NULL)
@@ -8606,7 +8608,7 @@  output_comp_unit (dw_die_ref die, int ou

   build_abbrev_table (die, extern_map);

-  htab_delete (extern_map);
+  extern_map.dispose ();

   /* Initialize the beginning DIE offset - and calculate sizes/offsets.  */
   next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
@@ -8764,7 +8766,7 @@  output_comdat_type_unit (comdat_type_nod
 #if defined (OBJECT_FORMAT_ELF)
   tree comdat_key;
 #endif
-  htab_t extern_map;
+  external_ref_hash_type extern_map;

   /* First mark all the DIEs in this CU so we know which get local refs.  */
   mark_dies (node->root_die);
@@ -8773,7 +8775,7 @@  output_comdat_type_unit (comdat_type_nod

   build_abbrev_table (node->root_die, extern_map);

-  htab_delete (extern_map);
+  extern_map.dispose ();

   /* Initialize the beginning DIE offset - and calculate sizes/offsets.  */
   next_die_offset = DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE;
@@ -21092,26 +21094,31 @@  dwarf2out_undef (unsigned int lineno ATT
     }
 }

-/* Routines to manipulate hash table of CUs.  */
+/* Helpers to manipulate hash table of CUs.  */

-static hashval_t
-htab_macinfo_hash (const void *of)
+struct macinfo_entry_hasher : typed_noop_remove <macinfo_entry>
 {
-  const macinfo_entry *const entry =
-    (const macinfo_entry *) of;
+  typedef macinfo_entry value_type;
+  typedef macinfo_entry compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};

+inline hashval_t
+macinfo_entry_hasher::hash (const value_type *entry)
+{
   return htab_hash_string (entry->info);
 }

-static int
-htab_macinfo_eq (const void *of1, const void *of2)
+inline bool
+macinfo_entry_hasher::equal (const value_type *entry1,
+			     const compare_type *entry2)
 {
-  const macinfo_entry *const entry1 = (const macinfo_entry *) of1;
-  const macinfo_entry *const entry2 = (const macinfo_entry *) of2;
-
   return !strcmp (entry1->info, entry2->info);
 }

+typedef hash_table <macinfo_entry_hasher> macinfo_hash_type;
+
 /* Output a single .debug_macinfo entry.  */

 static void
@@ -21200,7 +21207,7 @@  output_macinfo_op (macinfo_entry *ref)

 static unsigned
 optimize_macinfo_range (unsigned int idx, vec<macinfo_entry, va_gc> *files,
-			htab_t *macinfo_htab)
+			macinfo_hash_type *macinfo_htab)
 {
   macinfo_entry *first, *second, *cur, *inc;
   char linebuf[sizeof (HOST_WIDE_INT) * 3 + 1];
@@ -21209,7 +21216,7 @@  optimize_macinfo_range (unsigned int idx
   char *grp_name, *tail;
   const char *base;
   unsigned int i, count, encoded_filename_len, linebuf_len;
-  void **slot;
+  macinfo_entry **slot;

   first = &(*macinfo_table)[idx];
   second = &(*macinfo_table)[idx + 1];
@@ -21287,17 +21294,17 @@  optimize_macinfo_range (unsigned int idx
   inc->code = DW_MACRO_GNU_transparent_include;
   inc->lineno = 0;
   inc->info = ggc_strdup (grp_name);
-  if (*macinfo_htab == NULL)
-    *macinfo_htab = htab_create (10, htab_macinfo_hash, htab_macinfo_eq, NULL);
+  if (!macinfo_htab->is_created ())
+    macinfo_htab->create (10);
   /* Avoid emitting duplicates.  */
-  slot = htab_find_slot (*macinfo_htab, inc, INSERT);
+  slot = macinfo_htab->find_slot (inc, INSERT);
   if (*slot != NULL)
     {
       inc->code = 0;
       inc->info = NULL;
       /* If such an entry has been used before, just emit
 	 a DW_MACRO_GNU_transparent_include op.  */
-      inc = (macinfo_entry *) *slot;
+      inc = *slot;
       output_macinfo_op (inc);
       /* And clear all macinfo_entry in the range to avoid emitting them
 	 in the second pass.  */
@@ -21310,7 +21317,7 @@  optimize_macinfo_range (unsigned int idx
   else
     {
       *slot = inc;
-      inc->lineno = htab_elements (*macinfo_htab);
+      inc->lineno = macinfo_htab->elements ();
       output_macinfo_op (inc);
     }
   return count;
@@ -21361,7 +21368,7 @@  output_macinfo (void)
   unsigned long length = vec_safe_length (macinfo_table);
   macinfo_entry *ref;
   vec<macinfo_entry, va_gc> *files = NULL;
-  htab_t macinfo_htab = NULL;
+  macinfo_hash_type macinfo_htab;

   if (! length)
     return;
@@ -21434,10 +21441,10 @@  output_macinfo (void)
       ref->code = 0;
     }

-  if (macinfo_htab == NULL)
+  if (!macinfo_htab.is_created ())
     return;

-  htab_delete (macinfo_htab);
+  macinfo_htab.dispose ();

   /* If any DW_MACRO_GNU_transparent_include were used, on those
      DW_MACRO_GNU_transparent_include entries terminate the
@@ -22183,24 +22190,28 @@  file_table_relative_p (void ** slot, voi
   return 1;
 }

-/* Routines to manipulate hash table of comdat type units.  */
+/* Helpers to manipulate hash table of comdat type units.  */

-static hashval_t
-htab_ct_hash (const void *of)
+struct comdat_type_hasher : typed_noop_remove <comdat_type_node>
 {
-  hashval_t h;
-  const comdat_type_node *const type_node = (const comdat_type_node *) of;
+  typedef comdat_type_node value_type;
+  typedef comdat_type_node compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};

+inline hashval_t
+comdat_type_hasher::hash (const value_type *type_node)
+{
+  hashval_t h;
   memcpy (&h, type_node->signature, sizeof (h));
   return h;
 }

-static int
-htab_ct_eq (const void *of1, const void *of2)
+inline bool
+comdat_type_hasher::equal (const value_type *type_node_1,
+			   const compare_type *type_node_2)
 {
-  const comdat_type_node *const type_node_1 = (const comdat_type_node *) of1;
-  const comdat_type_node *const type_node_2 = (const comdat_type_node *) of2;
-
   return (! memcmp (type_node_1->signature, type_node_2->signature,
                     DWARF_TYPE_SIGNATURE_SIZE));
 }
@@ -23070,21 +23081,29 @@  compare_locs (dw_loc_descr_ref x, dw_loc
   return x == NULL && y == NULL;
 }

+/* Hashtable helpers.  */
+
+struct loc_list_hasher : typed_noop_remove <dw_loc_list_struct>
+{
+  typedef dw_loc_list_struct value_type;
+  typedef dw_loc_list_struct compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
 /* Return precomputed hash of location list X.  */

-static hashval_t
-loc_list_hash (const void *x)
+inline hashval_t
+loc_list_hasher::hash (const value_type *x)
 {
-  return ((const struct dw_loc_list_struct *) x)->hash;
+  return x->hash;
 }

-/* Return 1 if location lists X and Y are the same.  */
+/* Return true if location lists A and B are the same.  */

-static int
-loc_list_eq (const void *x, const void *y)
+inline bool
+loc_list_hasher::equal (const value_type *a, const compare_type *b)
 {
-  const struct dw_loc_list_struct *a = (const struct dw_loc_list_struct *) x;
-  const struct dw_loc_list_struct *b = (const struct dw_loc_list_struct *) y;
   if (a == b)
     return 1;
   if (a->hash != b->hash)
@@ -23099,16 +23118,19 @@  loc_list_eq (const void *x, const void *
   return a == NULL && b == NULL;
 }

+typedef hash_table <loc_list_hasher> loc_list_hash_type;
+
+
 /* Recursively optimize location lists referenced from DIE
    children and share them whenever possible.  */

 static void
-optimize_location_lists_1 (dw_die_ref die, htab_t htab)
+optimize_location_lists_1 (dw_die_ref die, loc_list_hash_type htab)
 {
   dw_die_ref c;
   dw_attr_ref a;
   unsigned ix;
-  void **slot;
+  dw_loc_list_struct **slot;

   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (AT_class (a) == dw_val_class_loc_list)
@@ -23117,12 +23139,11 @@  optimize_location_lists_1 (dw_die_ref di
 	/* TODO: perform some optimizations here, before hashing
 	   it and storing into the hash table.  */
 	hash_loc_list (list);
-	slot = htab_find_slot_with_hash (htab, list, list->hash,
-					 INSERT);
+	slot = htab.find_slot_with_hash (list, list->hash, INSERT);
 	if (*slot == NULL)
-	  *slot = (void *) list;
+	  *slot = list;
 	else
-          a->dw_attr_val.v.val_loc_list = (dw_loc_list_ref) *slot;
+          a->dw_attr_val.v.val_loc_list = *slot;
       }

   FOR_EACH_CHILD (die, c, optimize_location_lists_1 (c, htab));
@@ -23167,9 +23188,10 @@  index_location_lists (dw_die_ref die)
 static void
 optimize_location_lists (dw_die_ref die)
 {
-  htab_t htab = htab_create (500, loc_list_hash, loc_list_eq, NULL);
+  loc_list_hash_type htab;
+  htab.create (500);
   optimize_location_lists_1 (die, htab);
-  htab_delete (htab);
+  htab.dispose ();
 }
 
 /* Output stuff that dwarf requires at the end of every file,
@@ -23180,7 +23202,7 @@  dwarf2out_finish (const char *filename)
 {
   limbo_die_node *node, *next_node;
   comdat_type_node *ctnode;
-  htab_t comdat_type_table;
+  hash_table <comdat_type_hasher> comdat_type_table;
   unsigned int i;
   dw_die_ref main_comp_unit_die;

@@ -23440,10 +23462,10 @@  dwarf2out_finish (const char *filename)
   for (node = limbo_die_list; node; node = node->next)
     output_comp_unit (node->die, 0);

-  comdat_type_table = htab_create (100, htab_ct_hash, htab_ct_eq, NULL);
+  comdat_type_table.create (100);
   for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
     {
-      void **slot = htab_find_slot (comdat_type_table, ctnode, INSERT);
+      comdat_type_node **slot = comdat_type_table.find_slot (ctnode, INSERT);

       /* Don't output duplicate types.  */
       if (*slot != HTAB_EMPTY_ENTRY)
@@ -23461,7 +23483,7 @@  dwarf2out_finish (const char *filename)
       output_comdat_type_unit (ctnode);
       *slot = ctnode;
     }
-  htab_delete (comdat_type_table);
+  comdat_type_table.dispose ();

   /* The AT_pubnames attribute needs to go in all skeleton dies, including
      both the main_cu and all skeleton TUs.  Making this call unconditional
Index: gcc/tree-browser.c
===================================================================
--- gcc/tree-browser.c	(revision 193902)
+++ gcc/tree-browser.c	(working copy)
@@ -22,6 +22,7 @@  along with GCC; see the file COPYING3.
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "hash-table.h"
 #include "tree.h"
 #include "tree-pretty-print.h"

@@ -101,8 +102,40 @@  static tree TB_history_prev (void);
 /* FIXME: To be declared in a .h file.  */
 void browse_tree (tree);

+/* Hashtable helpers.  */
+struct tree_upper_hasher : typed_noop_remove <VALUE>
+{
+  typedef tree_node value_type;
+  typedef tree_node compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+tree_upper_hasher::hash (const value_type *v)
+{
+  return pointer_hash <value_type>::hash (v);
+}
+
+inline bool
+tree_upper_hasher::equal (const value_type *parent, const compare_type *node)
+{
+  if (parent == NULL || node == NULL)
+    return 0;
+
+  if (EXPR_P (parent))
+    {
+      int n = TREE_OPERAND_LENGTH (parent);
+      int i;
+      for (i = 0; i < n; i++)
+	if (node == TREE_OPERAND (parent, i))
+	  return true;
+    }
+  return false;
+}
+
 /* Static variables.  */
-static htab_t TB_up_ht;
+static hash_table <tree_upper_hasher> TB_up_ht;
 static vec<tree, va_gc> *TB_history_stack;
 static int TB_verbose = 1;

@@ -135,7 +168,7 @@  browse_tree (tree begin)

   /* Store in a hashtable information about previous and upper statements.  */
   {
-    TB_up_ht = htab_create (1023, htab_hash_pointer, &TB_parent_eq, NULL);
+    TB_up_ht.create (1023);
     TB_update_up (head);
   }

@@ -613,7 +646,7 @@  browse_tree (tree begin)
     }

  ret:;
-  htab_delete (TB_up_ht);
+  TB_up_ht.dispose ();
   return;
 }

@@ -659,7 +692,7 @@  TB_up_expr (tree node)
   if (node == NULL_TREE)
     return NULL_TREE;

-  res = (tree) htab_find (TB_up_ht, node);
+  res = TB_up_ht.find (node);
   return res;
 }

@@ -725,7 +758,7 @@  store_child_info (tree *tp, int *walk_su
 		  void *data ATTRIBUTE_UNUSED)
 {
   tree node;
-  void **slot;
+  tree_node **slot;

   node = *tp;

@@ -737,8 +770,8 @@  store_child_info (tree *tp, int *walk_su
       for (i = 0; i < n; i++)
 	{
 	  tree op = TREE_OPERAND (node, i);
-	  slot = htab_find_slot (TB_up_ht, op, INSERT);
-	  *slot = (void *) node;
+	  slot = TB_up_ht.find_slot (op, INSERT);
+	  *slot = node;
 	}
     }

@@ -746,28 +779,6 @@  store_child_info (tree *tp, int *walk_su
   return NULL_TREE;
 }

-/* Function used in TB_up_ht.  */
-
-static int
-TB_parent_eq (const void *p1, const void *p2)
-{
-  const_tree const node = (const_tree)p2;
-  const_tree const parent = (const_tree) p1;
-
-  if (p1 == NULL || p2 == NULL)
-    return 0;
-
-  if (EXPR_P (parent))
-    {
-      int n = TREE_OPERAND_LENGTH (parent);
-      int i;
-      for (i = 0; i < n; i++)
-	if (node == TREE_OPERAND (parent, i))
-	  return 1;
-    }
-  return 0;
-}
-
 /* Update information about upper expressions in the hash table.  */

 static void
Index: gcc/tree-eh.c
===================================================================
--- gcc/tree-eh.c	(revision 193902)
+++ gcc/tree-eh.c	(working copy)
@@ -21,6 +21,7 @@  along with GCC; see the file COPYING3.
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "hash-table.h"
 #include "tm.h"
 #include "tree.h"
 #include "flags.h"
@@ -194,20 +195,42 @@  struct finally_tree_node
   gimple parent;
 };

+/* Hashtable helpers.  */
+
+struct finally_tree_hasher : typed_free_remove <finally_tree_node>
+{
+  typedef finally_tree_node value_type;
+  typedef finally_tree_node compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+finally_tree_hasher::hash (const value_type *v)
+{
+  return (intptr_t)v->child.t >> 4;
+}
+
+inline bool
+finally_tree_hasher::equal (const value_type *v, const compare_type *c)
+{
+  return v->child.t == c->child.t;
+}
+
 /* Note that this table is *not* marked GTY.  It is short-lived.  */
-static htab_t finally_tree;
+static hash_table <finally_tree_hasher> finally_tree;

 static void
 record_in_finally_tree (treemple child, gimple parent)
 {
   struct finally_tree_node *n;
-  void **slot;
+  finally_tree_node **slot;

   n = XNEW (struct finally_tree_node);
   n->child = child;
   n->parent = parent;

-  slot = htab_find_slot (finally_tree, n, INSERT);
+  slot = finally_tree.find_slot (n, INSERT);
   gcc_assert (!*slot);
   *slot = n;
 }
@@ -286,7 +309,7 @@  outside_finally_tree (treemple start, gi
   do
     {
       n.child = start;
-      p = (struct finally_tree_node *) htab_find (finally_tree, &n);
+      p = finally_tree.find (&n);
       if (!p)
 	return true;
       start.g = p->parent;
@@ -2102,7 +2125,7 @@  lower_eh_constructs (void)
   if (bodyp == NULL)
     return 0;

-  finally_tree = htab_create (31, struct_ptr_hash, struct_ptr_eq, free);
+  finally_tree.create (31);
   eh_region_may_contain_throw_map = BITMAP_ALLOC (NULL);
   memset (&null_state, 0, sizeof (null_state));

@@ -2120,7 +2143,7 @@  lower_eh_constructs (void)
      didn't change its value, and we don't have to re-set the function.  */
   gcc_assert (bodyp == gimple_body (current_function_decl));

-  htab_delete (finally_tree);
+  finally_tree.dispose ();
   BITMAP_FREE (eh_region_may_contain_throw_map);
   eh_seq = NULL;

Index: gcc/trans-mem.c
===================================================================
--- gcc/trans-mem.c	(revision 193902)
+++ gcc/trans-mem.c	(working copy)
@@ -20,6 +20,7 @@ 
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "hash-table.h"
 #include "tree.h"
 #include "gimple.h"
 #include "tree-flow.h"
@@ -886,10 +887,6 @@  static htab_t tm_log;
    dominator order.  */
 static vec<tree> tm_log_save_addresses;

-/* Map for an SSA_NAME originally pointing to a non aliased new piece
-   of memory (malloc, alloc, etc).  */
-static htab_t tm_new_mem_hash;
-
 enum thread_memory_type
   {
     mem_non_local = 0,
@@ -905,6 +902,32 @@  typedef struct tm_new_mem_map
   enum thread_memory_type local_new_memory;
 } tm_new_mem_map_t;

+/* Hashtable helpers.  */
+
+struct tm_mem_map_hasher : typed_free_remove <tm_new_mem_map_t>
+{
+  typedef tm_new_mem_map_t value_type;
+  typedef tm_new_mem_map_t compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+tm_mem_map_hasher::hash (const value_type *v)
+{
+  return (intptr_t)v->val >> 4;
+}
+
+inline bool
+tm_mem_map_hasher::equal (const value_type *v, const compare_type *c)
+{
+  return v->val == c->val;
+}
+
+/* Map for an SSA_NAME originally pointing to a non aliased new piece
+   of memory (malloc, alloc, etc).  */
+static hash_table <tm_mem_map_hasher> tm_new_mem_hash;
+
 /* Htab support.  Return hash value for a `tm_log_entry'.  */
 static hashval_t
 tm_log_hash (const void *p)
@@ -956,7 +979,7 @@  static void
 tm_log_init (void)
 {
   tm_log = htab_create (10, tm_log_hash, tm_log_eq, tm_log_free);
-  tm_new_mem_hash = htab_create (5, struct_ptr_hash, struct_ptr_eq, free);
+  tm_new_mem_hash.create (5);
   tm_log_save_addresses.create (5);
 }

@@ -965,7 +988,7 @@  static void
 tm_log_delete (void)
 {
   htab_delete (tm_log);
-  htab_delete (tm_new_mem_hash);
+  tm_new_mem_hash.dispose ();
   tm_log_save_addresses.release ();
 }

@@ -1271,7 +1294,7 @@  thread_private_new_memory (basic_block e
 {
   gimple stmt = NULL;
   enum tree_code code;
-  void **slot;
+  tm_new_mem_map_t **slot;
   tm_new_mem_map_t elt, *elt_p;
   tree val = x;
   enum thread_memory_type retval = mem_transaction_local;
@@ -1285,8 +1308,8 @@  thread_private_new_memory (basic_block e

   /* Look in cache first.  */
   elt.val = x;
-  slot = htab_find_slot (tm_new_mem_hash, &elt, INSERT);
-  elt_p = (tm_new_mem_map_t *) *slot;
+  slot = tm_new_mem_hash.find_slot (&elt, INSERT);
+  elt_p = *slot;
   if (elt_p)
     return elt_p->local_new_memory;

Index: gcc/except.c
===================================================================
--- gcc/except.c	(revision 193902)
+++ gcc/except.c	(working copy)
@@ -130,7 +130,7 @@  along with GCC; see the file COPYING3.
 #include "dwarf2out.h"
 #include "dwarf2.h"
 #include "toplev.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "intl.h"
 #include "ggc.h"
 #include "tm_p.h"
@@ -168,6 +168,49 @@  struct GTY(()) call_site_record_d
   rtx landing_pad;
   int action;
 };
+
+/* In the following structure and associated functions,
+   we represent entries in the action table as 1-based indices.
+   Special cases are:
+
+	 0:	null action record, non-null landing pad; implies cleanups
+	-1:	null action record, null landing pad; implies no action
+	-2:	no call-site entry; implies must_not_throw
+	-3:	we have yet to process outer regions
+
+   Further, no special cases apply to the "next" field of the record.
+   For next, 0 means end of list.  */
+
+struct action_record
+{
+  int offset;
+  int filter;
+  int next;
+};
+
+/* Hashtable helpers.  */
+
+struct action_record_hasher : typed_free_remove <action_record>
+{
+  typedef action_record value_type;
+  typedef action_record compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+action_record_hasher::hash (const value_type *entry)
+{
+  return entry->next * 1009 + entry->filter;
+}
+
+inline bool
+action_record_hasher::equal (const value_type *entry, const compare_type *data)
+{
+  return entry->filter == data->filter && entry->next == data->next;
+}
+
+typedef hash_table <action_record_hasher> action_hash_type;
 
 static bool get_eh_region_and_lp_from_rtx (const_rtx, eh_region *,
 					   eh_landing_pad *);
@@ -175,18 +218,9 @@  static bool get_eh_region_and_lp_from_rt
 static int t2r_eq (const void *, const void *);
 static hashval_t t2r_hash (const void *);

-static int ttypes_filter_eq (const void *, const void *);
-static hashval_t ttypes_filter_hash (const void *);
-static int ehspec_filter_eq (const void *, const void *);
-static hashval_t ehspec_filter_hash (const void *);
-static int add_ttypes_entry (htab_t, tree);
-static int add_ehspec_entry (htab_t, htab_t, tree);
 static void dw2_build_landing_pads (void);

-static int action_record_eq (const void *, const void *);
-static hashval_t action_record_hash (const void *);
-static int add_action_record (htab_t, int, int);
-static int collect_one_action_chain (htab_t, eh_region);
+static int collect_one_action_chain (action_hash_type, eh_region);
 static int add_call_site (rtx, int, int);

 static void push_uleb128 (vec<uchar, va_gc> **, unsigned int);
@@ -689,46 +723,60 @@  struct ttypes_filter {
   int filter;
 };

+/* Helper for ttypes_filter hashing.  */
+
+struct ttypes_filter_hasher : typed_free_remove <ttypes_filter>
+{
+  typedef ttypes_filter value_type;
+  typedef tree_node compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
 /* Compare ENTRY (a ttypes_filter entry in the hash table) with DATA
    (a tree) for a @TTypes type node we are thinking about adding.  */

-static int
-ttypes_filter_eq (const void *pentry, const void *pdata)
+inline bool
+ttypes_filter_hasher::equal (const value_type *entry, const compare_type *data)
 {
-  const struct ttypes_filter *const entry
-    = (const struct ttypes_filter *) pentry;
-  const_tree const data = (const_tree) pdata;
-
   return entry->t == data;
 }

-static hashval_t
-ttypes_filter_hash (const void *pentry)
+inline hashval_t
+ttypes_filter_hasher::hash (const value_type *entry)
 {
-  const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
   return TREE_HASH (entry->t);
 }

+typedef hash_table <ttypes_filter_hasher> ttypes_hash_type;
+
+
+/* Helper for ehspec hashing.  */
+
+struct ehspec_hasher : typed_free_remove <ttypes_filter>
+{
+  typedef ttypes_filter value_type;
+  typedef ttypes_filter compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
 /* Compare ENTRY with DATA (both struct ttypes_filter) for a @TTypes
    exception specification list we are thinking about adding.  */
 /* ??? Currently we use the type lists in the order given.  Someone
    should put these in some canonical order.  */

-static int
-ehspec_filter_eq (const void *pentry, const void *pdata)
+inline bool
+ehspec_hasher::equal (const value_type *entry, const compare_type *data)
 {
-  const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
-  const struct ttypes_filter *data = (const struct ttypes_filter *) pdata;
-
   return type_list_equal (entry->t, data->t);
 }

 /* Hash function for exception specification lists.  */

-static hashval_t
-ehspec_filter_hash (const void *pentry)
+inline hashval_t
+ehspec_hasher::hash (const value_type *entry)
 {
-  const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
   hashval_t h = 0;
   tree list;

@@ -737,16 +785,19 @@  ehspec_filter_hash (const void *pentry)
   return h;
 }

+typedef hash_table <ehspec_hasher> ehspec_hash_type;
+
+
 /* Add TYPE (which may be NULL) to cfun->eh->ttype_data, using TYPES_HASH
    to speed up the search.  Return the filter value to be used.  */

 static int
-add_ttypes_entry (htab_t ttypes_hash, tree type)
+add_ttypes_entry (ttypes_hash_type ttypes_hash, tree type)
 {
   struct ttypes_filter **slot, *n;

-  slot = (struct ttypes_filter **)
-    htab_find_slot_with_hash (ttypes_hash, type, TREE_HASH (type), INSERT);
+  slot = ttypes_hash.find_slot_with_hash (type, (hashval_t) TREE_HASH (type),
+					  INSERT);

   if ((n = *slot) == NULL)
     {
@@ -767,14 +818,14 @@  add_ttypes_entry (htab_t ttypes_hash, tr
    to speed up the search.  Return the filter value to be used.  */

 static int
-add_ehspec_entry (htab_t ehspec_hash, htab_t ttypes_hash, tree list)
+add_ehspec_entry (ehspec_hash_type ehspec_hash, ttypes_hash_type ttypes_hash,
+		  tree list)
 {
   struct ttypes_filter **slot, *n;
   struct ttypes_filter dummy;

   dummy.t = list;
-  slot = (struct ttypes_filter **)
-    htab_find_slot (ehspec_hash, &dummy, INSERT);
+  slot = ehspec_hash.find_slot (&dummy, INSERT);

   if ((n = *slot) == NULL)
     {
@@ -823,7 +874,8 @@  void
 assign_filter_values (void)
 {
   int i;
-  htab_t ttypes, ehspec;
+  ttypes_hash_type ttypes;
+  ehspec_hash_type ehspec;
   eh_region r;
   eh_catch c;

@@ -833,8 +885,8 @@  assign_filter_values (void)
   else
     vec_alloc (cfun->eh->ehspec_data.other, 64);

-  ttypes = htab_create (31, ttypes_filter_hash, ttypes_filter_eq, free);
-  ehspec = htab_create (31, ehspec_filter_hash, ehspec_filter_eq, free);
+  ttypes.create (31);
+  ehspec.create (31);

   for (i = 1; vec_safe_iterate (cfun->eh->region_array, i, &r); ++i)
     {
@@ -888,8 +940,8 @@  assign_filter_values (void)
 	}
     }

-  htab_delete (ttypes);
-  htab_delete (ehspec);
+  ttypes.dispose ();
+  ehspec.dispose ();
 }

 /* Emit SEQ into basic block just before INSN (that is assumed to be
@@ -1011,12 +1063,12 @@  static vec<int> sjlj_lp_call_site_index;
 static int
 sjlj_assign_call_site_values (void)
 {
-  htab_t ar_hash;
+  action_hash_type ar_hash;
   int i, disp_index;
   eh_landing_pad lp;

   vec_alloc (crtl->eh.action_record_data, 64);
-  ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
+  ar_hash.create (31);

   disp_index = 0;
   call_site_base = 1;
@@ -1045,7 +1097,7 @@  sjlj_assign_call_site_values (void)
 	disp_index++;
       }

-  htab_delete (ar_hash);
+  ar_hash.dispose ();

   return disp_index;
 }
@@ -2201,47 +2253,14 @@  expand_builtin_extend_pointer (tree addr
   return convert_modes (targetm.unwind_word_mode (), ptr_mode, addr, extend);
 }
 
-/* In the following functions, we represent entries in the action table
-   as 1-based indices.  Special cases are:
-
-	 0:	null action record, non-null landing pad; implies cleanups
-	-1:	null action record, null landing pad; implies no action
-	-2:	no call-site entry; implies must_not_throw
-	-3:	we have yet to process outer regions
-
-   Further, no special cases apply to the "next" field of the record.
-   For next, 0 means end of list.  */
-
-struct action_record
-{
-  int offset;
-  int filter;
-  int next;
-};
-
 static int
-action_record_eq (const void *pentry, const void *pdata)
-{
-  const struct action_record *entry = (const struct action_record *) pentry;
-  const struct action_record *data = (const struct action_record *) pdata;
-  return entry->filter == data->filter && entry->next == data->next;
-}
-
-static hashval_t
-action_record_hash (const void *pentry)
-{
-  const struct action_record *entry = (const struct action_record *) pentry;
-  return entry->next * 1009 + entry->filter;
-}
-
-static int
-add_action_record (htab_t ar_hash, int filter, int next)
+add_action_record (action_hash_type ar_hash, int filter, int next)
 {
   struct action_record **slot, *new_ar, tmp;

   tmp.filter = filter;
   tmp.next = next;
-  slot = (struct action_record **) htab_find_slot (ar_hash, &tmp, INSERT);
+  slot = ar_hash.find_slot (&tmp, INSERT);

   if ((new_ar = *slot) == NULL)
     {
@@ -2266,7 +2285,7 @@  add_action_record (htab_t ar_hash, int f
 }

 static int
-collect_one_action_chain (htab_t ar_hash, eh_region region)
+collect_one_action_chain (action_hash_type ar_hash, eh_region region)
 {
   int next;

@@ -2395,7 +2414,7 @@  static unsigned int
 convert_to_eh_region_ranges (void)
 {
   rtx insn, iter, note;
-  htab_t ar_hash;
+  action_hash_type ar_hash;
   int last_action = -3;
   rtx last_action_insn = NULL_RTX;
   rtx last_landing_pad = NULL_RTX;
@@ -2409,7 +2428,7 @@  convert_to_eh_region_ranges (void)

   vec_alloc (crtl->eh.action_record_data, 64);

-  ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
+  ar_hash.create (31);

   for (iter = get_insns (); iter ; iter = NEXT_INSN (iter))
     if (INSN_P (iter))
@@ -2546,7 +2565,7 @@  convert_to_eh_region_ranges (void)

   call_site_base = saved_call_site_base;

-  htab_delete (ar_hash);
+  ar_hash.dispose ();
   return 0;
 }

Index: gcc/dwarf2cfi.c
===================================================================
--- gcc/dwarf2cfi.c	(revision 193902)
+++ gcc/dwarf2cfi.c	(working copy)
@@ -32,6 +32,7 @@  along with GCC; see the file COPYING3.
 #include "dwarf2out.h"
 #include "dwarf2asm.h"
 #include "ggc.h"
+#include "hash-table.h"
 #include "tm_p.h"
 #include "target.h"
 #include "common/common-target.h"
@@ -155,10 +156,33 @@  typedef struct
 typedef dw_trace_info *dw_trace_info_ref;


+/* Hashtable helpers.  */
+
+struct trace_info_hasher : typed_noop_remove <dw_trace_info>
+{
+  typedef dw_trace_info value_type;
+  typedef dw_trace_info compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+trace_info_hasher::hash (const value_type *ti)
+{
+  return INSN_UID (ti->head);
+}
+
+inline bool
+trace_info_hasher::equal (const value_type *a, const compare_type *b)
+{
+  return a->head == b->head;
+}
+
+
 /* The variables making up the pseudo-cfg, as described above.  */
 static vec<dw_trace_info> trace_info;
 static vec<dw_trace_info_ref> trace_work_list;
-static htab_t trace_index;
+static hash_table <trace_info_hasher> trace_index;

 /* A vector of call frame insns for the CIE.  */
 cfi_vec cie_cfi_vec;
@@ -277,28 +301,12 @@  expand_builtin_init_dwarf_reg_sizes (tre
 }

 
-static hashval_t
-dw_trace_info_hash (const void *ptr)
-{
-  const dw_trace_info *ti = (const dw_trace_info *) ptr;
-  return INSN_UID (ti->head);
-}
-
-static int
-dw_trace_info_eq (const void *ptr_a, const void *ptr_b)
-{
-  const dw_trace_info *a = (const dw_trace_info *) ptr_a;
-  const dw_trace_info *b = (const dw_trace_info *) ptr_b;
-  return a->head == b->head;
-}
-
 static dw_trace_info *
 get_trace_info (rtx insn)
 {
   dw_trace_info dummy;
   dummy.head = insn;
-  return (dw_trace_info *)
-    htab_find_with_hash (trace_index, &dummy, INSN_UID (insn));
+  return trace_index.find_with_hash (&dummy, INSN_UID (insn));
 }

 static bool
@@ -2746,22 +2754,20 @@  create_pseudo_cfg (void)

   /* Create the trace index after we've finished building trace_info,
      avoiding stale pointer problems due to reallocation.  */
-  trace_index = htab_create (trace_info.length (),
-			     dw_trace_info_hash, dw_trace_info_eq, NULL);
+  trace_index.create (trace_info.length ());
   dw_trace_info *tp;
   FOR_EACH_VEC_ELT (trace_info, i, tp)
     {
-      void **slot;
+      dw_trace_info **slot;

       if (dump_file)
 	fprintf (dump_file, "Creating trace %u : start at %s %d%s\n", i,
 		 rtx_name[(int) GET_CODE (tp->head)], INSN_UID (tp->head),
 		 tp->switch_sections ? " (section switch)" : "");

-      slot = htab_find_slot_with_hash (trace_index, tp,
-				       INSN_UID (tp->head), INSERT);
+      slot = trace_index.find_slot_with_hash (tp, INSN_UID (tp->head), INSERT);
       gcc_assert (*slot == NULL);
-      *slot = (void *) tp;
+      *slot = tp;
     }
 }

@@ -2910,8 +2916,7 @@  execute_dwarf2_frame (void)
   }
   trace_info.release ();

-  htab_delete (trace_index);
-  trace_index = NULL;
+  trace_index.dispose ();

   return 0;
 }
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 193902)
+++ gcc/Makefile.in	(working copy)
@@ -2008,7 +2008,7 @@  default-c.o: config/default-c.c $(CONFIG
 # Files used by all variants of C and some other languages.

 attribs.o : attribs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
-	$(FLAGS_H) $(DIAGNOSTIC_CORE_H) $(GGC_H) $(TM_P_H) \
+	$(HASH_TABLE_H) $(FLAGS_H) $(DIAGNOSTIC_CORE_H) $(GGC_H) $(TM_P_H) \
 	$(TARGET_H) langhooks.h $(CPPLIB_H) $(PLUGIN_H)

 incpath.o: incpath.c incpath.h $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) \
@@ -2100,7 +2100,7 @@  gtype-desc.o: gtype-desc.c $(CONFIG_H) $
 	$(CFGLOOP_H) $(TARGET_H) $(IPA_PROP_H) $(LTO_STREAMER_H) \
 	target-globals.h

-trans-mem.o : trans-mem.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+trans-mem.o : trans-mem.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(HASH_TABLE_H) \
 	$(TREE_H) $(GIMPLE_H) $(TREE_FLOW_H) $(TREE_PASS_H) $(TREE_INLINE_H) \
 	$(DIAGNOSTIC_CORE_H) $(DEMANGLE_H) output.h $(TRANS_MEM_H) \
 	$(PARAMS_H) $(TARGET_H) langhooks.h \
@@ -2421,7 +2421,7 @@  tree-ssa-operands.o : tree-ssa-operands.
    coretypes.h dumpfile.h langhooks.h $(IPA_REFERENCE_H)
$(GIMPLE_PRETTY_PRINT_H)
 tree-eh.o : tree-eh.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(TREE_H) $(TM_H) $(FLAGS_H) $(FUNCTION_H) $(EXCEPT_H) langhooks.h \
-   $(GGC_H) $(TREE_PASS_H) coretypes.h pointer-set.h \
+   $(HASH_TABLE_H) $(GGC_H) $(TREE_PASS_H) coretypes.h pointer-set.h \
    $(TREE_INLINE_H) tree-iterator.h toplev.h \
    $(DIAGNOSTIC_CORE_H) $(TARGET_H) $(CFGLOOP_H)