{"id":814410,"url":"http://patchwork.ozlabs.org/api/1.2/patches/814410/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/patch/CADzB+2n4mtiYNocfZYCE7xKwEf6aZW+QX9FdR05zf2a-9Qi4TQ@mail.gmail.com/","project":{"id":17,"url":"http://patchwork.ozlabs.org/api/1.2/projects/17/?format=json","name":"GNU Compiler Collection","link_name":"gcc","list_id":"gcc-patches.gcc.gnu.org","list_email":"gcc-patches@gcc.gnu.org","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<CADzB+2n4mtiYNocfZYCE7xKwEf6aZW+QX9FdR05zf2a-9Qi4TQ@mail.gmail.com>","list_archive_url":null,"date":"2017-09-15T21:45:13","name":"RFA (hash-map): PATCH to support GTY((cache)) with hash_map","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"8840b190ff3e93561a9ba6655c0134b2559d45fb","submitter":{"id":4337,"url":"http://patchwork.ozlabs.org/api/1.2/people/4337/?format=json","name":"Jason Merrill","email":"jason@redhat.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/gcc/patch/CADzB+2n4mtiYNocfZYCE7xKwEf6aZW+QX9FdR05zf2a-9Qi4TQ@mail.gmail.com/mbox/","series":[{"id":3390,"url":"http://patchwork.ozlabs.org/api/1.2/series/3390/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/list/?series=3390","date":"2017-09-15T21:45:13","name":"RFA (hash-map): PATCH to support GTY((cache)) with hash_map","version":1,"mbox":"http://patchwork.ozlabs.org/series/3390/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/814410/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/814410/checks/","tags":{},"related":[],"headers":{"Return-Path":"<gcc-patches-return-462304-incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list gcc-patches@gcc.gnu.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=gcc-patches-return-462304-incoming=patchwork.ozlabs.org@gcc.gnu.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tunprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org\n\theader.b=\"ZlbomE7z\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xv88z4p0Jz9sNc\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat, 16 Sep 2017 07:45:55 +1000 (AEST)","(qmail 97757 invoked by alias); 15 Sep 2017 21:45:41 -0000","(qmail 97564 invoked by uid 89); 15 Sep 2017 21:45:39 -0000","from mail-io0-f177.google.com (HELO mail-io0-f177.google.com)\n\t(209.85.223.177) by sourceware.org\n\t(qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP;\n\tFri, 15 Sep 2017 21:45:36 +0000","by mail-io0-f177.google.com with SMTP id d16so11561779ioj.3 for\n\t<gcc-patches@gcc.gnu.org>; Fri, 15 Sep 2017 14:45:36 -0700 (PDT)","by 10.107.166.140 with HTTP; Fri, 15 Sep 2017 14:45:13 -0700 (PDT)"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender\n\t:mime-version:from:date:message-id:subject:to:content-type; q=\n\tdns; s=default; b=LY+KIf8iy+16AOxnGTG/zO1VOw+hBa+tn+E3qDL+ITqXLX\n\tUl2IWLMY+tIvGUF8WhLCiTu23O/6WZ5qeAEfPgLefylw07pvJgM4QbeE2w3FVg9b\n\t8tKJIatd1GL1V4ZUO0j8RM0MRRMt0H5D0+uaH65sIdJ41ohpHdSQrzaIN3je8=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender\n\t:mime-version:from:date:message-id:subject:to:content-type; s=\n\tdefault; bh=8v6BbIoU6DqpALLB+tzmJF4S2MQ=; b=ZlbomE7z5fUCEW+B0+CF\n\tR/uXYw6jr+DikmyLN6p4N8/lltKaR2g82WnpyrVRUbDWPwcGXw/CZfU6q3lB6uSd\n\tUXdTASlw2qd8r0gdZ1vLsr+8hgQaCQebIPOOtkAt/OSRnC4WVyb53y1zBhOYWmos\n\tfdS1K8anyb+c/3TmYMgJNqk=","Mailing-List":"contact gcc-patches-help@gcc.gnu.org; run by ezmlm","Precedence":"bulk","List-Id":"<gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<mailto:gcc-patches-unsubscribe-incoming=patchwork.ozlabs.org@gcc.gnu.org>","List-Archive":"<http://gcc.gnu.org/ml/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-help@gcc.gnu.org>","Sender":"gcc-patches-owner@gcc.gnu.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-25.0 required=5.0 tests=AWL, BAYES_00,\n\tGIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3,\n\tRCVD_IN_DNSWL_NONE,\n\tRCVD_IN_SORBS_SPAM autolearn=ham version=3.3.2 spammy=MEMBER,\n\tFriend, traits, swept","X-HELO":"mail-io0-f177.google.com","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net;\n\ts=20161025;\n\th=x-gm-message-state:mime-version:from:date:message-id:subject:to;\n\tbh=v5lxp5ndFb35IcC3kX+Pqu8Huxbyrlwwtnt93g2QB7Y=;\n\tb=hlIjCcr31M/Qvoh9tdjGs31p/u83imcSskikICavXUoDo4ObnfWNXebC2zsMT52Rrh\n\t/c7kU6hBPqj0nXsf5r7a7L48iEC1eOFTFAEa0iCtHHgm5HFz2SIZizcxoAMJXqTZLrwn\n\tW9P7DHBibF7AZEvHuu+awPtQ24jab5Zdia63TDy942lqfvyw4QYYbrbDHL/465YLJxx/\n\tnepy8DGKyZu4FZ0oxiHoUIAgughKk+dn2RdsjdgKtR5yFf9OlC0G6FQ6HZ0NQPQdcdJN\n\tJ1nxInpQMeO1VdJaQzXTE1Tz/e686At6AY6tc29e+tna5g5szZ7yn49y3PlZCMcDZZCj\n\tR0+g==","X-Gm-Message-State":"AHPjjUjGih88CxWCx3P7AUOq7LGg8//3EfDGF6xSSMILpaKXVapKGe2c\tPw7MBDhg3yMNPTQZAQiuGFWW8/OW7ztD0sNywqJp78ldsIQ=","X-Google-Smtp-Source":"AOwi7QARDICkTILEDEZU1zLkyUk7inpK5yXRQ9q//RhMQoBSyCiQEL3XzOC4PmrdU6fqeTPvwTczHilx+fru41t/1II=","X-Received":"by 10.107.69.20 with SMTP id s20mr3777462ioa.113.1505511934453;\n\tFri, 15 Sep 2017 14:45:34 -0700 (PDT)","MIME-Version":"1.0","From":"Jason Merrill <jason@redhat.com>","Date":"Fri, 15 Sep 2017 17:45:13 -0400","Message-ID":"<CADzB+2n4mtiYNocfZYCE7xKwEf6aZW+QX9FdR05zf2a-9Qi4TQ@mail.gmail.com>","Subject":"RFA (hash-map): PATCH to support GTY((cache)) with hash_map","To":"gcc-patches List <gcc-patches@gcc.gnu.org>","Content-Type":"multipart/mixed; boundary=\"089e082866a80f313b0559415024\"","X-IsSubscribed":"yes"},"content":"The hash_map interface is a lot more convenient than that of\nhash_table for cases where it makes sense, but there hasn't been a way\nto get the ggc_cache_remove behavior with a hash_map.  In other words,\nnot marking elements during the initial ggc marking phase, but maybe\nmarking them during the clear_caches phase based on keep_cache_entry.\n\nThis patch implements that by:\n\nAdding a ggc_maybe_mx member function to ggc_remove, and overriding\nthat instead of ggc_mx in ggc_cache_remove.\nCalling H::ggc_maybe_mx instead of H::ggc_mx in gt_ggc_mx (hash_table *).\nCalling H::ggc_mx in gt_cleare_caches (hash_table *) rather than\nrelying on an extern declaration of a plain function that cannot be\ndeclared for hash_map::hash_entry.\nAdding ggc_maybe_mx and keep_cache_entry to hash_map::hash_entry.\nAdding gt_cleare_cache for hash_map.\nAdding a boolean constant to the hash-map traits indicating whether we\nwant the cache behavior above.\n\nI then define a typedef tree_cache_map to use this functionality, and\nuse it in a few places in the C++ front end.\n\nTested x86_64-pc-linux-gnu, OK for trunk?\ncommit 29a77538437442915ecb85516e3710c918d0e8ac\nAuthor: Jason Merrill <jason@redhat.com>\nDate:   Wed Sep 13 14:33:33 2017 -0400\n\n            Support GTY((cache)) on hash_map.\n    \n    gcc/\n            * hash-traits.h (ggc_remove): Add ggc_maybe_mx member function.\n            (ggc_cache_remove): Override it instead of ggc_mx.\n            * hash-table.h (gt_ggc_mx): Call it instead of ggc_mx.\n            (gt_cleare_cache): Call ggc_mx instead of gt_ggc_mx.\n            * hash-map-traits.h (simple_hashmap_traits): Add maybe_mx member.\n            (simple_cache_map_traits): Override maybe_mx.\n            * hash-map.h (hash_entry): Add ggc_maybe_mx and keep_cache_entry.\n            (hash_map): Friend gt_cleare_cache.\n            (gt_cleare_cache): New.\n            * tree.h (tree_cache_traits): New hash_map traits class.\n            (tree_cache_map): New typedef.\n    gcc/cp/\n            * decl.c (decomp_type_table): Use tree_cache_map.\n            * init.c (nsdmi_inst): Likewise.\n            * pt.c (defarg_ints): Likewise.\n            * cp-objcp-common.c (cp_get_debug_type): Likewise.","diff":"diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c\nindex 183e7f7bf57..27f0b985378 100644\n--- a/gcc/cp/cp-objcp-common.c\n+++ b/gcc/cp/cp-objcp-common.c\n@@ -131,19 +131,7 @@ cxx_types_compatible_p (tree x, tree y)\n   return same_type_ignoring_top_level_qualifiers_p (x, y);\n }\n \n-struct debug_type_hasher : ggc_cache_ptr_hash<tree_map>\n-{\n-  static hashval_t hash (tree_map *m) { return tree_map_hash (m); }\n-  static bool equal (tree_map *a, tree_map *b) { return tree_map_eq (a, b); }\n-\n-  static int\n-  keep_cache_entry (tree_map *&e)\n-  {\n-    return ggc_marked_p (e->base.from);\n-  }\n-};\n-\n-static GTY((cache)) hash_table<debug_type_hasher> *debug_type_hash;\n+static GTY((cache)) tree_cache_map *debug_type_map;\n \n /* Return a type to use in the debug info instead of TYPE, or NULL_TREE to\n    keep TYPE.  */\n@@ -151,38 +139,29 @@ static GTY((cache)) hash_table<debug_type_hasher> *debug_type_hash;\n tree\n cp_get_debug_type (const_tree type)\n {\n+  tree dtype = NULL_TREE;\n+\n   if (TYPE_PTRMEMFUNC_P (type) && !typedef_variant_p (type))\n+    dtype = build_offset_type (TYPE_PTRMEMFUNC_OBJECT_TYPE (type),\n+\t\t\t       TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)));\n+\n+  /* We cannot simply return the debug type here because the function uses\n+     the type canonicalization hashtable, which is GC-ed, so its behavior\n+     depends on the actual collection points.  Since we are building these\n+     types on the fly for the debug info only, they would not be attached\n+     to any GC root and always be swept, so we would make the contents of\n+     the debug info depend on the collection points.  */\n+  if (dtype)\n     {\n-      if (debug_type_hash == NULL)\n-\tdebug_type_hash = hash_table<debug_type_hasher>::create_ggc (512);\n-\n-      /* We cannot simply use build_offset_type here because the function uses\n-\t the type canonicalization hashtable, which is GC-ed, so its behavior\n-\t depends on the actual collection points.  Since we are building these\n-\t types on the fly for the debug info only, they would not be attached\n-\t to any GC root and always be swept, so we would make the contents of\n-\t the debug info depend on the collection points.  */\n-      struct tree_map in, *h;\n-\n-      in.base.from = CONST_CAST_TREE (type);\n-      in.hash = htab_hash_pointer (type);\n-      h = debug_type_hash->find_with_hash (&in, in.hash);\n-      if (h)\n-\treturn h->to;\n-\n-      tree t = build_offset_type (TYPE_PTRMEMFUNC_OBJECT_TYPE (type),\n-\t\t\t\t  TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)));\n-\n-      h = ggc_alloc<tree_map> ();\n-      h->base.from = CONST_CAST_TREE (type);\n-      h->hash = htab_hash_pointer (type);\n-      h->to = t;\n-      *debug_type_hash->find_slot_with_hash (h, h->hash, INSERT) = h;\n-\n-      return t;\n+      tree ktype = CONST_CAST_TREE (type);\n+      if (debug_type_map == NULL)\n+\tdebug_type_map = tree_cache_map::create_ggc (512);\n+      else if (tree *slot = debug_type_map->get (ktype))\n+\treturn *slot;\n+      debug_type_map->put (ktype, dtype);\n     }\n \n-  return NULL_TREE;\n+  return dtype;\n }\n \n /* Return -1 if dwarf ATTR shouldn't be added for DECL, or the attribute\ndiff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h\nindex f4d6f802cbe..06a4a7d22cc 100644\n--- a/gcc/cp/cp-tree.h\n+++ b/gcc/cp/cp-tree.h\n@@ -5117,7 +5117,6 @@ extern GTY(()) vec<tree, va_gc> *static_decls;\n /* An array of vtable-needing types that have no key function, or have\n    an emitted key function.  */\n extern GTY(()) vec<tree, va_gc> *keyed_classes;\n-\n \f\n /* Here's where we control how name mangling takes place.  */\n \ndiff --git a/gcc/cp/decl.c b/gcc/cp/decl.c\nindex 6101bdf2bc8..bfb0ebe9642 100644\n--- a/gcc/cp/decl.c\n+++ b/gcc/cp/decl.c\n@@ -7303,12 +7303,13 @@ get_tuple_decomp_init (tree decl, unsigned i)\n \n /* It's impossible to recover the decltype of a tuple decomposition variable\n    based on the actual type of the variable, so store it in a hash table.  */\n-static GTY(()) hash_map<tree,tree> *decomp_type_table;\n+\n+static GTY((cache)) tree_cache_map *decomp_type_table;\n static void\n store_decomp_type (tree v, tree t)\n {\n   if (!decomp_type_table)\n-    decomp_type_table = hash_map<tree,tree>::create_ggc (13);\n+    decomp_type_table = tree_cache_map::create_ggc (13);\n   decomp_type_table->put (v, t);\n }\n \ndiff --git a/gcc/cp/init.c b/gcc/cp/init.c\nindex b01d662fef2..d6241d29379 100644\n--- a/gcc/cp/init.c\n+++ b/gcc/cp/init.c\n@@ -535,7 +535,7 @@ perform_target_ctor (tree init)\n \n /* Return the non-static data initializer for FIELD_DECL MEMBER.  */\n \n-static GTY(()) hash_map<tree, tree> *nsdmi_inst;\n+static GTY((cache)) tree_cache_map *nsdmi_inst;\n \n tree\n get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)\n@@ -590,7 +590,7 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)\n \t  if (init != error_mark_node)\n \t    {\n \t      if (!nsdmi_inst)\n-\t\tnsdmi_inst = hash_map<tree,tree>::create_ggc (37);\n+\t\tnsdmi_inst = tree_cache_map::create_ggc (37);\n \t      nsdmi_inst->put (member, init);\n \t    }\n \ndiff --git a/gcc/cp/pt.c b/gcc/cp/pt.c\nindex ec7bbc890c6..aa158dc939d 100644\n--- a/gcc/cp/pt.c\n+++ b/gcc/cp/pt.c\n@@ -12008,7 +12008,7 @@ tsubst_aggr_type (tree t,\n     }\n }\n \n-static GTY(()) hash_map<tree, tree> *defarg_inst;\n+static GTY((cache)) tree_cache_map *defarg_inst;\n \n /* Substitute into the default argument ARG (a default argument for\n    FN), which has the indicated TYPE.  */\n@@ -12095,7 +12095,7 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,\n   if (arg != error_mark_node && !cp_unevaluated_operand)\n     {\n       if (!defarg_inst)\n-\tdefarg_inst = hash_map<tree,tree>::create_ggc (37);\n+\tdefarg_inst = tree_cache_map::create_ggc (37);\n       defarg_inst->put (parm, arg);\n     }\n \ndiff --git a/gcc/hash-map-traits.h b/gcc/hash-map-traits.h\nindex 2b5fddf2d09..a92f0cb00f4 100644\n--- a/gcc/hash-map-traits.h\n+++ b/gcc/hash-map-traits.h\n@@ -32,6 +32,7 @@ template <typename H, typename Value>\n struct simple_hashmap_traits\n {\n   typedef typename H::value_type key_type;\n+  static const bool maybe_mx = true;\n   static inline hashval_t hash (const key_type &);\n   static inline bool equal_keys (const key_type &, const key_type &);\n   template <typename T> static inline void remove (T &);\n@@ -97,6 +98,12 @@ simple_hashmap_traits <H, Value>::mark_deleted (T &entry)\n   H::mark_deleted (entry.m_key);\n }\n \n+template <typename H, typename Value>\n+struct simple_cache_map_traits: public simple_hashmap_traits<H,Value>\n+{\n+  static const bool maybe_mx = false;\n+};\n+\n /* Implement traits for a hash_map with values of type Value for cases\n    in which the key cannot represent empty and deleted slots.  Instead\n    record empty and deleted entries in Value.  Derived classes must\ndiff --git a/gcc/hash-map.h b/gcc/hash-map.h\nindex 73f1c5427a0..6b8365a9d0a 100644\n--- a/gcc/hash-map.h\n+++ b/gcc/hash-map.h\n@@ -62,6 +62,12 @@ class GTY((user)) hash_map\n \tgt_ggc_mx (e.m_value);\n       }\n \n+    static void ggc_maybe_mx (hash_entry &e)\n+      {\n+\tif (Traits::maybe_mx)\n+\t  ggc_mx (e);\n+      }\n+\n     static void pch_nx (hash_entry &e)\n       {\n \tgt_pch_nx (e.m_key);\n@@ -74,6 +80,11 @@ class GTY((user)) hash_map\n \tpch_nx_helper (e.m_value, op, c);\n       }\n \n+    static int keep_cache_entry (hash_entry &e)\n+      {\n+\treturn ggc_marked_p (e.m_key);\n+      }\n+\n   private:\n     template<typename T>\n     static void\n@@ -237,7 +248,8 @@ private:\n \n   template<typename T, typename U, typename V> friend void gt_ggc_mx (hash_map<T, U, V> *);\n   template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *);\n-      template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);\n+  template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);\n+  template<typename T, typename U, typename V> friend void gt_cleare_cache (hash_map<T, U, V> *);\n \n   hash_table<hash_entry> m_table;\n };\n@@ -260,6 +272,13 @@ gt_pch_nx (hash_map<K, V, H> *h)\n \n template<typename K, typename V, typename H>\n static inline void\n+gt_cleare_cache (hash_map<K, V, H> *h)\n+{\n+  gt_cleare_cache (&h->m_table);\n+}\n+\n+template<typename K, typename V, typename H>\n+static inline void\n gt_pch_nx (hash_map<K, V, H> *h, gt_pointer_operator op, void *cookie)\n {\n   op (&h->m_table.m_entries, cookie);\ndiff --git a/gcc/hash-table.h b/gcc/hash-table.h\nindex 64d3157953c..b86a1d1b278 100644\n--- a/gcc/hash-table.h\n+++ b/gcc/hash-table.h\n@@ -1044,7 +1044,9 @@ gt_ggc_mx (hash_table<E> *h)\n \t  || table::is_deleted (h->m_entries[i]))\n \tcontinue;\n \n-      E::ggc_mx (h->m_entries[i]);\n+      /* Use ggc_maxbe_mx so we don't mark right away for cache tables; we'll\n+\t mark in gt_cleare_cache if appropriate.  */\n+      E::ggc_maybe_mx (h->m_entries[i]);\n     }\n }\n \n@@ -1094,7 +1096,6 @@ template<typename H>\n inline void\n gt_cleare_cache (hash_table<H> *h)\n {\n-  extern void gt_ggc_mx (typename H::value_type &t);\n   typedef hash_table<H> table;\n   if (!h)\n     return;\n@@ -1106,7 +1107,7 @@ gt_cleare_cache (hash_table<H> *h)\n \tif (res == 0)\n \t  h->clear_slot (&*iter);\n \telse if (res != -1)\n-\t  gt_ggc_mx (*iter);\n+\t  H::ggc_mx (*iter);\n       }\n }\n \ndiff --git a/gcc/hash-traits.h b/gcc/hash-traits.h\nindex a5c4f103474..6a613c45811 100644\n--- a/gcc/hash-traits.h\n+++ b/gcc/hash-traits.h\n@@ -235,6 +235,13 @@ struct ggc_remove\n     gt_ggc_mx (p);\n   }\n \n+  /* Overridden in ggc_cache_remove.  */\n+  static void\n+  ggc_maybe_mx (T &p)\n+  {\n+    ggc_mx (p);\n+  }\n+\n   static void\n   pch_nx (T &p)\n   {\n@@ -256,7 +263,7 @@ template<typename T>\n struct ggc_cache_remove : ggc_remove<T>\n {\n   /* Entries are weakly held because this is for caches.  */\n-  static void ggc_mx (T &) {}\n+  static void ggc_maybe_mx (T &) {}\n \n   static int\n   keep_cache_entry (T &e)\ndiff --git a/gcc/tree.h b/gcc/tree.h\nindex caa4a69977d..6845953c09c 100644\n--- a/gcc/tree.h\n+++ b/gcc/tree.h\n@@ -4873,6 +4873,13 @@ struct tree_decl_map_cache_hasher : ggc_cache_ptr_hash<tree_decl_map>\n #define tree_vec_map_hash tree_decl_map_hash\n #define tree_vec_map_marked_p tree_map_base_marked_p\n \n+/* A hash_map of two trees for use with GTY((cache)).  Garbage collection for\n+   such a map will not mark keys, and will mark values if the key is already\n+   marked.  */\n+struct tree_cache_traits\n+  : simple_cache_map_traits<default_hash_traits<tree>, tree> { };\n+typedef hash_map<tree,tree,tree_cache_traits> tree_cache_map;\n+\n /* Initialize the abstract argument list iterator object ITER with the\n    arguments from CALL_EXPR node EXP.  */\n static inline void\n","prefixes":[]}