On Tue, 2013-09-10 at 15:34 +0200, Jan Hubicka wrote: Thanks for reviewing this, and sorry for the late response (I lost most of last week to illness). Some questions inline below...
> > This patch is the handwritten part of the conversion of these types > > to C++; it requires the followup patch, which is autogenerated. > > > > It converts: > > struct GTY(()) symtab_node_base > > to: > > class GTY((user)) symtab_node_base > > > > and converts: > > struct GTY(()) cgraph_node > > to: > > struct GTY((user)) cgraph_node : public symtab_node_base > > > > and: > > struct GTY(()) varpool_node > > to: > > class GTY((user)) varpool_node : public symtab_node_base > > > > dropping the symtab_node_def union. > > > > Since gengtype is unable to cope with inheritance, we have to mark the > > types with GTY((user)), and handcode the gty field-visiting functions. > > Given the simple hierarchy, we don't need virtual functions for this. > > > > Unfortunately doing so runs into various bugs in gengtype's handling > > of GTY((user)), so the patch also includes workarounds for these bugs. > > > > gengtype walks the graph of the *types* in the code, and produces > > functions in gtype-desc.[ch] for all types that are reachable from a > > GTY root. > > > > However, it ignores the contents of GTY((user)) types when walking > > this graph. > > > > Hence if you have a subgraph of types that are only reachable > > via fields in GTY((user)) types, gengtype won't generate helper code > > for those types. > > > > Ideally there would be some way to mark a GTY((user)) type to say > > which types it references, to avoid having to mark these types as > > GTY((user)). > > > > For now, work around this issue by providing explicit roots of the > > missing types, of dummy variables (see the bottom of cgraph.c) > > [..] > > diff --git a/gcc/cgraph.c b/gcc/cgraph.c > > index f12bf1b..4b12163 100644 > > --- a/gcc/cgraph.c > > +++ b/gcc/cgraph.c > > @@ -2994,4 +2994,222 @@ cgraph_get_body (struct cgraph_node *node) > > return true; > > } > > > > +/* GTY((user)) hooks for symtab_node_base (and its subclasses). > > + We could use virtual functions for this, but given the presence of the > > + "type" field and the trivial size of the class hierarchy, switches are > > + perhaps simpler and faster. */ > > + > > +void gt_ggc_mx (symtab_node_base *x) > > +{ > > + /* Hand-written equivalent of the chain_next/chain_prev machinery, to > > + avoid deep call-stacks. > > + > > + Locate the neighbors of x (within the linked-list) that haven't been > > + marked yet, so that x through xlimit give a range suitable for > > marking. > > + Note that x (on entry) itself has already been marked by the > > + gtype-desc.c code, so we first try its successor. > > + */ > > + symtab_node_base * xlimit = x ? x->next : NULL; > > + while (ggc_test_and_set_mark (xlimit)) > > + xlimit = xlimit->next; > > + if (x != xlimit) > > + for (;;) > > + { > > + symtab_node_base * const xprev = x->previous; > > + if (xprev == NULL) break; > > + x = xprev; > > + (void) ggc_test_and_set_mark (xprev); > > + } > > + while (x != xlimit) > > + { > > + /* Code common to all symtab nodes. */ > > + gt_ggc_m_9tree_node (x->decl); > > + gt_ggc_mx_symtab_node_base (x->next); > Aren't you marking next twice? Once by xlimit walk and one by recursion? Good catch; removed. > > + gt_ggc_mx_symtab_node_base (x->previous); The comment above also applies to "previous", so I've removed this also. > > + gt_ggc_mx_symtab_node_base (x->next_sharing_asm_name); > > + gt_ggc_mx_symtab_node_base (x->previous_sharing_asm_name); > > + gt_ggc_mx_symtab_node_base (x->same_comdat_group); > > You can skip marking these. They only point within symbol table and > not externally. OK; removed. > > + gt_ggc_m_20vec_ipa_ref_t_va_gc_ (x->ref_list.references); > > + gt_ggc_m_9tree_node (x->alias_target); > > + gt_ggc_m_18lto_file_decl_data (x->lto_file_data); > > + > > + /* Extra code, per subclass. */ > > + switch (x->type) > Didn't we agreed on the is_a API? There's just one interesting subclass here, so I've converted this to: if (cgraph_node *cgn = dyn_cast <cgraph_node *> (x)) { eliminating the switch and static_cast. > > + { > > + case SYMTAB_FUNCTION: > > + { > > > + cgraph_node *cgn = static_cast <cgraph_node *> (x); > > + gt_ggc_m_11cgraph_edge (cgn->callees); > > + gt_ggc_m_11cgraph_edge (cgn->callers); > > + gt_ggc_m_11cgraph_edge (cgn->indirect_calls); > > + gt_ggc_m_11cgraph_node (cgn->origin); > > + gt_ggc_m_11cgraph_node (cgn->nested); > > + gt_ggc_m_11cgraph_node (cgn->next_nested); > > + gt_ggc_m_11cgraph_node (cgn->next_sibling_clone); > > + gt_ggc_m_11cgraph_node (cgn->prev_sibling_clone); > > + gt_ggc_m_11cgraph_node (cgn->clones); > > + gt_ggc_m_11cgraph_node (cgn->clone_of); > Same as here. Sorry, it's not clear to me what you meant by "Same as here." here. Do you mean that I can skip marking them because they're within the symbol table? If so, are you referring to all 10 fields above ("callees" through "clone_of")? > > > + gt_ggc_m_P11cgraph_edge4htab (cgn->call_site_hash); > Move call site hash out of GGC rather than introducing hack. I see that this is allocated in cgraph_edge (), and it appears to be an index. I can create it with htab_create rather than htab_create_ggc, but if so, there doesn't seem a natural place to call htab_delete. Is that OK? > > + gt_ggc_m_9tree_node (cgn->former_clone_of); > > + gt_ggc_m_11cgraph_node (cgn->global.inlined_to); > And here Again, do you mean that "inlined_to" can be skipped since it's in the symbol table? > > + gt_ggc_m_28vec_ipa_replace_map_p_va_gc_ (cgn->clone.tree_map); > > + gt_ggc_m_15bitmap_head_def (cgn->clone.args_to_skip); > > + gt_ggc_m_15bitmap_head_def (cgn->clone.combined_args_to_skip); > > + gt_ggc_m_9tree_node (cgn->thunk.alias); > > + } > > + break; > > + default: > > + break; > > + } > > + x = x->next; > > + } > > +} > > + > > +void gt_pch_nx (symtab_node_base *x) > > +{ > > + symtab_node_base * xlimit = x ? x->next : NULL; > > + while (gt_pch_note_object (xlimit, xlimit, gt_pch_p_16symtab_node_base)) > > + xlimit = xlimit->next; > > + if (x != xlimit) > > + for (;;) > > + { > > + symtab_node_base * const xprev = x->previous; > > + if (xprev == NULL) break; > > + x = xprev; > > + (void) gt_pch_note_object (xprev, xprev, > > + gt_pch_p_16symtab_node_base); > > + } > > + while (x != xlimit) > > + { > > + /* Code common to all symtab nodes. */ > > + gt_pch_n_9tree_node (x->decl); > > + gt_pch_nx_symtab_node_base (x->next); > > + gt_pch_nx_symtab_node_base (x->previous); > > + gt_pch_nx_symtab_node_base (x->next_sharing_asm_name); > > + gt_pch_nx_symtab_node_base (x->previous_sharing_asm_name); > > + gt_pch_nx_symtab_node_base (x->same_comdat_group); > > + gt_pch_n_20vec_ipa_ref_t_va_gc_ (x->ref_list.references); > > + gt_pch_n_9tree_node (x->alias_target); > > + gt_pch_n_18lto_file_decl_data (x->lto_file_data); > > + > > + /* Extra code, per subclass. */ > > + switch (x->type) > > + { > > + case SYMTAB_FUNCTION: > > + { > > + cgraph_node *cgn = static_cast <cgraph_node *> (x); > > + gt_pch_n_11cgraph_edge (cgn->callees); > > + gt_pch_n_11cgraph_edge (cgn->callers); > > + gt_pch_n_11cgraph_edge (cgn->indirect_calls); > > + gt_pch_n_11cgraph_node (cgn->origin); > > + gt_pch_n_11cgraph_node (cgn->nested); > > + gt_pch_n_11cgraph_node (cgn->next_nested); > > + gt_pch_n_11cgraph_node (cgn->next_sibling_clone); > > + gt_pch_n_11cgraph_node (cgn->prev_sibling_clone); > > + gt_pch_n_11cgraph_node (cgn->clones); > > + gt_pch_n_11cgraph_node (cgn->clone_of); > > + gt_pch_n_P11cgraph_edge4htab (cgn->call_site_hash); > > + gt_pch_n_9tree_node (cgn->former_clone_of); > > + gt_pch_n_11cgraph_node (cgn->global.inlined_to); > > + gt_pch_n_28vec_ipa_replace_map_p_va_gc_ (cgn->clone.tree_map); > > + gt_pch_n_15bitmap_head_def (cgn->clone.args_to_skip); > > + gt_pch_n_15bitmap_head_def (cgn->clone.combined_args_to_skip); > > + gt_pch_n_9tree_node (cgn->thunk.alias); > > We can skip good part of those. Just small of those is build at PCH time. But > lets do that incrementally, PCH is touchy business. OK. I'll just make analogous changes here to those made to the gt_ggc_mx function. > > The patch is OK with those changes. The dummy workarounds are ugly :( > Honza Thanks.