diff options
author | Jan Hubicka <jh@suse.cz> | 2020-09-24 08:28:09 +0200 |
---|---|---|
committer | Jan Hubicka <jh@suse.cz> | 2020-09-24 08:28:09 +0200 |
commit | c9da53d6987af5f8ff68b58dd76a9fbc900a6a21 (patch) | |
tree | e0bed9ee6fe0d60237cdb71cbae19944289b800a /gcc | |
parent | 2d5fb576bdda843da47aea2e025bb5d45e883827 (diff) | |
download | gcc-c9da53d6987af5f8ff68b58dd76a9fbc900a6a21.zip gcc-c9da53d6987af5f8ff68b58dd76a9fbc900a6a21.tar.gz gcc-c9da53d6987af5f8ff68b58dd76a9fbc900a6a21.tar.bz2 |
Fix memory allocations in ipa-modref.
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ipa-modref-tree.h | 36 | ||||
-rw-r--r-- | gcc/ipa-modref.c | 71 |
2 files changed, 65 insertions, 42 deletions
diff --git a/gcc/ipa-modref-tree.h b/gcc/ipa-modref-tree.h index 3bdd305..82e959a 100644 --- a/gcc/ipa-modref-tree.h +++ b/gcc/ipa-modref-tree.h @@ -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 (); diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c index 9cc9056..43545c1 100644 --- a/gcc/ipa-modref.c +++ b/gcc/ipa-modref.c @@ -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++])) |