This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] [PR c++/80290] recycle tinst garbage sooner
Ok, thanks.
On Tue, Apr 17, 2018, 9:29 PM Alexandre Oliva <aoliva@redhat.com> wrote:
> 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
>