This patch re-factors pph_start_record so we can separate the decision of what marker to use from the emission of the marker.
This is used by pph_out_start_tree_record to decide if a new marker will be needed. In this patch, it will only display debugging info. The actual change comes in a subsequent patch. Tested on x86_64. Committed to branch. * pph-streamer-out.c (pph_get_marker_for): Factor out of pph_start_record. (pph_out_reference_record): Rename from pph_out_start_ref_record. (pph_out_start_tree_record): Detect when a tree's signature should be re-checked. diff --git a/gcc/cp/pph-streamer-out.c b/gcc/cp/pph-streamer-out.c index 2f9fcae..4bff1b6 100644 --- a/gcc/cp/pph-streamer-out.c +++ b/gcc/cp/pph-streamer-out.c @@ -226,59 +226,75 @@ pph_cache_should_handle (tree t) } -/* If DATA is NULL or it existed in one of the pickle caches associated - with STREAM, write a reference marker and return true. Otherwise, - do nothing and return false. */ +/* Return a PPH record marker according to whether DATA is NULL or + it can be found in one of the caches associated with STREAM. -static bool -pph_out_start_ref_record (pph_stream *stream, void *data) + If DATA is in any of the caches, return the corresponding slot in + *IX_P. If DATA is in the cache of an image included by STREAM, + return the image's index in *INCLUDE_IX_P. + + In all other cases, *IX_P and *INCLUDE_IX_P will be set to -1. */ + +static enum pph_record_marker +pph_get_marker_for (pph_stream *stream, void *data, unsigned *include_ix_p, + unsigned *ix_p) { - unsigned ix, include_ix; + *ix_p = -1u; + *include_ix_p = -1u; - /* Represent NULL pointers with a single PPH_RECORD_END. */ + /* We represent NULL pointers with PPH_RECORD_END. */ if (data == NULL) - { - pph_out_record_marker (stream, PPH_RECORD_END); - return true; - } + return PPH_RECORD_END; - /* See if we have data in STREAM's cache. If so, write an internal - reference to it and inform the caller that it should not write a - physical representation for DATA. */ - if (pph_cache_lookup (&stream->cache, data, &ix)) - { - pph_out_record_marker (stream, PPH_RECORD_IREF); - pph_out_uint (stream, ix); - return true; - } + /* If DATA is in STREAM's cache, return an internal reference marker. */ + if (pph_cache_lookup (&stream->cache, data, ix_p)) + return PPH_RECORD_IREF; - /* DATA is not in STREAM's cache. See if it is in any of the - included images. If it is, write an external reference to it - and inform the caller that it should not write a physical - representation for DATA. */ - if (pph_cache_lookup_in_includes (data, &include_ix, &ix)) - { - pph_out_record_marker (stream, PPH_RECORD_XREF); - pph_out_uint (stream, include_ix); - pph_out_uint (stream, ix); - return true; - } + /* If DATA is in the cache of an included image, return an external + reference marker. */ + if (pph_cache_lookup_in_includes (data, include_ix_p, ix_p)) + return PPH_RECORD_XREF; + + /* If DATA is a pre-loaded tree node, return a pre-loaded reference + marker. */ + if (pph_cache_lookup (NULL, data, ix_p)) + return PPH_RECORD_PREF; + + /* DATA is in none of the caches. It should be pickled out. */ + return PPH_RECORD_START; +} + + +/* Write a reference record on STREAM. MARKER is the tag indicating what + kind of reference to write. IX is the cache slot index to write. + INCLUDE_IX is used for PPH_RECORD_XREF records. */ + +static inline void +pph_out_reference_record (pph_stream *stream, enum pph_record_marker marker, + unsigned include_ix, unsigned ix) +{ + gcc_assert (marker == PPH_RECORD_END || pph_is_reference_marker (marker)); + + pph_out_record_marker (stream, marker); - /* DATA is not in any stream's cache. See if it is a preloaded node. */ - if (pph_cache_lookup (NULL, data, &ix)) + if (pph_is_reference_marker (marker)) { - pph_out_record_marker (stream, PPH_RECORD_PREF); + if (marker == PPH_RECORD_XREF) + { + gcc_assert (include_ix != -1u); + pph_out_uint (stream, include_ix); + } + + gcc_assert (ix != -1u); pph_out_uint (stream, ix); - return true; } - - /* Could not write a reference record. DATA must be pickled. */ - return false; + else + gcc_assert (marker == PPH_RECORD_END); } /* Start a new record in STREAM for DATA. If DATA is NULL - write an end-of-record marker and return false. + write an end-of-record marker and return true. If DATA is not NULL and did not exist in the pickle cache, add it, write a start-of-record marker and return true. This means that we @@ -292,15 +308,19 @@ pph_out_start_ref_record (pph_stream *stream, void *data) static inline bool pph_out_start_record (pph_stream *stream, void *data) { - unsigned ix; + unsigned include_ix, ix; + enum pph_record_marker marker; /* Try to write a reference record first. */ - if (pph_out_start_ref_record (stream, data)) - return true; + marker = pph_get_marker_for (stream, data, &include_ix, &ix); + if (marker == PPH_RECORD_END || pph_is_reference_marker (marker)) + { + pph_out_reference_record (stream, marker, include_ix, ix); + return true; + } /* DATA is in none of the pickle caches. Add DATA to STREAM's - pickle cache and return false to tell the caller that it should - pickle DATA out. */ + pickle cache and write the slot where we stored it in. */ pph_cache_add (&stream->cache, data, &ix); pph_out_record_marker (stream, PPH_RECORD_START); pph_out_uint (stream, ix); @@ -317,9 +337,35 @@ pph_out_start_record (pph_stream *stream, void *data) static inline bool pph_out_start_tree_record (pph_stream *stream, tree t) { - /* Try to write a reference record first. */ - if (pph_out_start_ref_record (stream, t)) - return true; + unsigned include_ix, ix; + enum pph_record_marker marker; + + /* Determine what kind of record we will be writing. */ + marker = pph_get_marker_for (stream, t, &include_ix, &ix); + + /* DECLs and TYPEs that have been read from an external PPH image + may have mutated while parsing this header. In that case, + we need to write a mutated reference record and re-pickle the + tree. */ + if (marker == PPH_RECORD_XREF && tree_needs_signature (t)) + { + pph_cache *cache = pph_cache_select (stream, marker, include_ix); + pph_cache_entry *e = pph_cache_get_entry (cache, ix); + unsigned crc = pph_get_signature (t, NULL); + if (crc != e->crc) + if (flag_pph_debug > 1) + { + fprintf (pph_logfile, "Tree signature changed: %x to %x\n", + e->crc, crc); + print_node (pph_logfile, "", t, 4); + } + } + + if (marker == PPH_RECORD_END || pph_is_reference_marker (marker)) + { + pph_out_reference_record (stream, marker, include_ix, ix); + return true; + } /* We want to prevent some trees from hitting the cache. Note that this does not prevent us from ever putting these nodes in the -- 1.7.3.1 -- This patch is available for review at http://codereview.appspot.com/5179042