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.