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