From patchwork Tue Sep 27 16:43:56 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Diego Novillo X-Patchwork-Id: 116630 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 65323B6F6F for ; Wed, 28 Sep 2011 02:44:31 +1000 (EST) Received: (qmail 3447 invoked by alias); 27 Sep 2011 16:44:28 -0000 Received: (qmail 3431 invoked by uid 22791); 27 Sep 2011 16:44:24 -0000 X-SWARE-Spam-Status: No, hits=-2.4 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RP_MATCHES_RCVD, SPF_HELO_PASS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (74.125.121.67) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 27 Sep 2011 16:44:00 +0000 Received: from hpaq3.eem.corp.google.com (hpaq3.eem.corp.google.com [172.25.149.3]) by smtp-out.google.com with ESMTP id p8RGhwN4015145; Tue, 27 Sep 2011 09:43:59 -0700 Received: from topo.tor.corp.google.com (topo.tor.corp.google.com [172.29.41.2]) by hpaq3.eem.corp.google.com with ESMTP id p8RGhuZG019272; Tue, 27 Sep 2011 09:43:57 -0700 Received: by topo.tor.corp.google.com (Postfix, from userid 54752) id 59C931DA1C7; Tue, 27 Sep 2011 12:43:56 -0400 (EDT) To: reply@codereview.appspotmail.com, crowl@google.com, gcc-patches@gcc.gnu.org Subject: [pph] Prepare for mutation detection [1/3] (issue5124050) Message-Id: <20110927164356.59C931DA1C7@topo.tor.corp.google.com> Date: Tue, 27 Sep 2011 12:43:56 -0400 (EDT) From: dnovillo@google.com (Diego Novillo) X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This series of patches prepare support for detecting state mutation when reading tree nodes from different PPH images (http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00658.html). This first patch introduces a new data structure to represent entries in the pickle cache (pph_cache_entry). The data associated with the structure will have an optional signature computed the first time the data is read. In the case of DECLs, the first time we read it from a PPH image, we compute its signature. When time comes to write it out, we compute the signature again, if it changed, it means that the DECL has mutated, so instead of writing a reference to it, we pickle it out again (this is indicated with a new record marker PPH_RECORD_MREF). Tested on x86_64. Committed to branch. Diego. * pph-streamer.h (enum pph_record_marker): Add PPH_RECORD_MREF value. (pph_cache_entry): Declare. (pph_cache): Rename from pph_pickle_cache. Change field v to be a VEC of pph_cache_entry elements. Update all users. diff --git a/gcc/cp/pph-streamer.c b/gcc/cp/pph-streamer.c index 02fd1c0..c3dee7a 100644 --- a/gcc/cp/pph-streamer.c +++ b/gcc/cp/pph-streamer.c @@ -41,13 +41,13 @@ along with GCC; see the file COPYING3. If not see VEC(pph_stream_ptr, heap) *pph_read_images; /* A cache of pre-loaded common tree nodes. */ -static pph_pickle_cache *pph_preloaded_cache; +static pph_cache *pph_preloaded_cache; /* Pre-load common tree nodes into CACHE. These nodes are always built by the front end, so there is no need to pickle them. */ static void -pph_cache_preload (pph_pickle_cache *cache) +pph_cache_preload (pph_cache *cache) { unsigned i; @@ -101,7 +101,7 @@ pph_hooks_init (void) /* Initialize an empty pickle CACHE. */ static void -pph_cache_init (pph_pickle_cache *cache) +pph_cache_init (pph_cache *cache) { cache->v = NULL; cache->m = pointer_map_create (); @@ -111,7 +111,7 @@ pph_cache_init (pph_pickle_cache *cache) void pph_init_preloaded_cache (void) { - pph_preloaded_cache = XCNEW (pph_pickle_cache); + pph_preloaded_cache = XCNEW (pph_cache); pph_cache_init (pph_preloaded_cache); pph_cache_preload (pph_preloaded_cache); } @@ -169,7 +169,7 @@ pph_stream_close (pph_stream *stream) /* Deallocate all memory used. */ stream->file = NULL; - VEC_free (void_p, heap, stream->cache.v); + VEC_free (pph_cache_entry, heap, stream->cache.v); pointer_map_destroy (stream->cache.m); VEC_free (pph_symtab_entry, heap, stream->symtab.v); @@ -398,22 +398,31 @@ pph_trace_bitpack (pph_stream *stream, struct bitpack_d *bp) } -/* Insert DATA in CACHE at slot IX. If DATA already existed in the CACHE, IX - must be the same as the previous entry. */ +/* Insert DATA in CACHE at slot IX. We support inserting the same + DATA at different locations of the array (FIXME pph, this happens + when reading builtins, which may have been converted into builtins + after they were read originally. This should be detected and + converted into mutated references). */ void -pph_cache_insert_at (pph_pickle_cache *cache, void *data, unsigned ix) +pph_cache_insert_at (pph_cache *cache, void *data, unsigned ix) { void **map_slot; + pph_cache_entry e = { data, 0, 0 }; map_slot = pointer_map_insert (cache->m, data); if (*map_slot == NULL) { - *map_slot = (void *) (unsigned HOST_WIDE_INT) ix; - if (ix + 1 > VEC_length (void_p, cache->v)) - VEC_safe_grow_cleared (void_p, heap, cache->v, ix + 1); - VEC_replace (void_p, cache->v, ix, data); + *map_slot = (void *) (intptr_t) ix; + if (ix + 1 > VEC_length (pph_cache_entry, cache->v)) + VEC_safe_grow_cleared (pph_cache_entry, heap, cache->v, ix + 1); + VEC_replace (pph_cache_entry, cache->v, ix, &e); } +#if 0 + /* FIXME pph. Re-add after mutated references are implemented. */ + else + gcc_assert (ix == (intptr_t) *((intptr_t **) map_slot)); +#endif } @@ -422,7 +431,7 @@ pph_cache_insert_at (pph_pickle_cache *cache, void *data, unsigned ix) If CACHE is NULL use pph_preloaded_cache by default. */ bool -pph_cache_lookup (pph_pickle_cache *cache, void *data, unsigned *ix_p) +pph_cache_lookup (pph_cache *cache, void *data, unsigned *ix_p) { void **map_slot; unsigned ix; @@ -503,7 +512,7 @@ pph_cache_lookup_in_includes (void *data, unsigned *include_ix_p, in the CACHE, false otherwise. */ bool -pph_cache_add (pph_pickle_cache *cache, void *data, unsigned *ix_p) +pph_cache_add (pph_cache *cache, void *data, unsigned *ix_p) { unsigned ix; bool existed_p; @@ -513,7 +522,7 @@ pph_cache_add (pph_pickle_cache *cache, void *data, unsigned *ix_p) else { existed_p = false; - ix = VEC_length (void_p, cache->v); + ix = VEC_length (pph_cache_entry, cache->v); pph_cache_insert_at (cache, data, ix); } @@ -524,17 +533,18 @@ pph_cache_add (pph_pickle_cache *cache, void *data, unsigned *ix_p) } -/* Return the pointer at slot IX in STREAM_CACHE if MARKER is an IREF. IF - MARKER is a XREF then instead of looking up in STREAM_CACHE, the pointer is - looked up in the CACHE of pph_read_images[INCLUDE_IX]. Finally if MARKER is - a PREF return the pointer at slot IX in the preloaded cache. */ +/* Return the pointer at slot IX in STREAM_CACHE if MARKER is an IREF. + If MARKER is a XREF then instead of looking up in STREAM_CACHE, the + pointer is looked up in the CACHE of pph_read_images[INCLUDE_IX]. + Finally if MARKER is a PREF return the pointer at slot IX in the + preloaded cache. */ void * -pph_cache_get (pph_pickle_cache *stream_cache, unsigned include_ix, unsigned ix, +pph_cache_get (pph_cache *stream_cache, unsigned include_ix, unsigned ix, enum pph_record_marker marker) { - void *data; - pph_pickle_cache *cache; + pph_cache_entry *e; + pph_cache *cache; /* Determine which cache to use. */ switch (marker) @@ -552,7 +562,7 @@ pph_cache_get (pph_pickle_cache *stream_cache, unsigned include_ix, unsigned ix, gcc_unreachable (); } - data = VEC_index (void_p, cache->v, ix); - gcc_assert (data); - return data; + e = VEC_index (pph_cache_entry, cache->v, ix); + gcc_assert (e); + return e->data; } diff --git a/gcc/cp/pph-streamer.h b/gcc/cp/pph-streamer.h index 4e62186..2a1ef8b 100644 --- a/gcc/cp/pph-streamer.h +++ b/gcc/cp/pph-streamer.h @@ -52,14 +52,25 @@ enum pph_record_marker { /* Preloaded reference. This marker indicates that this data is a preloaded node created by the front-end at the beginning of compilation, which we do not need to stream out as it will already exist on the way in. */ - PPH_RECORD_PREF + PPH_RECORD_PREF, + + /* Mutated reference. This marker indicates that this data already + existed in the cache for another PPH image, but it has mutated + since it was inserted into the cache: + + - The writer will pickle the object again as if it had not + been pickled before. + + - The reader uses this as an indication that it should not + allocate a new object, it should simply unpickle the object on + top of the already allocated object. */ + PPH_RECORD_MREF }; /* Line table markers. We only stream line table entries from the parent header file, other entries are referred to by the name of the file which is then loaded as an include at the correct point in time. */ enum pph_linetable_marker { - /* A regular line_map entry in the line_table. */ PPH_LINETABLE_ENTRY = 0x01, @@ -102,9 +113,30 @@ typedef struct pph_file_header { } pph_file_header; -typedef void *void_p; -DEF_VEC_P(void_p); -DEF_VEC_ALLOC_P(void_p,heap); +/* An entry in the pickle cache. Each entry contains a pointer to + the cached data and checksum information. This checksum is used to + detect mutated states. This is common, for instance, in decl trees + that are first parsed as declarations and later on they are + converted into their definition. + + When the cache notices a cache hit on a mutated data, it writes a + PPH_RECORD_MUTATED_REF to indicate to the reader that it is about + to read an already instantiated tree. */ +typedef struct pph_cache_entry { + /* Pointer to cached data. */ + void *data; + + /* Checksum information for DATA. */ + unsigned int crc; + + /* Length of the checksummed area pointed by DATA. Note that this + is *not* the size of the memory area pointed by DATA, just the + number of bytes in DATA that we have checksummed. */ + unsigned int crc_nbytes; +} pph_cache_entry; + +DEF_VEC_O(pph_cache_entry); +DEF_VEC_ALLOC_O(pph_cache_entry,heap); /* A cache for storing pickled data structures. This is used to implement pointer sharing. @@ -118,13 +150,13 @@ DEF_VEC_ALLOC_P(void_p,heap); first materialized, its address is saved into the same cache slot used when writing. Subsequent reads will simply get the materialized pointer from that slot. */ -typedef struct pph_pickle_cache { +typedef struct pph_cache { /* Array of entries. */ - VEC(void_p,heap) *v; + VEC(pph_cache_entry,heap) *v; /* Map between slots in the array and pointers. */ struct pointer_map_t *m; -} pph_pickle_cache; +} pph_cache; /* Actions associated with each symbol table entry. These indicate @@ -212,7 +244,7 @@ typedef struct pph_stream { } encoder; /* Cache of pickled data structures. */ - pph_pickle_cache cache; + pph_cache cache; /* Nonzero if the stream was opened for writing. */ unsigned int write_p : 1; @@ -243,12 +275,11 @@ void pph_trace_string_with_length (pph_stream *, const char *, unsigned); void pph_trace_location (pph_stream *, location_t); void pph_trace_chain (pph_stream *, tree); void pph_trace_bitpack (pph_stream *, struct bitpack_d *); -void pph_cache_insert_at (pph_pickle_cache *, void *, unsigned); -bool pph_cache_lookup (pph_pickle_cache *, void *, unsigned *); +void pph_cache_insert_at (pph_cache *, void *, unsigned); +bool pph_cache_lookup (pph_cache *, void *, unsigned *); bool pph_cache_lookup_in_includes (void *, unsigned *, unsigned *); -bool pph_cache_add (pph_pickle_cache *, void *, unsigned *); -void *pph_cache_get (pph_pickle_cache *, unsigned, unsigned, - enum pph_record_marker); +bool pph_cache_add (pph_cache *, void *, unsigned *); +void *pph_cache_get (pph_cache *, unsigned, unsigned, enum pph_record_marker); /* In pph-streamer-out.c. */ void pph_flush_buffers (pph_stream *);