@@ -1,5 +1,18 @@
2012-03-04 Diego Novillo <dnovillo@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 <dnovillo@google.com>
+
Merge from trunk rev 184817.
BASE-VER: Update to 4.8.0-pph.
@@ -1,3 +1,30 @@
+2012-03-13 Diego Novillo <dnovillo@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 <crowl@google.com>
* name-lookup.c (pph_out_binding_table): Correct comment.
@@ -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.
@@ -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));
}
@@ -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)
@@ -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)
@@ -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. */
@@ -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
@@ -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. */
@@ -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 */