Part 1: Add more trees to the preloaded tree cache. This prevents more common trees, built at compiler initialization time, to be streamed out to PPH images.
These trees are in: - type_hash_table: The private hash table used in tree.c to record canonical types. To avoid exposing this table out of tree.c, I added a traversal routine with a callback argument (type_hash_table_traverse). - Builtin types registered with record_builtin_type. I added a routine pph_register_builtin_type that is called for every builtin type. We later record those types in pph_cache_preload. Another piece of private state that needs to be written out is canonical_template_parms and nonstandard_integer_type_cache. I added writer and reader routines to pt.c to do deal with canonical_template_parms and traversal+callback iterators in tree.c to deal with nonstandard_integer_type_cache (to avoid middle-end routines to have to know about PPH). 2012-03-13 Diego Novillo <dnovi...@google.com> cp/ChangeLog.pph * decl.c (record_builtin_type): Call pph_register_builtin_type. * pph-core.c (pph_cache_add_full_tree_r): New. (pph_cache_add_full_tree): New. (nitc_callback): New. (pph_builtin_types): Declare. (pph_register_builtin_type): New. (pph_cache_add_builtin_types): New. (pph_cache_add_canonical_type): New. (pph_cache_preload): Call pph_cache_add_full_tree instead of pph_cache_add. Call traverse_nonstandard_integer_type_cache with nitc_callback. Call pph_cache_add_builtin_types. Call type_hash_table_traverse. * pph-in.c (pph_in_tcc_type): Read TYP_NEXT_PTR_TO for POINTER_TYPE types. (pph_read_file_1): Call pph_in_canonical_template_parms. * pph-out.c (pph_out_tcc_type): Write TYPE_NEXT_PTR_TO for POINTER_TYPE types. (pph_write_file): Call pph_out_canonical_template_parms. * pph.h (pph_register_builtin_type): Declare. (pph_out_canonical_template_parms): Declare. (pph_in_canonical_template_parms): Declare. * pt.c (pph_out_canonical_template_parms): New. (pph_in_canonical_template_parms): New. ChangeLog.pph * tree.c (type_hash_traverse): Declare. (type_hash_table_retrieve_entry): New. (type_hash_table_traverse): New. (type_hash_table_length): New. (CACHED_PREC_LEN): Factor out of ... (nonstandard_integer_type_cache): ... here. (traverse_nonstandard_integer_type_cache): New. * tree.h (type_hash_table_traverse): Declare. (type_hash_table_length): Declare. (traverse_nonstandard_integer_type_cache): Declare. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/pph@185344 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog.pph | 13 ++++++ gcc/cp/ChangeLog.pph | 27 +++++++++++++ gcc/cp/decl.c | 6 +++ gcc/cp/pph-core.c | 106 +++++++++++++++++++++++++++++++++++++++++++------- gcc/cp/pph-in.c | 14 +++++-- gcc/cp/pph-out.c | 12 ++++- gcc/cp/pph.h | 5 ++ gcc/cp/pt.c | 31 +++++++++++++++ gcc/tree.c | 67 +++++++++++++++++++++++++++++++- gcc/tree.h | 4 ++ 10 files changed, 263 insertions(+), 22 deletions(-) diff --git a/gcc/ChangeLog.pph b/gcc/ChangeLog.pph index d95c153..2bf6c9a 100644 --- a/gcc/ChangeLog.pph +++ b/gcc/ChangeLog.pph @@ -1,5 +1,18 @@ 2012-03-04 Diego Novillo <dnovi...@google.com> + * tree.c (type_hash_traverse): Declare. + (type_hash_table_retrieve_entry): New. + (type_hash_table_traverse): New. + (type_hash_table_length): New. + (CACHED_PREC_LEN): Factor out of ... + (nonstandard_integer_type_cache): ... here. + (traverse_nonstandard_integer_type_cache): New. + * tree.h (type_hash_table_traverse): Declare. + (type_hash_table_length): Declare. + (traverse_nonstandard_integer_type_cache): Declare. + +2012-03-04 Diego Novillo <dnovi...@google.com> + Merge from trunk rev 184817. BASE-VER: Update to 4.8.0-pph. diff --git a/gcc/cp/ChangeLog.pph b/gcc/cp/ChangeLog.pph index c867ca3..697ae2b 100644 --- a/gcc/cp/ChangeLog.pph +++ b/gcc/cp/ChangeLog.pph @@ -1,3 +1,30 @@ +2012-03-13 Diego Novillo <dnovi...@google.com> + + * decl.c (record_builtin_type): Call pph_register_builtin_type. + * pph-core.c (pph_cache_add_full_tree_r): New. + (pph_cache_add_full_tree): New. + (nitc_callback): New. + (pph_builtin_types): Declare. + (pph_register_builtin_type): New. + (pph_cache_add_builtin_types): New. + (pph_cache_add_canonical_type): New. + (pph_cache_preload): Call pph_cache_add_full_tree instead of + pph_cache_add. + Call traverse_nonstandard_integer_type_cache with nitc_callback. + Call pph_cache_add_builtin_types. + Call type_hash_table_traverse. + * pph-in.c (pph_in_tcc_type): Read TYP_NEXT_PTR_TO for + POINTER_TYPE types. + (pph_read_file_1): Call pph_in_canonical_template_parms. + * pph-out.c (pph_out_tcc_type): Write TYPE_NEXT_PTR_TO for + POINTER_TYPE types. + (pph_write_file): Call pph_out_canonical_template_parms. + * pph.h (pph_register_builtin_type): Declare. + (pph_out_canonical_template_parms): Declare. + (pph_in_canonical_template_parms): Declare. + * pt.c (pph_out_canonical_template_parms): New. + (pph_in_canonical_template_parms): New. + 2012-03-09 Lawrence Crowl <cr...@google.com> * name-lookup.c (pph_out_binding_table): Correct comment. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 279a9ab..ab2b7d2 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3436,6 +3436,12 @@ record_builtin_type (enum rid rid_index, if (tdecl) debug_hooks->type_decl (tdecl, 0); + + /* When using pre-parsed headers, we register builtin types in the PPH + pickle cache to avoid writing a physical representation of these types + and make sure that all references resolve to the same pre-built type. */ + if (pph_enabled_p ()) + pph_register_builtin_type (type); } /* Record one of the standard Java types. diff --git a/gcc/cp/pph-core.c b/gcc/cp/pph-core.c index 464f39f..8c79017 100644 --- a/gcc/cp/pph-core.c +++ b/gcc/cp/pph-core.c @@ -472,6 +472,82 @@ pph_cache_init (pph_cache *cache) static pph_cache *pph_preloaded_cache; +/* Callback for cp_walk_tree. Called from pph_cache_add_full_tree. + Add the sub-tree *TP to the cache pointed to by DATA. Always set + WALK_SUBTREES to 1 to traverse every sub-tree. */ + +static tree +pph_cache_add_full_tree_r (tree *tp, int *walk_subtrees, void *data) +{ + pph_cache *cache = (pph_cache *) data; + pph_cache_add (cache, *tp, NULL, pph_tree_code_to_tag (*tp)); + *walk_subtrees = 1; + return NULL; +} + + +/* Add tree T and all its children into CACHE. */ + +static void +pph_cache_add_full_tree (pph_cache *cache, tree t) +{ + cp_walk_tree (&t, pph_cache_add_full_tree_r, cache, NULL); +} + + +/* Callback for traverse_nonstandard_integer_type_cache. Add the + full tree TYPE to the cache pointed by DATA. */ + +static bool +nitc_callback (tree type, void *data) +{ + pph_cache *cache = (pph_cache *) data; + pph_cache_add_full_tree (cache, type); + return true; +} + +/* Vector of builtin types to register in the preloaded cache. */ +static VEC(tree,gc) *pph_builtin_types; + + +/* Register a builtin type to be preloaded when we are setting up the + pickle cache. This is called from record_builtin_type. */ + +void +pph_register_builtin_type (tree type) +{ + VEC_safe_push (tree, gc, pph_builtin_types, type); +} + + +/* Pre-load all the builtin types declared by the compiler. */ + +static void +pph_cache_add_builtin_types (pph_cache *cache) +{ + unsigned i; + tree type; + + FOR_EACH_VEC_ELT (tree, pph_builtin_types, i, type) + pph_cache_add_full_tree (cache, type); +} + + +/* Callback for type_hash_table_traverse. DATA points to the cache + where we are preloading trees built by the front end on startup. + TYPE is the type to preload. Always return true, so we visit the + whole table. */ + +static bool +pph_cache_add_canonical_type (unsigned long h ATTRIBUTE_UNUSED, tree type, + void *data) +{ + pph_cache *cache = (pph_cache *) data; + pph_cache_add_full_tree (cache, type); + return true; +} + + /* Pre-load common tree nodes into CACHE. These nodes are always built by the front end, so there is no need to pickle them. */ @@ -481,24 +557,20 @@ pph_cache_preload (pph_cache *cache) unsigned i; for (i = itk_char; i < itk_none; i++) - pph_cache_add (cache, integer_types[i], NULL, - pph_tree_code_to_tag (integer_types[i])); + pph_cache_add_full_tree (cache, integer_types[i]); for (i = 0; i < TYPE_KIND_LAST; i++) - pph_cache_add (cache, sizetype_tab[i], NULL, - pph_tree_code_to_tag (sizetype_tab[i])); + pph_cache_add_full_tree (cache, sizetype_tab[i]); /* global_trees[] can have NULL entries in it. Skip them. */ for (i = 0; i < TI_MAX; i++) if (global_trees[i]) - pph_cache_add (cache, global_trees[i], NULL, - pph_tree_code_to_tag (global_trees[i])); + pph_cache_add_full_tree (cache, global_trees[i]); /* c_global_trees[] can have NULL entries in it. Skip them. */ for (i = 0; i < CTI_MAX; i++) if (c_global_trees[i]) - pph_cache_add (cache, c_global_trees[i], NULL, - pph_tree_code_to_tag (c_global_trees[i])); + pph_cache_add_full_tree (cache, c_global_trees[i]); /* cp_global_trees[] can have NULL entries in it. Skip them. */ for (i = 0; i < CPTI_MAX; i++) @@ -508,16 +580,22 @@ pph_cache_preload (pph_cache *cache) continue; if (cp_global_trees[i]) - pph_cache_add (cache, cp_global_trees[i], NULL, - pph_tree_code_to_tag (cp_global_trees[i])); + pph_cache_add_full_tree (cache, cp_global_trees[i]); } + /* Pre-load the table of nonstandard integer types. */ + traverse_nonstandard_integer_type_cache (nitc_callback, (void *) cache); + + /* Pre-load all the builtin types. */ + pph_cache_add_builtin_types (cache); + + /* Pre-load the table of canonical types. */ + type_hash_table_traverse (pph_cache_add_canonical_type, cache); + /* Add other well-known nodes that should always be taken from the current compilation context. */ - pph_cache_add (cache, global_namespace, NULL, - pph_tree_code_to_tag (global_namespace)); - pph_cache_add (cache, DECL_CONTEXT (global_namespace), NULL, - pph_tree_code_to_tag (DECL_CONTEXT (global_namespace))); + pph_cache_add_full_tree (cache, global_namespace); + pph_cache_add_full_tree (cache, DECL_CONTEXT (global_namespace)); } diff --git a/gcc/cp/pph-in.c b/gcc/cp/pph-in.c index caa90c8..12685a9 100644 --- a/gcc/cp/pph-in.c +++ b/gcc/cp/pph-in.c @@ -1959,12 +1959,13 @@ pph_in_tcc_type (pph_stream *stream, tree type) { TYPE_LANG_SPECIFIC (type) = pph_in_lang_type (stream); TYPE_POINTER_TO (type) = pph_in_tree (stream); + if (TREE_CODE (type) == POINTER_TYPE) + TYPE_NEXT_PTR_TO (type) = pph_in_tree (stream); TYPE_REFERENCE_TO (type) = pph_in_tree (stream); TYPE_NEXT_VARIANT (type) = pph_in_tree (stream); SET_TYPE_MODE (type, pph_in_machine_mode (stream)); - /* FIXME pph - Streaming TYPE_CANONICAL generates many type comparison - failures. Why? */ - /* FIXME pph: apparently redundant. */ + /* We do not read TYPE_CANONICAL. Instead, we emit the table of + canonical types and re-instantiate it on read. */ TREE_CHAIN (type) = pph_in_tree (stream); /* The type values cache is built as constants are instantiated, @@ -3255,7 +3256,12 @@ pph_read_file_1 (pph_stream *stream) static_aggregates = chainon (file_static_aggregates, static_aggregates); pph_in_decl2_hidden_state (stream); - /* Read and process the symbol table. */ + pph_in_canonical_template_parms (stream); + + /* Read and process the symbol table. This must be done at the end + because we have symbols coming in from children PPH images which + must be instantiated in the same order they were instantiated by + the original parser. */ pph_in_symtab (stream); if (flag_pph_dump_tree) diff --git a/gcc/cp/pph-out.c b/gcc/cp/pph-out.c index 3a56b93..c817f22 100644 --- a/gcc/cp/pph-out.c +++ b/gcc/cp/pph-out.c @@ -1859,11 +1859,13 @@ pph_out_tcc_type (pph_stream *stream, tree type) { pph_out_lang_type (stream, type); pph_out_tree (stream, TYPE_POINTER_TO (type)); + if (TREE_CODE (type) == POINTER_TYPE) + pph_out_tree (stream, TYPE_NEXT_PTR_TO (type)); pph_out_tree (stream, TYPE_REFERENCE_TO (type)); pph_out_tree (stream, TYPE_NEXT_VARIANT (type)); pph_out_machine_mode (stream, TYPE_MODE (type)); - /* FIXME pph - Streaming TYPE_CANONICAL generates many type comparison - failures. Why? */ + /* We do not write TYPE_CANONICAL. Instead, we emit the table of + canonical types and re-instantiate it on read. */ pph_out_tree (stream, TREE_CHAIN (type)); /* The type values cache is built as constants are instantiated, @@ -2721,7 +2723,11 @@ pph_write_file (pph_stream *stream) pph_out_tree (stream, static_aggregates); pph_out_decl2_hidden_state (stream); - /* Emit the symbol table. */ + pph_out_canonical_template_parms (stream); + + /* Emit the symbol table. The symbol table must be emitted at the + end because all the symbols read from children PPH images are not + known in advance when we start reading this file in the reader. */ pph_out_symtab (stream); if (flag_pph_dump_tree) diff --git a/gcc/cp/pph.h b/gcc/cp/pph.h index e864978..c6ec227 100644 --- a/gcc/cp/pph.h +++ b/gcc/cp/pph.h @@ -147,6 +147,7 @@ extern void pph_dump_tree_name (FILE *file, tree t, int flags); extern void pph_dump_vec_tree (FILE *file, VEC(tree,gc) *v); extern void pph_init_include_tree (void); extern void pph_dump_includes (FILE *, pph_stream *, unsigned); +extern void pph_register_builtin_type (tree); /* In pph-out.c. */ extern void pph_out_uint (pph_stream *stream, unsigned int value); @@ -189,6 +190,10 @@ extern void pph_out_merge_key_template_state (pph_stream *); extern void pph_out_merge_body_template_state (pph_stream *); extern void pph_in_merge_key_template_state (pph_stream *); extern void pph_in_merge_body_template_state (pph_stream *); +extern void pph_out_spec_entry_tables (pph_stream *); +extern void pph_in_spec_entry_tables (pph_stream *); +extern void pph_out_canonical_template_parms (pph_stream *); +extern void pph_in_canonical_template_parms (pph_stream *); /* FIXME pph: These functions should be moved to tree.c on merge. */ extern VEC(tree,heap) *chain2vec (tree chain); /* In pph-out.c. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 9018237..7758dfe25 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3472,6 +3472,37 @@ canonical_type_parameter (tree type) } } + +/* Write the canonical type parameter table to STREAM. */ + +void +pph_out_canonical_template_parms (pph_stream *stream) +{ + tree type; + unsigned i; + + pph_out_uint (stream, VEC_length (tree, canonical_template_parms)); + FOR_EACH_VEC_ELT (tree, canonical_template_parms, i, type) + pph_out_tree (stream, type); +} + + +/* Read the canonical type parameter table from STREAM. */ + +void +pph_in_canonical_template_parms (pph_stream *stream) +{ + unsigned i, len; + + len = pph_in_uint (stream); + for (i = 0; i < len; i++) + { + tree parm = pph_in_tree (stream); + VEC_safe_push (tree, gc, canonical_template_parms, parm); + } +} + + /* Return a TEMPLATE_PARM_INDEX, similar to INDEX, but whose TEMPLATE_PARM_LEVEL has been decreased by LEVELS. If such a TEMPLATE_PARM_INDEX already exists, it is returned; otherwise, a diff --git a/gcc/tree.c b/gcc/tree.c index 2eac37b..89bb013 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -6293,6 +6293,52 @@ type_hash_canon (unsigned int hashcode, tree type) } } +/* Data structure used to pass data to the htab_traverse callback used + in type_hash_table_traverse. */ +struct type_hash_traverse { + bool (*callback) (unsigned long, tree, void *); + void *data; +}; + +/* Helper for type_hash_table_traverse. Retrieve a type hash table element and + call FN with it. Pass DATA as an argument to FN. If FN returns false, + traversal is stopped. */ + +static int +type_hash_table_retrieve_entry (void **slot, void *data) +{ + struct type_hash *h = (struct type_hash *) *slot; + struct type_hash_traverse *e = (struct type_hash_traverse *) data; + return (e->callback (h->hash, h->type, e->data)) ? 1 : 0; +} + + +/* Walk the type hash table, calling function CALLBACK with every element. + CALLBACK receives three arguments: + unsigned long representing the hash value + tree the type with that hash value + data a void * to arbitrary data used by CALLBACK. */ + +void +type_hash_table_traverse (bool (*callback) (unsigned long, tree, void *), + void *data) +{ + struct type_hash_traverse e; + e.callback = callback; + e.data = data; + htab_traverse (type_hash_table, type_hash_table_retrieve_entry, &e); +} + + +/* Return the number of types in the type hash table. */ + +size_t +type_hash_table_length (void) +{ + return htab_elements (type_hash_table); +} + + /* See if the data pointed to by the type hash table is marked. We consider it marked if the type is marked or if a debug type number or symbol table entry has been made for the type. */ @@ -7212,7 +7258,8 @@ build_type_no_quals (tree t) #define MAX_INT_CACHED_PREC \ (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64) -static GTY(()) tree nonstandard_integer_type_cache[2 * MAX_INT_CACHED_PREC + 2]; +#define CACHED_PREC_LEN (2 * MAX_INT_CACHED_PREC + 2) +static GTY(()) tree nonstandard_integer_type_cache[CACHED_PREC_LEN]; /* Builds a signed or unsigned integer type of precision PRECISION. Used for C bitfields whose precision does not match that of @@ -7250,6 +7297,24 @@ build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision, return ret; } + +/* Walk nonstandard_integer_type_cache, calling CALLBACK on every non-NULL + entry. CALLBACK is called with the current tree and DATA. If + CALLBACK returns false, the walk is aborted. */ + +void +traverse_nonstandard_integer_type_cache (bool (*callback) (tree, void *), + void *data) +{ + size_t i; + + for (i = 0; i < CACHED_PREC_LEN; i++) + if (nonstandard_integer_type_cache[i]) + if (!callback (nonstandard_integer_type_cache[i], data)) + return; +} + + /* Create a range of some discrete type TYPE (an INTEGER_TYPE, ENUMERAL_TYPE or BOOLEAN_TYPE) with low bound LOWVAL and high bound HIGHVAL. If SHARED is true, reuse such a type that has already been constructed. */ diff --git a/gcc/tree.h b/gcc/tree.h index b269ee4..5e61992 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -5190,6 +5190,10 @@ extern void assign_assembler_name_if_neeeded (tree); extern void warn_deprecated_use (tree, tree); enum tree_node_structure_enum tree_node_structure_for_code (enum tree_code); void mark_ts_structures_for (enum tree_code, enum tree_node_structure_enum); +void type_hash_table_traverse (bool (*) (unsigned long, tree, void *), void *); +size_t type_hash_table_length (void); +void traverse_nonstandard_integer_type_cache (bool (*callback) (tree, void *), + void *); /* In cgraph.c */ -- 1.7.7.3 -- This patch is available for review at http://codereview.appspot.com/5803043