On Fri, Jun 20, 2014 at 08:41:22AM +0200, Jan Hubicka wrote: > Hi, > this patch moves init and fini priorities to symbol table instead of trees. > They are already in on-side hashtables, but the hashtables are now maintaned > by symbol table. This is needed for correctness with LTO. > > Currently tree merging may load declaration with priority and then ggc_free > it creating a stale entry in the hashtable. This is usually not problem, > because > ctor declarations are usually static, but it is not safe. > > I would really like to have template for such a sparse annotations to symbols > (writting our old school pch friendly hashtable is not a fun) but I am not > sure > I can get it done in GGC/PCH safe way. Is user marking working for PCH?
hm, so thinking about this a little more I wonder if you can just use hash_table, and add a dtor to symtab_node that removes its entry from the hash table. ggc should invoke your dtor as a finalizer for the node then. Trev > > Bootstrapped/regtested x86_64-linux, will commit it shortly. > > Honza > > * cgraph.h (struct symtab_node): Add field in_init_priority_hash > (set_init_priority, get_init_priority, set_fini_priority, > get_fini_priority): New methods. > * tree.c (init_priority_for_decl): Remove. > (init_ttree): Do not initialize init priority. > (decl_init_priority_lookup, decl_fini_priority_lookup): Rewrite. > (decl_priority_info): Remove. > (decl_init_priority_insert): Rewrite. > (decl_fini_priority_insert): Rewrite. > * tree.h (tree_priority_map_eq, tree_priority_map_hash, > tree_priority_map_marked_p): Remove. > * lto-cgraph.c (lto_output_node, input_node): Stream init priorities. > * lto-streamer-out.c (hash_tree): Do not hash priorities. > * tree-streamer-out.c (pack_ts_decl_with_vis_value_fields): Do > not output priorities. > (pack_ts_function_decl_value_fields): Likewise. > * tree-streamer-in.c (unpack_ts_decl_with_vis_value_fields): Do > not input priorities. > (unpack_ts_function_decl_value_fields): Likewise. > * symtab.c (symbol_priority_map): Declare. > (init_priority_hash): Declare. > (symtab_unregister_node): Unregister from priority hash, too. > (symtab_node::get_init_priority, cgraph_node::get_fini_priority): > New methods. > (symbol_priority_map_eq, symbol_priority_map_hash): New functions. > (symbol_priority_info): New function. > (symtab_node::set_init_priority, cgraph_node::set_fini_priority): > New methods. > * tree-core.h (tree_priority_map): Remove. > > * lto.c (compare_tree_sccs_1): Do not compare priorities. > Index: cgraph.h > =================================================================== > --- cgraph.h (revision 211831) > +++ cgraph.h (working copy) > @@ -130,6 +130,8 @@ public: > > /* Set when symbol has address taken. */ > unsigned address_taken : 1; > + /* Set when init priority is set. */ > + unsigned in_init_priority_hash : 1; > > > /* Ordering of all symtab entries. */ > @@ -163,6 +165,7 @@ public: > return x_comdat_group; > } > > + /* Return comdat group as identifier_node. */ > tree get_comdat_group_id () > { > if (x_comdat_group && TREE_CODE (x_comdat_group) != IDENTIFIER_NODE) > @@ -208,6 +211,9 @@ public: > /* Set section for symbol and its aliases. */ > void set_section (const char *section); > void set_section_for_node (const char *section); > + > + void set_init_priority (priority_type priority); > + priority_type get_init_priority (); > }; > > enum availability > @@ -497,6 +503,9 @@ public: > /* True if this decl calls a COMDAT-local function. This is set up in > compute_inline_parameters and inline_call. */ > unsigned calls_comdat_local : 1; > + > + void set_fini_priority (priority_type priority); > + priority_type get_fini_priority (); > }; > > > Index: tree.c > =================================================================== > --- tree.c (revision 211831) > +++ tree.c (working copy) > @@ -219,10 +219,6 @@ static GTY ((if_marked ("tree_decl_map_m > static GTY ((if_marked ("tree_vec_map_marked_p"), param_is (struct > tree_vec_map))) > htab_t debug_args_for_decl; > > -static GTY ((if_marked ("tree_priority_map_marked_p"), > - param_is (struct tree_priority_map))) > - htab_t init_priority_for_decl; > - > static void set_type_quals (tree, int); > static int type_hash_eq (const void *, const void *); > static hashval_t type_hash_hash (const void *); > @@ -573,8 +569,6 @@ init_ttree (void) > > value_expr_for_decl = htab_create_ggc (512, tree_decl_map_hash, > tree_decl_map_eq, 0); > - init_priority_for_decl = htab_create_ggc (512, tree_priority_map_hash, > - tree_priority_map_eq, 0); > > int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash, > int_cst_hash_eq, NULL); > @@ -6492,13 +6486,12 @@ tree_decl_map_hash (const void *item) > priority_type > decl_init_priority_lookup (tree decl) > { > - struct tree_priority_map *h; > - struct tree_map_base in; > + symtab_node *snode = symtab_get_node (decl); > > - gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); > - in.from = decl; > - h = (struct tree_priority_map *) htab_find (init_priority_for_decl, &in); > - return h ? h->init : DEFAULT_INIT_PRIORITY; > + if (!snode) > + return DEFAULT_INIT_PRIORITY; > + return > + snode->get_init_priority (); > } > > /* Return the finalization priority for DECL. */ > @@ -6506,39 +6499,12 @@ decl_init_priority_lookup (tree decl) > priority_type > decl_fini_priority_lookup (tree decl) > { > - struct tree_priority_map *h; > - struct tree_map_base in; > - > - gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); > - in.from = decl; > - h = (struct tree_priority_map *) htab_find (init_priority_for_decl, &in); > - return h ? h->fini : DEFAULT_INIT_PRIORITY; > -} > - > -/* Return the initialization and finalization priority information for > - DECL. If there is no previous priority information, a freshly > - allocated structure is returned. */ > - > -static struct tree_priority_map * > -decl_priority_info (tree decl) > -{ > - struct tree_priority_map in; > - struct tree_priority_map *h; > - void **loc; > - > - in.base.from = decl; > - loc = htab_find_slot (init_priority_for_decl, &in, INSERT); > - h = (struct tree_priority_map *) *loc; > - if (!h) > - { > - h = ggc_cleared_alloc<tree_priority_map> (); > - *loc = h; > - h->base.from = decl; > - h->init = DEFAULT_INIT_PRIORITY; > - h->fini = DEFAULT_INIT_PRIORITY; > - } > + cgraph_node *node = cgraph_get_node (decl); > > - return h; > + if (!node) > + return DEFAULT_INIT_PRIORITY; > + return > + node->get_fini_priority (); > } > > /* Set the initialization priority for DECL to PRIORITY. */ > @@ -6546,13 +6512,19 @@ decl_priority_info (tree decl) > void > decl_init_priority_insert (tree decl, priority_type priority) > { > - struct tree_priority_map *h; > + struct symtab_node *snode; > > - gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); > if (priority == DEFAULT_INIT_PRIORITY) > - return; > - h = decl_priority_info (decl); > - h->init = priority; > + { > + snode = symtab_get_node (decl); > + if (!snode) > + return; > + } > + else if (TREE_CODE (decl) == VAR_DECL) > + snode = varpool_node_for_decl (decl); > + else > + snode = cgraph_get_create_node (decl); > + snode->set_init_priority (priority); > } > > /* Set the finalization priority for DECL to PRIORITY. */ > @@ -6560,13 +6532,17 @@ decl_init_priority_insert (tree decl, pr > void > decl_fini_priority_insert (tree decl, priority_type priority) > { > - struct tree_priority_map *h; > + struct cgraph_node *node; > > - gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); > if (priority == DEFAULT_INIT_PRIORITY) > - return; > - h = decl_priority_info (decl); > - h->fini = priority; > + { > + node = cgraph_get_node (decl); > + if (!node) > + return; > + } > + else > + node = cgraph_get_create_node (decl); > + node->set_fini_priority (priority); > } > > /* Print out the statistics for the DECL_DEBUG_EXPR hash table. */ > Index: tree.h > =================================================================== > --- tree.h (revision 211831) > +++ tree.h (working copy) > @@ -4345,10 +4345,6 @@ extern unsigned int tree_decl_map_hash ( > #define tree_int_map_hash tree_map_base_hash > #define tree_int_map_marked_p tree_map_base_marked_p > > -#define tree_priority_map_eq tree_map_base_eq > -#define tree_priority_map_hash tree_map_base_hash > -#define tree_priority_map_marked_p tree_map_base_marked_p > - > #define tree_vec_map_eq tree_map_base_eq > #define tree_vec_map_hash tree_decl_map_hash > #define tree_vec_map_marked_p tree_map_base_marked_p > Index: lto-cgraph.c > =================================================================== > --- lto-cgraph.c (revision 211831) > +++ lto-cgraph.c (working copy) > @@ -557,6 +557,10 @@ lto_output_node (struct lto_simple_outpu > streamer_write_uhwi_stream (ob->main_stream, > node->thunk.virtual_value); > } > streamer_write_hwi_stream (ob->main_stream, node->profile_id); > + if (DECL_STATIC_CONSTRUCTOR (node->decl)) > + streamer_write_hwi_stream (ob->main_stream, DECL_INIT_PRIORITY > (node->decl)); > + if (DECL_STATIC_DESTRUCTOR (node->decl)) > + streamer_write_hwi_stream (ob->main_stream, DECL_FINI_PRIORITY > (node->decl)); > } > > /* Output the varpool NODE to OB. > @@ -1210,6 +1214,10 @@ input_node (struct lto_file_decl_data *f > if (node->alias && !node->analyzed && node->weakref) > node->alias_target = get_alias_symbol (node->decl); > node->profile_id = streamer_read_hwi (ib); > + if (DECL_STATIC_CONSTRUCTOR (node->decl)) > + SET_DECL_INIT_PRIORITY (node->decl, streamer_read_hwi (ib)); > + if (DECL_STATIC_DESTRUCTOR (node->decl)) > + SET_DECL_FINI_PRIORITY (node->decl, streamer_read_hwi (ib)); > return node; > } > > Index: lto-streamer-out.c > =================================================================== > --- lto-streamer-out.c (revision 211831) > +++ lto-streamer-out.c (working copy) > @@ -827,8 +827,6 @@ hash_tree (struct streamer_tree_cache_d > | (DECL_CXX_CONSTRUCTOR_P (t) << 1) > | (DECL_CXX_DESTRUCTOR_P (t) << 2), > v); > - if (VAR_OR_FUNCTION_DECL_P (t)) > - v = iterative_hash_host_wide_int (DECL_INIT_PRIORITY (t), v); > } > > if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL)) > @@ -852,8 +850,6 @@ hash_tree (struct streamer_tree_cache_d > | (DECL_LOOPING_CONST_OR_PURE_P (t) << > 15), v); > if (DECL_BUILT_IN_CLASS (t) != NOT_BUILT_IN) > v = iterative_hash_host_wide_int (DECL_FUNCTION_CODE (t), v); > - if (DECL_STATIC_DESTRUCTOR (t)) > - v = iterative_hash_host_wide_int (DECL_FINI_PRIORITY (t), v); > } > > if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON)) > Index: lto/lto.c > =================================================================== > --- lto/lto.c (revision 211831) > +++ lto/lto.c (working copy) > @@ -1300,8 +1300,6 @@ compare_tree_sccs_1 (tree t1, tree t2, t > /* DECL_IN_TEXT_SECTION is set during final asm output only. */ > compare_values (DECL_IN_CONSTANT_POOL); > } > - if (VAR_OR_FUNCTION_DECL_P (t1)) > - compare_values (DECL_INIT_PRIORITY); > } > > if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL)) > @@ -1328,8 +1326,6 @@ compare_tree_sccs_1 (tree t1, tree t2, t > compare_values (DECL_CXX_DESTRUCTOR_P); > if (DECL_BUILT_IN_CLASS (t1) != NOT_BUILT_IN) > compare_values (DECL_FUNCTION_CODE); > - if (DECL_STATIC_DESTRUCTOR (t1)) > - compare_values (DECL_FINI_PRIORITY); > } > > if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON)) > Index: tree-streamer-out.c > =================================================================== > --- tree-streamer-out.c (revision 211831) > +++ tree-streamer-out.c (working copy) > @@ -256,8 +256,6 @@ pack_ts_decl_with_vis_value_fields (stru > bp_pack_value (bp, DECL_CXX_CONSTRUCTOR_P (expr), 1); > bp_pack_value (bp, DECL_CXX_DESTRUCTOR_P (expr), 1); > } > - if (VAR_OR_FUNCTION_DECL_P (expr)) > - bp_pack_var_len_unsigned (bp, DECL_INIT_PRIORITY (expr)); > } > > > @@ -291,8 +289,6 @@ pack_ts_function_decl_value_fields (stru > bp_pack_value (bp, DECL_LOOPING_CONST_OR_PURE_P (expr), 1); > if (DECL_BUILT_IN_CLASS (expr) != NOT_BUILT_IN) > bp_pack_value (bp, DECL_FUNCTION_CODE (expr), 11); > - if (DECL_STATIC_DESTRUCTOR (expr)) > - bp_pack_var_len_unsigned (bp, DECL_FINI_PRIORITY (expr)); > } > > > Index: tree-streamer-in.c > =================================================================== > --- tree-streamer-in.c (revision 211831) > +++ tree-streamer-in.c (working copy) > @@ -288,12 +288,6 @@ unpack_ts_decl_with_vis_value_fields (st > DECL_CXX_CONSTRUCTOR_P (expr) = (unsigned) bp_unpack_value (bp, 1); > DECL_CXX_DESTRUCTOR_P (expr) = (unsigned) bp_unpack_value (bp, 1); > } > - if (VAR_OR_FUNCTION_DECL_P (expr)) > - { > - priority_type p; > - p = (priority_type) bp_unpack_var_len_unsigned (bp); > - SET_DECL_INIT_PRIORITY (expr, p); > - } > } > > > @@ -336,12 +330,6 @@ unpack_ts_function_decl_value_fields (st > fatal_error ("target specific builtin not available"); > } > } > - if (DECL_STATIC_DESTRUCTOR (expr)) > - { > - priority_type p; > - p = (priority_type) bp_unpack_var_len_unsigned (bp); > - SET_DECL_FINI_PRIORITY (expr, p); > - } > } > > > Index: symtab.c > =================================================================== > --- symtab.c (revision 211831) > +++ symtab.c (working copy) > @@ -64,6 +64,17 @@ static GTY((param_is (section_hash_entry > /* Hash table used to convert assembler names into nodes. */ > static GTY((param_is (symtab_node))) htab_t assembler_name_hash; > > +/* Map from a symbol to initialization/finalization priorities. */ > +struct GTY(()) symbol_priority_map { > + symtab_node *symbol; > + priority_type init; > + priority_type fini; > +}; > + > +/* Hash table used to hold init priorities. */ > +static GTY ((param_is (struct symbol_priority_map))) > + htab_t init_priority_hash; > + > /* Linked list of symbol table nodes. */ > symtab_node *symtab_nodes; > > @@ -337,6 +348,16 @@ symtab_unregister_node (symtab_node *nod > } > if (!is_a <varpool_node *> (node) || !DECL_HARD_REGISTER (node->decl)) > unlink_from_assembler_name_hash (node, false); > + if (node->in_init_priority_hash) > + { > + struct symbol_priority_map in; > + void **slot; > + in.symbol = node; > + > + slot = htab_find_slot (init_priority_hash, &in, NO_INSERT); > + if (slot) > + htab_clear_slot (init_priority_hash, slot); > + } > } > > > @@ -1176,6 +1197,122 @@ symtab_node::set_section (const char *se > symtab_for_node_and_aliases (this, set_section_1, const_cast<char > *>(section), true); > } > > +/* Return the initialization priority. */ > + > +priority_type > +symtab_node::get_init_priority () > +{ > + struct symbol_priority_map *h; > + struct symbol_priority_map in; > + > + if (!this->in_init_priority_hash) > + return DEFAULT_INIT_PRIORITY; > + in.symbol = this; > + h = (struct symbol_priority_map *) htab_find (init_priority_hash, &in); > + return h ? h->init : DEFAULT_INIT_PRIORITY; > +} > + > +/* Return the finalization priority. */ > + > +priority_type > +cgraph_node::get_fini_priority () > +{ > + struct symbol_priority_map *h; > + struct symbol_priority_map in; > + > + if (!this->in_init_priority_hash) > + return DEFAULT_INIT_PRIORITY; > + in.symbol = this; > + h = (struct symbol_priority_map *) htab_find (init_priority_hash, &in); > + return h ? h->fini : DEFAULT_INIT_PRIORITY; > +} > + > +/* Return true if the from tree in both priority maps are equal. */ > + > +int > +symbol_priority_map_eq (const void *va, const void *vb) > +{ > + const struct symbol_priority_map *const a = (const struct > symbol_priority_map *) va, > + *const b = (const struct symbol_priority_map *) vb; > + return (a->symbol == b->symbol); > +} > + > +/* Hash a from symbol in a symbol_priority_map. */ > + > +unsigned int > +symbol_priority_map_hash (const void *item) > +{ > + return htab_hash_pointer (((const struct symbol_priority_map > *)item)->symbol); > +} > + > +/* Return the initialization and finalization priority information for > + DECL. If there is no previous priority information, a freshly > + allocated structure is returned. */ > + > +static struct symbol_priority_map * > +symbol_priority_info (struct symtab_node *symbol) > +{ > + struct symbol_priority_map in; > + struct symbol_priority_map *h; > + void **loc; > + > + in.symbol = symbol; > + if (!init_priority_hash) > + init_priority_hash = htab_create_ggc (512, symbol_priority_map_hash, > + symbol_priority_map_eq, 0); > + > + loc = htab_find_slot (init_priority_hash, &in, INSERT); > + h = (struct symbol_priority_map *) *loc; > + if (!h) > + { > + h = ggc_cleared_alloc<symbol_priority_map> (); > + *loc = h; > + h->symbol = symbol; > + h->init = DEFAULT_INIT_PRIORITY; > + h->fini = DEFAULT_INIT_PRIORITY; > + symbol->in_init_priority_hash = true; > + } > + > + return h; > +} > + > +/* Set initialization priority to PRIORITY. */ > + > +void > +symtab_node::set_init_priority (priority_type priority) > +{ > + struct symbol_priority_map *h; > + > + if (is_a <cgraph_node *> (this)) > + gcc_assert (DECL_STATIC_CONSTRUCTOR (this->decl)); > + > + if (priority == DEFAULT_INIT_PRIORITY) > + { > + gcc_assert (get_init_priority() == priority); > + return; > + } > + h = symbol_priority_info (this); > + h->init = priority; > +} > + > +/* Set fialization priority to PRIORITY. */ > + > +void > +cgraph_node::set_fini_priority (priority_type priority) > +{ > + struct symbol_priority_map *h; > + > + gcc_assert (DECL_STATIC_DESTRUCTOR (this->decl)); > + > + if (priority == DEFAULT_INIT_PRIORITY) > + { > + gcc_assert (get_fini_priority() == priority); > + return; > + } > + h = symbol_priority_info (this); > + h->fini = priority; > +} > + > /* Worker for symtab_resolve_alias. */ > > static bool > Index: tree-core.h > =================================================================== > --- tree-core.h (revision 211831) > +++ tree-core.h (working copy) > @@ -1761,13 +1761,6 @@ struct GTY(()) tree_int_map { > unsigned int to; > }; > > -/* Map from a tree to initialization/finalization priorities. */ > -struct GTY(()) tree_priority_map { > - struct tree_map_base base; > - priority_type init; > - priority_type fini; > -}; > - > /* Map from a decl tree to a tree vector. */ > struct GTY(()) tree_vec_map { > struct tree_map_base base;