This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix leaks on ipa_transform_to_apply, struct function and gimple bodies


Hi,
this patch fix memory leak on ipa_transforms_to_apply and CFG edges in
cgraph_release_function_body.  While doing it, I also added ggc_free to struct
function and gimple_df since keeping it dangling is evil; it dangle the whole
function body.

This uncovered that those indeed dangle via outer pointer in function.  This is
used to maintain nested function stack (but is initialized for C++ testcases
too). Fortunately the chains are used only by find_function_data that
is used only once to be ignored, so we can safely get rid of them.

Bootstrapped/regtested x86_64-linux (including Ada).  OK?

	* cgraph.c (cgraph_release_function_body): Plug memory leak on
	ipa_transforms_to_apply and CFG; ggc_free gimple df and struct function
	so we are sure we do not dangle it forever.
	* function.c (outer_function_chain, find_function_data): Remove.
	(function_context_stack): New.
	(push_function_context, pop_function_context): Update.
	* function.h (struct function): Remove pointer outer.
	(outer_function_chain, find_function_data): Remove.
	* stmt.c (force_label_rtx): Remove dead call of find_function_data.
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 140271)
+++ cgraph.c	(working copy)
@@ -846,21 +846,34 @@ cgraph_node_remove_callers (struct cgrap
 void
 cgraph_release_function_body (struct cgraph_node *node)
 {
-  if (DECL_STRUCT_FUNCTION (node->decl)
-      && DECL_STRUCT_FUNCTION (node->decl)->gimple_df)
+  if (DECL_STRUCT_FUNCTION (node->decl))
     {
       tree old_decl = current_function_decl;
       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
-      current_function_decl = node->decl;
-      delete_tree_ssa ();
-      delete_tree_cfg_annotations ();
-      cfun->eh = NULL;
-      gimple_set_body (node->decl, NULL);
-      current_function_decl = old_decl;
+      if (cfun->gimple_df)
+	{
+	  current_function_decl = node->decl;
+	  delete_tree_ssa ();
+	  delete_tree_cfg_annotations ();
+	  cfun->eh = NULL;
+	  current_function_decl = old_decl;
+	}
+      if (cfun->cfg)
+	{
+	  gcc_assert (dom_computed[0] == DOM_NONE);
+	  gcc_assert (dom_computed[1] == DOM_NONE);
+	  clear_edges ();
+	}
       pop_cfun();
+      gimple_set_body (node->decl, NULL);
+      VEC_free (ipa_opt_pass, heap,
+      		DECL_STRUCT_FUNCTION (node->decl)->ipa_transforms_to_apply);
+      /* Struct function hangs a lot of data that would leak if we didn't
+         removed all pointers to it.   */
+      ggc_free (DECL_STRUCT_FUNCTION (node->decl));
+      DECL_STRUCT_FUNCTION (node->decl) = NULL;
     }
   DECL_SAVED_TREE (node->decl) = NULL;
-  DECL_STRUCT_FUNCTION (node->decl) = NULL;
   DECL_INITIAL (node->decl) = error_mark_node;
 }
 
Index: function.c
===================================================================
--- function.c	(revision 140271)
+++ function.c	(working copy)
@@ -208,23 +208,14 @@ static void do_clobber_return_reg (rtx, 
 static void do_use_return_reg (rtx, void *);
 static void set_insn_locators (rtx, int) ATTRIBUTE_UNUSED;
 
-/* Pointer to chain of `struct function' for containing functions.  */
-struct function *outer_function_chain;
-
-/* Given a function decl for a containing function,
-   return the `struct function' for it.  */
-
-struct function *
-find_function_data (tree decl)
-{
-  struct function *p;
+/* Stack of nested functions.  */
+/* Keep track of the cfun stack.  */
 
-  for (p = outer_function_chain; p; p = p->outer)
-    if (p->decl == decl)
-      return p;
+typedef struct function *function_p;
 
-  gcc_unreachable ();
-}
+DEF_VEC_P(function_p);
+DEF_VEC_ALLOC_P(function_p,heap);
+static VEC(function_p,heap) *function_context_stack;
 
 /* Save the current context for compilation of a nested function.
    This is called from language-specific code.  */
@@ -235,8 +226,7 @@ push_function_context (void)
   if (cfun == 0)
     allocate_struct_function (NULL, false);
 
-  cfun->outer = outer_function_chain;
-  outer_function_chain = cfun;
+  VEC_safe_push (function_p, heap, function_context_stack, cfun);
   set_cfun (NULL);
 }
 
@@ -246,10 +236,8 @@ push_function_context (void)
 void
 pop_function_context (void)
 {
-  struct function *p = outer_function_chain;
-
+  struct function *p = VEC_pop (function_p, function_context_stack);
   set_cfun (p);
-  outer_function_chain = p->outer;
   current_function_decl = p->decl;
 
   /* Reset variables that have known state during rtx generation.  */
@@ -3904,13 +3893,6 @@ set_cfun (struct function *new_cfun)
     }
 }
 
-/* Keep track of the cfun stack.  */
-
-typedef struct function *function_p;
-
-DEF_VEC_P(function_p);
-DEF_VEC_ALLOC_P(function_p,heap);
-
 /* Initialized with NOGC, making this poisonous to the garbage collector.  */
 
 static VEC(function_p,heap) *cfun_stack;
Index: function.h
===================================================================
--- function.h	(revision 140271)
+++ function.h	(working copy)
@@ -495,9 +495,6 @@ struct function GTY(())
   /* Points to the FUNCTION_DECL of this function.  */
   tree decl;
 
-  /* Function containing this function, if any.  */
-  struct function *outer;
-
   /* A PARM_DECL that should contain the static chain for this function.
      It will be initialized at the beginning of the function.  */
   tree static_chain_decl;
@@ -610,9 +607,6 @@ extern GTY(()) struct function *cfun;
    push_cfun or set_cfun.  */
 #define cfun (cfun + 0)
 
-/* Pointer to chain of `struct function' for containing functions.  */
-extern GTY(()) struct function *outer_function_chain;
-
 /* Nonzero if we've already converted virtual regs to hard regs.  */
 extern int virtuals_instantiated;
 
@@ -633,10 +627,6 @@ extern void instantiate_decl_rtl (rtx x)
 #define n_bbs_in_dom_tree (cfun->cfg->x_n_bbs_in_dom_tree)
 #define VALUE_HISTOGRAMS(fun) (fun)->value_histograms
 
-/* Given a function decl for a containing function,
-   return the `struct function' for it.  */
-struct function *find_function_data (tree);
-
 /* Identify BLOCKs referenced by more than one NOTE_INSN_BLOCK_{BEG,END},
    and create duplicate blocks.  */
 extern void reorder_blocks (void);
Index: stmt.c
===================================================================
--- stmt.c	(revision 140271)
+++ stmt.c	(working copy)
@@ -151,15 +151,9 @@ force_label_rtx (tree label)
 {
   rtx ref = label_rtx (label);
   tree function = decl_function_context (label);
-  struct function *p;
 
   gcc_assert (function);
 
-  if (function != current_function_decl)
-    p = find_function_data (function);
-  else
-    p = cfun;
-
   forced_labels = gen_rtx_EXPR_LIST (VOIDmode, ref, forced_labels);
   return ref;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]