PATCH fix heisenbug in cp/spew.c

Richard Earnshaw rearnsha@arm.com
Mon Jul 29 04:07:00 GMT 2002


Outch, this is the way I really want to spend my weekend :-(

The conditions for this bug are quite complex.  We must

- Allocate a token_chunk and then put in it a tree node

- Run a garbage collection pass that recovers both of the above

- Reuse the memory that was previously used for the tree node for some 
other data object (eg a piece of RTL)

- Re-allocate the memory that was previously used as a token chunk in 
space_for_token()

- Only partially fill the token chunk, so that the previous link to the 
tree node is not overridden

- Place the token chunk on a GCable list so that it remains live

- Run GC again

With all of the above conditions we will try to walk the memory that 
previously held the tree node as a tree node and get a segmentation fault.

Whilst tracking down the above I made a few observations:

1) When we are recursing through the tree structures we can get a *very* 
deep stack (in the case I was debugging there were more than 3000 frames 
on the stack) -- is there any way we could tune the autogenerated 
tree-walking code to tail-call itself -- ideally with a marker in the 
structure to indicate the most beneficial tail-call pointer?

2) We have a lot of cases in the autogenerated memory-walking code where 
we have sequences like:

    unsigned int tag1 = (((*x)).yychar);
    if (tag1 == (NSNAME)) {
      gt_ggc_m_tree_node ((*x).yylval.ttype);
    }
    if (tag1 == (PTYPENAME_DEFN)) {
      gt_ggc_m_tree_node ((*x).yylval.ttype);
    }
    if (tag1 == (TYPENAME_DEFN)) {
      gt_ggc_m_tree_node ((*x).yylval.ttype);
    }
    if (tag1 == (IDENTIFIER_DEFN)) {
      gt_ggc_m_tree_node ((*x).yylval.ttype);
    }
    if (tag1 == (PRE_PARSED_FUNCTION_DECL)) {
      gt_ggc_m_unparsed_text ((*x).yylval.pi);
    }
    if (tag1 == (DEFARG_MARKER)) {
      gt_ggc_m_tree_node ((*x).yylval.ttype);
    }
    if (tag1 == (DEFARG)) {
	...

This should be done as else-if tests, since it is clear that not more than 
one can be true.  Better still might be a switch -- gcc could then 
optimize small tables into if-else chains.  GCC with -O will probably 
simplify the above, but the first stage of the bootstrap will certainly 
not do this optimization, which means that we have to test every case.


3) When checking is enabled can we make the tree marking code check 
(cheaply) that memory it is marking is not marked as unallocated -- I 
don't know if it would have found this bug, but it might have caused a 
diagnostic fault to have triggered more often than the above conditions 
would have occurred.

Bootstrapped on i686-pc-linux-gnu with a regtest (C++ only) and also 
verified to have fixed the original testsuite failure on 
arm-unknown-linux-gnu.

Fixed with:

2002-07-29  Richard Earnshaw  <rearnsha@arm.com>

	* spew.c (space_for_token): Allocate zeroed memory for a new token
	chunk.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: gcc-spew.patch
Type: text/x-patch
Size: 813 bytes
Desc: gcc-spew.patch
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20020729/5e216be9/attachment.bin>


More information about the Gcc-patches mailing list