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