Fix memory allocations in ipa-modref.
authorJan Hubicka <jh@suse.cz>
Thu, 24 Sep 2020 06:28:09 +0000 (08:28 +0200)
committerJan Hubicka <jh@suse.cz>
Thu, 24 Sep 2020 06:28:09 +0000 (08:28 +0200)
Pair ggc_delete with ggc_alloc_no_dtor.  I copy same scheme as used by Martin
in ipa-fnsummary, that is creating a static member function create_ggc hidding
the ugly bits and using it in ipa-modref.c.

I also noticed that modref-tree leaks memory on destruction/collapse method and
fixed that.

Bootstrapped/regtested x86_64-linux.

gcc/ChangeLog:

2020-09-24  Jan Hubicka  <hubicka@ucw.cz>

* ipa-modref-tree.h (modref_base::collapse): Release memory.
(modref_tree::create_ggc): New member function.
(modref_tree::colapse): Release memory.
(modref_tree::~modref_tree): New destructor.
* ipa-modref.c (modref_summaries::create_ggc): New function.
(analyze_function): Use create_ggc.
(modref_summaries::duplicate): Likewise.
(read_modref_records): Likewise.
(modref_read): Likewise.

gcc/ipa-modref-tree.h
gcc/ipa-modref.c

index 3bdd3058aa1d7d31a736306f42c09e43773951e8..82e959a7d46590c3cc273a49a8000a1a6492b6ff 100644 (file)
@@ -95,7 +95,15 @@ struct GTY((user)) modref_base_node
 
   void collapse ()
   {
-    vec_free (refs);
+    size_t i;
+    modref_ref_node <T> *r;
+
+    if (refs)
+      {
+       FOR_EACH_VEC_SAFE_ELT (refs, i, r)
+         ggc_free (r);
+       vec_free (refs);
+      }
     refs = NULL;
     every_ref = true;
   }
@@ -214,12 +222,36 @@ struct GTY((user)) modref_tree
     return NULL;
   }
 
+  /* Return ggc allocated instance.  We explicitly call destructors via
+     ggc_delete and do not want finalizers to be registered and
+     called at the garbage collection time.  */
+  static modref_tree<T> *create_ggc (size_t max_bases, size_t max_refs)
+  {
+    return new (ggc_alloc_no_dtor<modref_tree<T>> ())
+        modref_tree<T> (max_bases, max_refs);
+  }
+
   void collapse ()
   {
-    vec_free (bases);
+    size_t i;
+    modref_base_node <T> *n;
+
+    if (bases)
+      {
+       FOR_EACH_VEC_SAFE_ELT (bases, i, n)
+         {
+           n->collapse ();
+           ggc_free (n);
+         }
+       vec_free (bases);
+      }
     bases = NULL;
     every_base = true;
   }
+  ~modref_tree ()
+  {
+    collapse ();
+  }
 };
 
 void modref_c_tests ();
index 9cc9056589116e3d449af8a04eaf01d60d923cdd..43545c1fb09b5d2de360463cd2904b2086943099 100644 (file)
@@ -84,6 +84,11 @@ public:
      ipa-modref pass execution needs to be analyzed in IPA mode while all
      other insertions leads to normal analysis.  */
   bool ipa;
+  static modref_summaries *create_ggc (symbol_table *symtab)
+  {
+    return new (ggc_alloc_no_dtor<modref_summaries> ())
+            modref_summaries (symtab);
+  }
 };
 
 /* Global variable holding all modref summaries.  */
@@ -608,8 +613,7 @@ analyze_function (function *f, bool ipa)
 
   /* Initialize the summary.  */
   if (!summaries)
-    summaries = new (ggc_alloc <modref_summaries> ())
-                    modref_summaries (symtab);
+    summaries = modref_summaries::create_ggc (symtab);
   else /* Remove existing summary if we are re-running the pass.  */
     summaries->remove (cgraph_node::get (f->decl));
 
@@ -633,28 +637,22 @@ analyze_function (function *f, bool ipa)
   if (nolto)
     {
       gcc_assert (!summary->loads);
-      summary->loads
-        = new (ggc_alloc <modref_tree<alias_set_type> > ())
-               modref_records (param_modref_max_bases,
-                               param_modref_max_refs);
+      summary->loads = modref_records::create_ggc (param_modref_max_bases,
+                                                  param_modref_max_refs);
       gcc_assert (!summary->stores);
-      summary->stores
-        = new (ggc_alloc <modref_tree<alias_set_type> > ())
-               modref_records (param_modref_max_bases,
-                               param_modref_max_refs);
+      summary->stores = modref_records::create_ggc (param_modref_max_bases,
+                                                   param_modref_max_refs);
     }
   if (lto)
     {
       gcc_assert (!summary->loads_lto);
-      summary->loads_lto
-        = new (ggc_alloc <modref_tree<tree> > ())
-               modref_records_lto (param_modref_max_bases,
-                                   param_modref_max_refs);
+      summary->loads_lto = modref_records_lto::create_ggc
+                                (param_modref_max_bases,
+                                 param_modref_max_refs);
       gcc_assert (!summary->stores_lto);
-      summary->stores_lto
-        = new (ggc_alloc <modref_tree<tree> > ())
-               modref_records_lto (param_modref_max_bases,
-                                   param_modref_max_refs);
+      summary->stores_lto = modref_records_lto::create_ggc
+                                (param_modref_max_bases,
+                                 param_modref_max_refs);
     }
   summary->finished = false;
   int ecf_flags = flags_from_decl_or_type (current_function_decl);
@@ -730,34 +728,30 @@ modref_summaries::duplicate (cgraph_node *, cgraph_node *,
   dst_data->finished = src_data->finished;
   if (src_data->stores)
     {
-      dst_data->stores = new (ggc_alloc <modref_tree<alias_set_type> > ())
-                             modref_records
-                                (src_data->stores->max_bases,
-                                 src_data->stores->max_refs);
+      dst_data->stores = modref_records::create_ggc
+                           (src_data->stores->max_bases,
+                            src_data->stores->max_refs);
       dst_data->stores->merge (src_data->stores);
     }
   if (src_data->loads)
     {
-      dst_data->loads = new (ggc_alloc <modref_tree<alias_set_type> > ())
-                            modref_records
-                               (src_data->loads->max_bases,
-                                src_data->loads->max_refs);
+      dst_data->loads = modref_records::create_ggc
+                           (src_data->loads->max_bases,
+                            src_data->loads->max_refs);
       dst_data->loads->merge (src_data->loads);
     }
   if (src_data->stores_lto)
     {
-      dst_data->stores_lto = new (ggc_alloc <modref_tree<tree> > ())
-                                 modref_records_lto
-                                   (src_data->stores_lto->max_bases,
-                                    src_data->stores_lto->max_refs);
+      dst_data->stores_lto = modref_records_lto::create_ggc
+                           (src_data->stores_lto->max_bases,
+                            src_data->stores_lto->max_refs);
       dst_data->stores_lto->merge (src_data->stores_lto);
     }
   if (src_data->loads_lto)
     {
-      dst_data->loads_lto = new (ggc_alloc <modref_tree<tree> > ())
-                                 modref_records_lto
-                                   (src_data->stores_lto->max_bases,
-                                    src_data->stores_lto->max_refs);
+      dst_data->loads_lto = modref_records_lto::create_ggc
+                           (src_data->loads_lto->max_bases,
+                            src_data->loads_lto->max_refs);
       dst_data->loads_lto->merge (src_data->loads_lto);
     }
 }
@@ -838,11 +832,9 @@ read_modref_records (lto_input_block *ib, struct data_in *data_in,
   /* Decide whether we want to turn LTO data types to non-LTO (i.e. when
      LTO re-streaming is not going to happen).  */
   if (flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO)
-    *lto_ret = new (ggc_alloc <modref_records_lto> ()) modref_records_lto
-                             (max_bases, max_refs);
+    *lto_ret = modref_records_lto::create_ggc (max_bases, max_refs);
   else
-    *nolto_ret = new (ggc_alloc <modref_records> ()) modref_records
-                             (max_bases, max_refs);
+    *nolto_ret = modref_records::create_ggc (max_bases, max_refs);
 
   size_t every_base = streamer_read_uhwi (ib);
   size_t nbase = streamer_read_uhwi (ib);
@@ -1048,8 +1040,7 @@ modref_read (void)
   unsigned int j = 0;
 
   if (!summaries)
-    summaries = new (ggc_alloc <modref_summaries> ())
-                    modref_summaries (symtab);
+    summaries = modref_summaries::create_ggc (symtab);
   ((modref_summaries *)summaries)->ipa = true;
 
   while ((file_data = file_data_vec[j++]))