When we read a tree from the cache of an external PPH file and the tree is mutated in the current file, we need to re-sign the tree to reflect the changes.
The problem was, that the signing code was assuming that the tree had come from the *current* file, so it was trying to sign a cache entry for the internal cache, which would ICE if the internal cache is smaller than the external one. I have not yet been able to produce a small test case for this, but it fixes several thousand ICEs in our internal code. I will add a test case as soon as I get one reduced. * pph-in.c (pph_in_tree): Sign EXPR from the cache it was taken from. * pph-streamer.h (pph_cache_select): Handle PPH_RECORD_START, PPH_RECORD_START_MERGE_BODY, PPH_RECORD_START_MERGE_KEY and PPH_RECORD_START_MUTATED. diff --git a/gcc/cp/pph-in.c b/gcc/cp/pph-in.c index 2dbad83..0b2529f 100644 --- a/gcc/cp/pph-in.c +++ b/gcc/cp/pph-in.c @@ -2565,8 +2565,7 @@ pph_in_tree (pph_stream *stream) /* When reading a mutated tree, we only need to re-read its body, the tree itself is already in the cache for another PPH image. */ - expr = (tree) pph_cache_find (stream, PPH_RECORD_XREF, image_ix, ix, - PPH_any_tree); + expr = (tree) pph_cache_find (stream, marker, image_ix, ix, PPH_any_tree); } else if (marker == PPH_RECORD_START_MERGE_BODY) { @@ -2600,7 +2599,7 @@ pph_in_tree (pph_stream *stream) pph_trace_tree (expr, pph_trace_back, marker == PPH_RECORD_START_MERGE_BODY ? pph_trace_merge_body : marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate - : pph_trace_normal ); + : pph_trace_normal); /* If needed, sign the recently materialized tree to detect mutations. Note that we only need to compute signatures @@ -2612,8 +2611,13 @@ pph_in_tree (pph_stream *stream) { unsigned crc; size_t nbytes; + pph_cache *cache; + + /* Retrieve the cache to sign based on where we materialized + EXPR from. */ + cache = pph_cache_select (stream, marker, image_ix); crc = pph_get_signature (expr, &nbytes); - pph_cache_sign (&stream->cache, ix, crc, nbytes); + pph_cache_sign (cache, ix, crc, nbytes); } return expr; diff --git a/gcc/cp/pph-streamer.h b/gcc/cp/pph-streamer.h index b641776..c5db972 100644 --- a/gcc/cp/pph-streamer.h +++ b/gcc/cp/pph-streamer.h @@ -293,9 +293,16 @@ void pph_reader_finish (void); /* Return the pickle cache in STREAM corresponding to MARKER. - if MARKER is PPH_RECORD_IREF, it returns the cache in STREAM itself. - If MARKER is PPH_RECORD_XREF, it returns the cache in - STREAM->INCLUDES[INCLUDE_IX]. + INCLUDE_IX is only used for MARKER values PPH_RECORD_XREF or + PPH_RECORD_START_MUTATED. + + If MARKER is one of {PPH_RECORD_IREF, PPH_RECORD_START, + PPH_RECORD_START_MERGE_BODY, PPH_RECORD_START_MERGE_KEY}, it + returns the cache in STREAM itself. + + If MARKER is one of {PPH_RECORD_XREF, PPH_RECORD_START_MUTATED}, it + returns the cache in STREAM->INCLUDES[INCLUDE_IX]. + If MARKER is a PREF, it returns the preloaded cache. */ static inline pph_cache * pph_cache_select (pph_stream *stream, enum pph_record_marker marker, @@ -304,9 +311,13 @@ pph_cache_select (pph_stream *stream, enum pph_record_marker marker, switch (marker) { case PPH_RECORD_IREF: + case PPH_RECORD_START: + case PPH_RECORD_START_MERGE_BODY: + case PPH_RECORD_START_MERGE_KEY: return &stream->cache; break; case PPH_RECORD_XREF: + case PPH_RECORD_START_MUTATED: return &VEC_index (pph_stream_ptr, stream->includes, include_ix)->cache; break; case PPH_RECORD_PREF: -- This patch is available for review at http://codereview.appspot.com/5554070