Support GTY((cache)) on hash_map.
authorJason Merrill <jason@redhat.com>
Tue, 14 Nov 2017 16:02:57 +0000 (11:02 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 14 Nov 2017 16:02:57 +0000 (11:02 -0500)
gcc/
* hash-traits.h (ggc_remove): Add ggc_maybe_mx member function.
(ggc_cache_remove): Override it instead of ggc_mx.
* hash-table.h (gt_ggc_mx): Call it instead of ggc_mx.
(gt_cleare_cache): Call ggc_mx instead of gt_ggc_mx.
* hash-map-traits.h (simple_hashmap_traits): Add maybe_mx member.
(simple_cache_map_traits): Override maybe_mx.
* hash-map.h (hash_entry): Add ggc_maybe_mx and keep_cache_entry.
(hash_map): Friend gt_cleare_cache.
(gt_cleare_cache): New.
* tree.h (tree_cache_traits): New hash_map traits class.
(tree_cache_map): New typedef.
gcc/cp/
* decl.c (decomp_type_table): Use tree_cache_map.
* init.c (nsdmi_inst): Likewise.
* pt.c (defarg_ints): Likewise.
* cp-objcp-common.c (cp_get_debug_type): Likewise.

From-SVN: r254731

12 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/cp-objcp-common.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/init.c
gcc/cp/pt.c
gcc/hash-map-traits.h
gcc/hash-map.h
gcc/hash-table.h
gcc/hash-traits.h
gcc/tree.h

index e9bb5ae6542bb7dcbb9804558242fdaa17def14a..199ac5c30cb07aea05666b34108f29e71c4bdb99 100644 (file)
@@ -1,3 +1,18 @@
+2017-11-14  Jason Merrill  <jason@redhat.com>
+
+       Support GTY((cache)) on hash_map.
+       * hash-traits.h (ggc_remove): Add ggc_maybe_mx member function.
+       (ggc_cache_remove): Override it instead of ggc_mx.
+       * hash-table.h (gt_ggc_mx): Call it instead of ggc_mx.
+       (gt_cleare_cache): Call ggc_mx instead of gt_ggc_mx.
+       * hash-map-traits.h (simple_hashmap_traits): Add maybe_mx member.
+       (simple_cache_map_traits): Override maybe_mx.
+       * hash-map.h (hash_entry): Add ggc_maybe_mx and keep_cache_entry.
+       (hash_map): Friend gt_cleare_cache.
+       (gt_cleare_cache): New.
+       * tree.h (tree_cache_traits): New hash_map traits class.
+       (tree_cache_map): New typedef.
+
 2017-11-14  Richard Biener  <rguenther@suse.de>
 
        * tree-cfgcleanup.c (cleanup_control_expr_graph): Remove first_p
index ce0c874a5b0c7795aea15943022d9a7f081543f1..8ba5b78aac23d62ca8ef97b8083e66387e855374 100644 (file)
@@ -1,3 +1,11 @@
+2017-11-14  Jason Merrill  <jason@redhat.com>
+
+       Use GTY((cache)) on some hash tables.
+       * decl.c (decomp_type_table): Use tree_cache_map.
+       * init.c (nsdmi_inst): Likewise.
+       * pt.c (defarg_ints): Likewise.
+       * cp-objcp-common.c (cp_get_debug_type): Likewise.
+
 2017-11-13  Jason Merrill  <jason@redhat.com>
 
        Capture adjustments for P0588R1.
index e051d66b67b837b41b83af772006d1e5a25ae83e..9a398e0218cbab2ea4984aad4e69bbd2305ee45d 100644 (file)
@@ -122,19 +122,7 @@ cxx_types_compatible_p (tree x, tree y)
   return same_type_ignoring_top_level_qualifiers_p (x, y);
 }
 
-struct debug_type_hasher : ggc_cache_ptr_hash<tree_map>
-{
-  static hashval_t hash (tree_map *m) { return tree_map_hash (m); }
-  static bool equal (tree_map *a, tree_map *b) { return tree_map_eq (a, b); }
-
-  static int
-  keep_cache_entry (tree_map *&e)
-  {
-    return ggc_marked_p (e->base.from);
-  }
-};
-
-static GTY((cache)) hash_table<debug_type_hasher> *debug_type_hash;
+static GTY((cache)) tree_cache_map *debug_type_map;
 
 /* Return a type to use in the debug info instead of TYPE, or NULL_TREE to
    keep TYPE.  */
@@ -142,38 +130,29 @@ static GTY((cache)) hash_table<debug_type_hasher> *debug_type_hash;
 tree
 cp_get_debug_type (const_tree type)
 {
+  tree dtype = NULL_TREE;
+
   if (TYPE_PTRMEMFUNC_P (type) && !typedef_variant_p (type))
+    dtype = build_offset_type (TYPE_PTRMEMFUNC_OBJECT_TYPE (type),
+                              TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)));
+
+  /* We cannot simply return the debug type here because the function uses
+     the type canonicalization hashtable, which is GC-ed, so its behavior
+     depends on the actual collection points.  Since we are building these
+     types on the fly for the debug info only, they would not be attached
+     to any GC root and always be swept, so we would make the contents of
+     the debug info depend on the collection points.  */
+  if (dtype)
     {
-      if (debug_type_hash == NULL)
-       debug_type_hash = hash_table<debug_type_hasher>::create_ggc (512);
-
-      /* We cannot simply use build_offset_type here because the function uses
-        the type canonicalization hashtable, which is GC-ed, so its behavior
-        depends on the actual collection points.  Since we are building these
-        types on the fly for the debug info only, they would not be attached
-        to any GC root and always be swept, so we would make the contents of
-        the debug info depend on the collection points.  */
-      struct tree_map in, *h, **slot;
-
-      in.base.from = CONST_CAST_TREE (type);
-      in.hash = htab_hash_pointer (type);
-      slot = debug_type_hash->find_slot_with_hash (&in, in.hash, INSERT);
-      if (*slot)
-       return (*slot)->to;
-
-      tree t = build_offset_type (TYPE_PTRMEMFUNC_OBJECT_TYPE (type),
-                                 TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)));
-
-      h = ggc_alloc<tree_map> ();
-      h->base.from = CONST_CAST_TREE (type);
-      h->hash = htab_hash_pointer (type);
-      h->to = t;
-      *slot = h;
-
-      return t;
+      tree ktype = CONST_CAST_TREE (type);
+      if (debug_type_map == NULL)
+       debug_type_map = tree_cache_map::create_ggc (512);
+      else if (tree *slot = debug_type_map->get (ktype))
+       return *slot;
+      debug_type_map->put (ktype, dtype);
     }
 
-  return NULL_TREE;
+  return dtype;
 }
 
 /* Return -1 if dwarf ATTR shouldn't be added for DECL, or the attribute
index b9942066a07ce0cb81bbbda4eefe82b6db1809c6..6051348048f410f5c1e61d50dd723da33ee03111 100644 (file)
@@ -5124,7 +5124,6 @@ extern GTY(()) vec<tree, va_gc> *static_decls;
 /* An array of vtable-needing types that have no key function, or have
    an emitted key function.  */
 extern GTY(()) vec<tree, va_gc> *keyed_classes;
-
 \f
 /* Here's where we control how name mangling takes place.  */
 
index 2e356a0f09a96c9c9e68363adadf2331f368f2c4..c4eb28d14e2a9a9d51e2d05a8bc1ae49b9feb8ee 100644 (file)
@@ -7283,12 +7283,13 @@ get_tuple_decomp_init (tree decl, unsigned i)
 
 /* It's impossible to recover the decltype of a tuple decomposition variable
    based on the actual type of the variable, so store it in a hash table.  */
-static GTY(()) hash_map<tree,tree> *decomp_type_table;
+
+static GTY((cache)) tree_cache_map *decomp_type_table;
 static void
 store_decomp_type (tree v, tree t)
 {
   if (!decomp_type_table)
-    decomp_type_table = hash_map<tree,tree>::create_ggc (13);
+    decomp_type_table = tree_cache_map::create_ggc (13);
   decomp_type_table->put (v, t);
 }
 
index 1084ab1aa013a1f51f03cec977736623730adb8a..c76460d6ee6b6ffeca086cca207a7051cb7408cb 100644 (file)
@@ -535,7 +535,7 @@ perform_target_ctor (tree init)
 
 /* Return the non-static data initializer for FIELD_DECL MEMBER.  */
 
-static GTY(()) hash_map<tree, tree> *nsdmi_inst;
+static GTY((cache)) tree_cache_map *nsdmi_inst;
 
 tree
 get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
@@ -590,7 +590,7 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
          if (init != error_mark_node)
            {
              if (!nsdmi_inst)
-               nsdmi_inst = hash_map<tree,tree>::create_ggc (37);
+               nsdmi_inst = tree_cache_map::create_ggc (37);
              nsdmi_inst->put (member, init);
            }
 
index 4ca5974b1967d3cd07b310d7374e1da7879eade5..562b9272596195d35376d9f8475e6f75f57bea7c 100644 (file)
@@ -12014,7 +12014,7 @@ tsubst_aggr_type (tree t,
     }
 }
 
-static GTY(()) hash_map<tree, tree> *defarg_inst;
+static GTY((cache)) tree_cache_map *defarg_inst;
 
 /* Substitute into the default argument ARG (a default argument for
    FN), which has the indicated TYPE.  */
@@ -12101,7 +12101,7 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
   if (arg != error_mark_node && !cp_unevaluated_operand)
     {
       if (!defarg_inst)
-       defarg_inst = hash_map<tree,tree>::create_ggc (37);
+       defarg_inst = tree_cache_map::create_ggc (37);
       defarg_inst->put (parm, arg);
     }
 
index 2b5fddf2d095f070ee0ac97c3be0716dd07d2f4b..a92f0cb00f491eaf20174016ee6ed752b1cdab91 100644 (file)
@@ -32,6 +32,7 @@ template <typename H, typename Value>
 struct simple_hashmap_traits
 {
   typedef typename H::value_type key_type;
+  static const bool maybe_mx = true;
   static inline hashval_t hash (const key_type &);
   static inline bool equal_keys (const key_type &, const key_type &);
   template <typename T> static inline void remove (T &);
@@ -97,6 +98,12 @@ simple_hashmap_traits <H, Value>::mark_deleted (T &entry)
   H::mark_deleted (entry.m_key);
 }
 
+template <typename H, typename Value>
+struct simple_cache_map_traits: public simple_hashmap_traits<H,Value>
+{
+  static const bool maybe_mx = false;
+};
+
 /* Implement traits for a hash_map with values of type Value for cases
    in which the key cannot represent empty and deleted slots.  Instead
    record empty and deleted entries in Value.  Derived classes must
index 73f1c5427a0b9be426fbc4d2247d8f88ab753825..6b8365a9d0a6bc066a7780b264a519fe2e47461b 100644 (file)
@@ -62,6 +62,12 @@ class GTY((user)) hash_map
        gt_ggc_mx (e.m_value);
       }
 
+    static void ggc_maybe_mx (hash_entry &e)
+      {
+       if (Traits::maybe_mx)
+         ggc_mx (e);
+      }
+
     static void pch_nx (hash_entry &e)
       {
        gt_pch_nx (e.m_key);
@@ -74,6 +80,11 @@ class GTY((user)) hash_map
        pch_nx_helper (e.m_value, op, c);
       }
 
+    static int keep_cache_entry (hash_entry &e)
+      {
+       return ggc_marked_p (e.m_key);
+      }
+
   private:
     template<typename T>
     static void
@@ -237,7 +248,8 @@ private:
 
   template<typename T, typename U, typename V> friend void gt_ggc_mx (hash_map<T, U, V> *);
   template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *);
-      template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);
+  template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);
+  template<typename T, typename U, typename V> friend void gt_cleare_cache (hash_map<T, U, V> *);
 
   hash_table<hash_entry> m_table;
 };
@@ -258,6 +270,13 @@ gt_pch_nx (hash_map<K, V, H> *h)
   gt_pch_nx (&h->m_table);
 }
 
+template<typename K, typename V, typename H>
+static inline void
+gt_cleare_cache (hash_map<K, V, H> *h)
+{
+  gt_cleare_cache (&h->m_table);
+}
+
 template<typename K, typename V, typename H>
 static inline void
 gt_pch_nx (hash_map<K, V, H> *h, gt_pointer_operator op, void *cookie)
index 64d3157953c7b0f210aac60642da71726ba52cad..b86a1d1b27831d5b72be154963d84daab0a3784e 100644 (file)
@@ -1044,7 +1044,9 @@ gt_ggc_mx (hash_table<E> *h)
          || table::is_deleted (h->m_entries[i]))
        continue;
 
-      E::ggc_mx (h->m_entries[i]);
+      /* Use ggc_maxbe_mx so we don't mark right away for cache tables; we'll
+        mark in gt_cleare_cache if appropriate.  */
+      E::ggc_maybe_mx (h->m_entries[i]);
     }
 }
 
@@ -1094,7 +1096,6 @@ template<typename H>
 inline void
 gt_cleare_cache (hash_table<H> *h)
 {
-  extern void gt_ggc_mx (typename H::value_type &t);
   typedef hash_table<H> table;
   if (!h)
     return;
@@ -1106,7 +1107,7 @@ gt_cleare_cache (hash_table<H> *h)
        if (res == 0)
          h->clear_slot (&*iter);
        else if (res != -1)
-         gt_ggc_mx (*iter);
+         H::ggc_mx (*iter);
       }
 }
 
index a5c4f10347403238b7cd40af68d2f26dda61fb5e..6a613c45811726fe485ebadbf4ed31f92fbf89cb 100644 (file)
@@ -235,6 +235,13 @@ struct ggc_remove
     gt_ggc_mx (p);
   }
 
+  /* Overridden in ggc_cache_remove.  */
+  static void
+  ggc_maybe_mx (T &p)
+  {
+    ggc_mx (p);
+  }
+
   static void
   pch_nx (T &p)
   {
@@ -256,7 +263,7 @@ template<typename T>
 struct ggc_cache_remove : ggc_remove<T>
 {
   /* Entries are weakly held because this is for caches.  */
-  static void ggc_mx (T &) {}
+  static void ggc_maybe_mx (T &) {}
 
   static int
   keep_cache_entry (T &e)
index 277aa919780e6de7c682c221cea33f57b74b6aa3..39acffe52662d42c8086728b902323e6bcf0913b 100644 (file)
@@ -4858,6 +4858,13 @@ struct tree_decl_map_cache_hasher : ggc_cache_ptr_hash<tree_decl_map>
 #define tree_vec_map_hash tree_decl_map_hash
 #define tree_vec_map_marked_p tree_map_base_marked_p
 
+/* A hash_map of two trees for use with GTY((cache)).  Garbage collection for
+   such a map will not mark keys, and will mark values if the key is already
+   marked.  */
+struct tree_cache_traits
+  : simple_cache_map_traits<default_hash_traits<tree>, tree> { };
+typedef hash_map<tree,tree,tree_cache_traits> tree_cache_map;
+
 /* Initialize the abstract argument list iterator object ITER with the
    arguments from CALL_EXPR node EXP.  */
 static inline void