This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] [PR c++/80290] recycle tinst garbage sooner


On Apr 17, 2018, Jason Merrill <jason@redhat.com> wrote:

>> Any objections to making dec_refcount_use a friend of tinst_level's?
>> Otherwise, I'd rather add a free() member function (or maybe static
>> member function) to free both the TREE_LIST and the tinst_level objects.

> Either of those sounds fine.

Here's the additional incremental patch I'm testing.

I've added a number of line breaks before opening braces in function
definitions, that had escaped my attention in the initial patch
submission.

---
 gcc/cp/cp-tree.h |    5 ++++-
 gcc/cp/mangle.c  |    2 +-
 gcc/cp/pt.c      |   56 ++++++++++++++++++++++++++++++++++++------------------
 3 files changed, 42 insertions(+), 21 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 26a50ac136dd..7031c79b35db 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5903,6 +5903,9 @@ struct GTY((chain_next ("%h.next"))) tinst_level {
   tree to_list ();
 
  public:
+  /* Release storage for OBJ and node, if it's a TREE_LIST.  */
+  static void free(tinst_level *obj);
+
   /* Return TRUE iff the original node is a list, split or not.  */
   bool list_p () const { return !not_list_p (); }
 
@@ -5916,7 +5919,7 @@ struct GTY((chain_next ("%h.next"))) tinst_level {
 
   /* Return the original node if it's a DECL or a TREE_LIST, but do
      NOT convert a split list to a TREE_LIST: return NULL instead.  */
-  tree get_decl_maybe () const {
+  tree maybe_get_node () const {
     if (!split_list_p ()) return tldcl;
     else return NULL_TREE;
   }
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 940f7ed87e20..2f65709d7d8c 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -3777,7 +3777,7 @@ mangle_decl_string (const tree decl)
   if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
     {
       struct tinst_level *tl = current_instantiation ();
-      if ((!tl || tl->get_decl_maybe () != decl)
+      if ((!tl || tl->maybe_get_node () != decl)
 	  && push_tinst_level (decl))
 	{
 	  template_p = true;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2442f07095ca..79563dfa5334 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -50,7 +50,8 @@ typedef int (*tree_fn_t) (tree, void*);
 /* The PENDING_TEMPLATES is a TREE_LIST of templates whose
    instantiations have been deferred, either because their definitions
    were not yet available, or because we were putting off doing the work.  */
-struct GTY ((chain_next ("%h.next"))) pending_template {
+struct GTY ((chain_next ("%h.next"))) pending_template
+{
   struct pending_template *next;
   struct tinst_level *tinst;
 };
@@ -8839,17 +8840,20 @@ public:
    build_tree_list logic in reinit, so this could go out of sync.  */
 template <>
 inline tree &
-freelist<tree_node>::next (tree obj) {
+freelist<tree_node>::next (tree obj)
+{
   return TREE_CHAIN (obj);
 }
 template <>
 inline tree
-freelist<tree_node>::anew () {
+freelist<tree_node>::anew ()
+{
   return build_tree_list (NULL, NULL);
 }
 template <>
 inline void
-freelist<tree_node>::poison (tree obj ATTRIBUTE_UNUSED) {
+freelist<tree_node>::poison (tree obj ATTRIBUTE_UNUSED)
+{
   int size ATTRIBUTE_UNUSED = sizeof (tree_list);
   tree p ATTRIBUTE_UNUSED = obj;
   tree_base *b ATTRIBUTE_UNUSED = &obj->base;
@@ -8878,7 +8882,8 @@ freelist<tree_node>::poison (tree obj ATTRIBUTE_UNUSED) {
 }
 template <>
 inline void
-freelist<tree_node>::reinit (tree obj ATTRIBUTE_UNUSED) {
+freelist<tree_node>::reinit (tree obj ATTRIBUTE_UNUSED)
+{
   tree_base *b ATTRIBUTE_UNUSED = &obj->base;
 
 #ifdef ENABLE_GC_CHECKING
@@ -8902,7 +8907,8 @@ freelist<tree_node>::reinit (tree obj ATTRIBUTE_UNUSED) {
 static GTY((deletable)) tree tree_list_freelist_head;
 /* Return the/an actual TREE_LIST freelist.  */
 static inline freelist<tree_node>
-tree_list_freelist () {
+tree_list_freelist ()
+{
   return tree_list_freelist_head;
 }
 
@@ -8910,7 +8916,8 @@ tree_list_freelist () {
 static GTY((deletable)) tinst_level *tinst_level_freelist_head;
 /* Return the/an actual tinst_level freelist.  */
 static inline freelist<tinst_level>
-tinst_level_freelist () {
+tinst_level_freelist ()
+{
   return tinst_level_freelist_head;
 }
 
@@ -8918,7 +8925,8 @@ tinst_level_freelist () {
 static GTY((deletable)) pending_template *pending_template_freelist_head;
 /* Return the/an actual pending_template freelist.  */
 static inline freelist<pending_template>
-pending_template_freelist () {
+pending_template_freelist ()
+{
   return pending_template_freelist_head;
 }
 
@@ -8939,7 +8947,8 @@ tinst_level::to_list ()
 
 /* Increment OBJ's refcount.  */
 static tinst_level *
-inc_refcount_use (tinst_level *obj) {
+inc_refcount_use (tinst_level *obj)
+{
   if (obj)
     {
       ++obj->refcount;
@@ -8948,18 +8957,26 @@ inc_refcount_use (tinst_level *obj) {
   return obj;
 }
 
+/* Release storage for OBJ and node, if it's a TREE_LIST.  */
+void
+tinst_level::free (tinst_level *obj)
+{
+  if (obj->tree_list_p ())
+    tree_list_freelist ().free (obj->get_node ());
+  tinst_level_freelist ().free (obj);
+}
+
 /* Decrement OBJ's refcount.  If it reaches zero, release OBJ's DECL
    and OBJ, and start over with the tinst_level object that used to be
    referenced by OBJ's NEXT.  */
 static void
-dec_refcount_use (tinst_level *obj) {
+dec_refcount_use (tinst_level *obj)
+{
   while (obj && !--obj->refcount)
     {
       gcc_assert (obj->refcount+1 != 0);
       tinst_level *next = obj->next;
-      if (obj->list_p () && obj->get_decl_maybe ())
-	tree_list_freelist ().free (obj->get_node ());
-      tinst_level_freelist ().free (obj);
+      tinst_level::free (obj);
       obj = next;
     }
 }
@@ -8971,7 +8988,8 @@ dec_refcount_use (tinst_level *obj) {
    overload resolution.  */
 template <typename T>
 static void
-set_refcount_ptr (T *& ptr, T *obj = NULL) {
+set_refcount_ptr (T *& ptr, T *obj = NULL)
+{
   T *save = ptr;
   ptr = inc_refcount_use (obj);
   dec_refcount_use (save);
@@ -8994,7 +9012,7 @@ add_pending_template (tree d)
      Compensate.  */
   gcc_assert (TREE_CODE (d) != TREE_LIST);
   level = !current_tinst_level
-    || current_tinst_level->get_decl_maybe () != d;
+    || current_tinst_level->maybe_get_node () != d;
 
   if (level)
     push_tinst_level (d);
@@ -10077,7 +10095,7 @@ limit_bad_template_recursion (tree decl)
     return false;
 
   for (; lev; lev = lev->next)
-    if (neglectable_inst_p (lev->get_decl_maybe ()))
+    if (neglectable_inst_p (lev->maybe_get_node ()))
       break;
 
   return (lev && errs > lev->errors);
@@ -10197,7 +10215,7 @@ reopen_tinst_level (struct tinst_level *level)
   pop_tinst_level ();
   if (current_tinst_level)
     current_tinst_level->errors = errorcount+sorrycount;
-  return level->get_decl_maybe ();
+  return level->maybe_get_node ();
 }
 
 /* Returns the TINST_LEVEL which gives the original instantiation
@@ -24010,7 +24028,7 @@ instantiate_pending_templates (int retries)
      to avoid infinite loop.  */
   if (pending_templates && retries >= max_tinst_depth)
     {
-      tree decl = pending_templates->tinst->get_decl_maybe ();
+      tree decl = pending_templates->tinst->maybe_get_node ();
 
       fatal_error (input_location,
 		   "template instantiation depth exceeds maximum of %d"
@@ -24351,7 +24369,7 @@ bool
 instantiating_current_function_p (void)
 {
   return (current_instantiation ()
-	  && (current_instantiation ()->get_decl_maybe ()
+	  && (current_instantiation ()->maybe_get_node ()
 	      == current_function_decl));
 }
 
-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]