get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.2/patches/814410/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 814410,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/814410/?format=api",
    "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=api",
        "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=api",
        "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=api",
            "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": []
}