On Thu, Mar 3, 2016 at 9:16 AM, Patrick Palka <patr...@parcs.ath.cx> wrote:
> push_to_top_level gets called fairly frequently in template-heavy code
> that performs a lot of instantiations, and we currently "leak" a lot of
> GC memory when compiling such code since [push|pop]_to_top_level() do
> not bother reusing or even freeing each saved_scope structure it
> allocates.
>
> This patch makes push_to_top_level() reuse the saved_scope structures it
> allocates.  This is similar to how begin_scope() reuses the
> cp_binding_level structures it allocates.
>
> This patch reduces the maximum memory usage of the compiler by 4.5%,
> from 525MB to 500MB, when compiling the Boost::Fusion test file
> libs/fusion/test/compile_time/transform.cpp from the Boost 1.60 testsuite.
>
> Bootstrapped and tested on x86_64-pc-linux-gnu, OK for
> trunk or for GCC 7?
>
> gcc/cp/ChangeLog:
>
>         * name-lookup.c (free_saved_scope): New free list of saved_scope
>         structures.
>         (push_to_top_level): Attempt to reuse a saved_scope struct
>         from free_saved_scope instead of allocating a new one each time.
>         (pop_from_top_level_1): Chain the now-unused saved_scope structure
>         onto free_saved_scope.
> ---
>  gcc/cp/name-lookup.c | 25 ++++++++++++++++++++++++-
>  1 file changed, 24 insertions(+), 1 deletion(-)
>
> diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
> index 89d84d7..3478b6a 100644
> --- a/gcc/cp/name-lookup.c
> +++ b/gcc/cp/name-lookup.c
> @@ -6134,6 +6134,10 @@ store_class_bindings (vec<cp_class_binding, va_gc> 
> *names,
>    timevar_cond_stop (TV_NAME_LOOKUP, subtime);
>  }
>
> +/* A chain of saved_scope structures awaiting reuse.  */
> +
> +static GTY((deletable)) struct saved_scope *free_saved_scope;
> +
>  void
>  push_to_top_level (void)
>  {
> @@ -6144,7 +6148,21 @@ push_to_top_level (void)
>    bool need_pop;
>
>    bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
> -  s = ggc_cleared_alloc<saved_scope> ();
> +
> +  /* Reuse or create a new structure for this saved scope.  */
> +  if (free_saved_scope != NULL)
> +    {
> +      s = free_saved_scope;
> +      free_saved_scope = s->prev;
> +
> +      vec<cxx_saved_binding, va_gc> *old_bindings = s->old_bindings;
> +      memset (s, 0, sizeof (*s));
> +      /* Also reuse the structure's old_bindings vector.  */
> +      vec_safe_truncate (old_bindings, 0);
> +      s->old_bindings = old_bindings;
> +    }
> +  else
> +    s = ggc_cleared_alloc<saved_scope> ();
>
>    b = scope_chain ? current_binding_level : 0;
>
> @@ -6237,6 +6255,11 @@ pop_from_top_level_1 (void)
>    current_function_decl = s->function_decl;
>    cp_unevaluated_operand = s->unevaluated_operand;
>    c_inhibit_evaluation_warnings = s->inhibit_evaluation_warnings;
> +
> +  /* Make this saved_scope structure available for reuse by
> +     push_to_top_level.  */
> +  s->prev = free_saved_scope;
> +  free_saved_scope = s;
>  }
>
>  /* Wrapper for pop_from_top_level_1.  */
> --
> 2.8.0.rc0.11.g9bfbc33
>

Ping.

Reply via email to