On Tue, Nov 24, 2015 at 9:45 AM, Jan Hubicka <[email protected]> wrote:
> Hi,
> while looking into the earlier bug I noticed that type_hash_canon is used to
> avoid producing type duplicates. The type is however created, then looked up
> in the cache and if it exists it is never used. The function takes care to
> remove the code found memory stats but never actually free it. I suppose it
> is
> artifact of conversion from obstack to ggc. We produce a lot of type
> duplicates
> this way that is not very cool.
>
> It always bit bothered me that unify_scc does not update the statistics so
> this patch introduces free_node that can be used to free given tree node.
>
> Bootstrapped/regtested x86_64-linux, OK?
Ok.
Thanks,
Richard.
>
> * tree.c (free_node): New function.
> (type_hash_canon): Use it.
> * tree.h (free_node): Declare.
> * lto.c (unify_scc): Use free_node.
>
> Index: tree.c
> ===================================================================
> --- tree.c (revision 230718)
> +++ tree.c (working copy)
> @@ -1103,6 +1103,27 @@ make_node_stat (enum tree_code code MEM_
>
> return t;
> }
> +
> +/* Free tree node. */
> +
> +void
> +free_node (tree node)
> +{
> + enum tree_code code = TREE_CODE (node);
> + if (GATHER_STATISTICS)
> + {
> + tree_code_counts[(int) TREE_CODE (node)]--;
> + tree_node_counts[(int) t_kind]--;
> + tree_node_sizes[(int) t_kind] -= tree_code_size (TREE_CODE (node));
> + }
> + if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
> + vec_free (CONSTRUCTOR_ELTS (node));
> + else if (code == BLOCK)
> + vec_free (BLOCK_NONLOCALIZED_VARS (node));
> + else if (code == TREE_BINFO)
> + vec_free (BINFO_BASE_ACCESSES (node));
> + ggc_free (node);
> +}
>
> /* Return a new node with the same contents as NODE except that its
> TREE_CHAIN, if it has one, is zero and it has a fresh uid. */
> @@ -7100,12 +7123,7 @@ type_hash_canon (unsigned int hashcode,
> {
> tree t1 = ((type_hash *) *loc)->type;
> gcc_assert (TYPE_MAIN_VARIANT (t1) == t1);
> - if (GATHER_STATISTICS)
> - {
> - tree_code_counts[(int) TREE_CODE (type)]--;
> - tree_node_counts[(int) t_kind]--;
> - tree_node_sizes[(int) t_kind] -= sizeof (struct
> tree_type_non_common);
> - }
> + free_node (type);
> return t1;
> }
> else
> Index: tree.h
> ===================================================================
> --- tree.h (revision 230718)
> +++ tree.h (working copy)
> @@ -3763,6 +3763,10 @@ extern int allocate_decl_uid (void);
> extern tree make_node_stat (enum tree_code MEM_STAT_DECL);
> #define make_node(t) make_node_stat (t MEM_STAT_INFO)
>
> +/* Free tree node. */
> +
> +extern void free_node (tree);
> +
> /* Make a copy of a node, with all the same contents. */
>
> extern tree copy_node_stat (tree MEM_STAT_DECL);
> Index: lto/lto.c
> ===================================================================
> --- lto/lto.c (revision 230718)
> +++ lto/lto.c (working copy)
> @@ -1623,13 +1622,9 @@ unify_scc (struct data_in *data_in, unsi
> data_in->location_cache.revert_location_cache ();
> for (unsigned i = 0; i < len; ++i)
> {
> - enum tree_code code;
> if (TYPE_P (scc->entries[i]))
> num_merged_types++;
> - code = TREE_CODE (scc->entries[i]);
> - if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
> - vec_free (CONSTRUCTOR_ELTS (scc->entries[i]));
> - ggc_free (scc->entries[i]);
> + free_node (scc->entries[i]);
> }
>
> break;