diff options
author | Jason Merrill <jason@redhat.com> | 2019-06-10 15:32:34 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2019-06-10 15:32:34 -0400 |
commit | 620adbec08f9483d73b1f1e1edcd2f181a213a3c (patch) | |
tree | c3552ddc778bab30df301e0a6fa24c0b56f3a7e6 | |
parent | 9b9eb42a4168c342e5cd71b13d21e63ba7e1b7ab (diff) | |
download | gcc-620adbec08f9483d73b1f1e1edcd2f181a213a3c.zip gcc-620adbec08f9483d73b1f1e1edcd2f181a213a3c.tar.gz gcc-620adbec08f9483d73b1f1e1edcd2f181a213a3c.tar.bz2 |
constexpr.c (free_constructor): New.
* constexpr.c (free_constructor): New.
(cxx_eval_call_expression): Free parameter value CONSTRUCTORs.
From-SVN: r272127
-rw-r--r-- | gcc/cp/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 44 |
2 files changed, 45 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 93d5f49..084e623 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2019-06-10 Jason Merrill <jason@redhat.com> + * constexpr.c (free_constructor): New. + (cxx_eval_call_expression): Free parameter value CONSTRUCTORs. + * constexpr.c (unshare_constructor): Only unshare if T is itself a CONSTRUCTOR. (cxx_eval_call_expression): Don't call it on the result here. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index d7adb46..a2f2969 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1350,6 +1350,30 @@ unshare_constructor (tree t) return t; } +/* If T is a CONSTRUCTOR, ggc_free T and any sub-CONSTRUCTORs. */ + +static void +free_constructor (tree t) +{ + if (!t || TREE_CODE (t) != CONSTRUCTOR) + return; + releasing_vec ctors; + vec_safe_push (ctors, t); + while (!ctors->is_empty ()) + { + tree c = ctors->pop (); + if (vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (c)) + { + constructor_elt *ce; + for (HOST_WIDE_INT i = 0; vec_safe_iterate (elts, i, &ce); ++i) + if (TREE_CODE (ce->value) == CONSTRUCTOR) + vec_safe_push (ctors, ce->value); + ggc_free (elts); + } + ggc_free (c); + } +} + /* Subroutine of cxx_eval_call_expression. We are processing a call expression (either CALL_EXPR or AGGR_INIT_EXPR) in the context of CTX. Evaluate @@ -1398,7 +1422,8 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, if (!*non_constant_p) { - /* Don't share a CONSTRUCTOR that might be changed. */ + /* Unsharing here isn't necessary for correctness, but it + significantly improves memory performance for some reason. */ arg = unshare_constructor (arg); /* Make sure the binding has the same type as the parm. But only for constant args. */ @@ -1733,7 +1758,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, void preserve () { do_free = false; } ~free_bindings () { if (do_free) - ggc_free (bindings); + { + for (int i = 0; i < TREE_VEC_LENGTH (bindings); ++i) + free_constructor (TREE_VEC_ELT (bindings, i)); + ggc_free (bindings); + } } } fb (new_call.bindings); @@ -1804,6 +1833,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, else { tree body, parms, res; + releasing_vec ctors; /* Reuse or create a new unshared copy of this function's body. */ tree copy = get_fundef_copy (new_call.fundef); @@ -1819,6 +1849,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, tree arg = TREE_VEC_ELT (bound, i); /* Don't share a CONSTRUCTOR that might be changed. */ arg = unshare_constructor (arg); + if (TREE_CODE (arg) == CONSTRUCTOR) + vec_safe_push (ctors, arg); ctx->values->put (remapped, arg); remapped = DECL_CHAIN (remapped); } @@ -1884,6 +1916,14 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, for (tree parm = parms; parm; parm = TREE_CHAIN (parm)) ctx->values->remove (parm); + /* Free any parameter CONSTRUCTORs we aren't returning directly. */ + while (!ctors->is_empty ()) + { + tree c = ctors->pop (); + if (c != result) + free_constructor (c); + } + /* Make the unshared function copy we used available for re-use. */ save_fundef_copy (fun, copy); } |