On Fri, Aug 29, 2014 at 07:58:14PM +0200, Richard Biener wrote:
> On August 29, 2014 5:29:43 PM CEST, Basile Starynkevitch 
> <bas...@starynkevitch.net> wrote:
> >Hello All,
> >
> >[[I know that this is a sensitive issue, and I also know that I am in
> >the minority believing that a garbage collection is useful inside the
> >GCC compiler]]
> >
> >How should plugins deal with data that is explicitly gcc_free-d outside
> >of ggc_collect?
> >
> >In particular, plugins are apparently allowed to have their own GTY-ed
> >data (which is very good, I certainly don't want that feature to
> >disappear). I'm particularly thinking of "static analysis" (or
> >"observing") plugins, which would take advantage of the GCC compiler to
> >add some extra measures and analysis but which won't change anything
> >observable in the GCC internal representations (e.g. plugins that won't
> >add or remove any Gimple inside existing functions, for instance).
> >
> >I believe that such "observing" plugins should certainly be allowed to
> >register a pass which would put some data (e.g. tree-s or
> >basic_block-s)
> >inside some GTY-ed variable and examine it much later, perhaps even at
> >PLUGIN_FINISH time (and certainly at PLUGIN_FINISH_UNIT time). This
> >would make sense if such a plugin would like to make some detailed
> >statistics, serialize *some* of the Gimple or Tree-s in a database,
> >etc.
> >
> >However, such a plugin could crash, because at several occasions
> >ggc_free is *forcibly* called *outside* of the garbage collector - and
> >there is no mechanism (finalization, plugin hooks) to communicate that
> >deletion to the plugin. So such a plugin will keep a *stale* data
> >referenced by its GTY-ed roots.
> >
> >I have a concrete example within my MELT branch -currently close to GCC
> >4.9-  & plugin (see http://gcc-melt.org/ if you never heard of MELT).
> >the justcountipa pass I have in file gcc/melt/xtramelt-ana-simple.melt
> >near lines 840 and following. It stores some global MELT data singleton
> >of CLASS_JUSTCOUNTIPA_DATA in the MELT pass, and that data stays
> >available, so is never freed by the GGC. Unfortunately, that data
> >contains (very indirectly) some tree-s and edge-s which have been
> >*explicitly* ggc_free-d, e.g. by execute_todo calling indirectly
> >cleanup_tree_cfg calling indirectly free_edge.
> >
> >If you are interested here is the offending backtrace (with a
> >watchpoint
> >triggered when ggc_free is overwriting, by enable-checking code, some
> >edge still kept in MELT global data thru a GTY-ed variable) 
> >
> >0  in memset of ../sysdeps/x86_64/memset.S:65
> >1  in ggc_free of /usr/src/Lang/basile-melt-gcc/gcc/ggc-page.c:1544
> >2  in free_edge of /usr/src/Lang/basile-melt-gcc/gcc/cfg.c:92
> >3  in remove_edge_raw of /usr/src/Lang/basile-melt-gcc/gcc/cfg.c:351
> >4  in remove_edge of /usr/src/Lang/basile-melt-gcc/gcc/cfghooks.c:418
> >5  in remove_phi_nodes_and_edges_for_unreachable_block
> >of /usr/src/Lang/basile-melt-gcc/gcc/tree-cfg.c:1934
> >6  in remove_bb of /usr/src/Lang/basile-melt-gcc/gcc/tree-cfg.c:2016
> >7  in delete_basic_block
> >of /usr/src/Lang/basile-melt-gcc/gcc/cfghooks.c:565
> >8  in remove_forwarder_block
> >of /usr/src/Lang/basile-melt-gcc/gcc/tree-cfgcleanup.c:529
> >9  in cleanup_tree_cfg_bb
> >of /usr/src/Lang/basile-melt-gcc/gcc/tree-cfgcleanup.c:633
> >10 in cleanup_tree_cfg_1
> >of /usr/src/Lang/basile-melt-gcc/gcc/tree-cfgcleanup.c:675
> >11 in cleanup_tree_cfg_noloop
> >of /usr/src/Lang/basile-melt-gcc/gcc/tree-cfgcleanup.c:731
> >12 in cleanup_tree_cfg
> >of /usr/src/Lang/basile-melt-gcc/gcc/tree-cfgcleanup.c:786
> >13 in execute_function_todo
> >of /usr/src/Lang/basile-melt-gcc/gcc/passes.c:1811
> >14 in do_per_function of
> >/usr/src/Lang/basile-melt-gcc/gcc/passes.c:1574
> >15 in execute_todo of /usr/src/Lang/basile-melt-gcc/gcc/passes.c:1887
> >16 in execute_one_pass
> >of /usr/src/Lang/basile-melt-gcc/gcc/passes.c:2247
> >17 in execute_pass_list
> >of /usr/src/Lang/basile-melt-gcc/gcc/passes.c:2286
> >18 in execute_pass_list
> >of /usr/src/Lang/basile-melt-gcc/gcc/passes.c:2287
> >19 in do_per_function_toporder
> >of /usr/src/Lang/basile-melt-gcc/gcc/passes.c:1630
> >20 in execute_ipa_pass_list
> >of /usr/src/Lang/basile-melt-gcc/gcc/passes.c:2617
> >21 in ipa_passes of /usr/src/Lang/basile-melt-gcc/gcc/cgraphunit.c:2043
> >22 in compile of /usr/src/Lang/basile-melt-gcc/gcc/cgraphunit.c:2174
> >23 in finalize_compilation_unit
> >of /usr/src/Lang/basile-melt-gcc/gcc/cgraphunit.c:2329
> >
> >If I continue the above execution my MELT plugin crashes (in GGC
> >marking
> >routines) because the stale edge has been free-d and reused later.
> > 
> >Of course, a dirty workaround is for me to clear manually that data
> >before it could be seen by the GGC marking garbage collector. And such
> >a
> >workaround is working. But I really find it shameful.
> >
> >Unfortunately, the data which are manually freed outside of ggc_collect
> >(so which should perhaps not be kept without care in GTY-ed variables
> >inside plugins) is not exactly documented.
> >
> >From my biased point of view, I would much prefer if ggc_free was
> >called
> >*only* from ggc_collect. Sadly, I believe that few GCC people would
> >agree with that. Or we could have ggc_free called only from
> >ggc_collect,
> >and add a new ggc_becomes_freeable routine (and every call to ggc_free
> >outside of ggc_collect would be replaced by a call to
> >ggc_becomes_freeable which for example would call ggc_free if not
> >plugin
> >is loaded, and stays a no-op if some plugins are loaded...).
> >
> >Perhaps we could improve the situation e.g.
> >
> >
> >   document more when and which data is cleaned up
> >
> >  add a finalizer plugin hook for the few static calls to ggc_free, but
> >that probably would be quite expensive (e.g. we'll run that hook from
> >free_edge in gcc/cfg.c ...) because ggc_free is probably called a big
> >lot of times.
> >
> >   more realistically, add plugin hooks in cleanup routines, notably in
> >cleanup_cfg file gcc/cfgcleanup.c
> >
> >
> >Please comment on this. If we agree on something I'll try to propose
> >some patch to GCC 5.0 during its stage 1. 
> 
> You are in the same situation as any other pass would be.  Don't hang on 
> things that can get stale.
> 
> There is no point in keeping a pointer to a deleted edge.
> 
> Of course we should make things more explicit here and move all data 
> structures out of GC that are explicitly freed.  Work in that direction is 
> welcome.  The CFG is in GC memory because it indirectly refers to trees (the 
> single most reason why things are in GC space, fixable nowadays with custom 
> GC marker routines)

I thought it was also because of pch?

I'm hoping we'll soon be at a point where everything uses the overload
based gc scheme currently used for user gc which should hopefully make
custom marking easier, but pch will still be a big pain, and in fact is
by far the worst part of implementing marking functions.

Trev

> 
> Richard.
> 
> >
> >Regards.
> 
> 

Reply via email to