Interesting. My first reaction is that this is an invalid use of the
garbage collector. I think there is really only one valid function
that can be used as an if_marked function: one which checks
ggc_marked_p on the structure.
Then how about tree_map_base_marked_p, the if_marked function for
value_expr_for_decl?
tree.h:
...
struct GTY(()) tree_map_base {
tree from;
};
struct GTY(()) tree_decl_map {
struct tree_map_base base;
tree to;
};
#define tree_decl_map_marked_p tree_map_base_marked_p
...
tree.c:
...
static GTY ((if_marked ("tree_decl_map_marked_p"), param_is (struct
tree_decl_map)))
htab_t value_expr_for_decl;
int
tree_map_base_marked_p (const void *p)
{
return ggc_marked_p (((const struct tree_map_base *) p)->from);
}
...
The tree_map_base_marked_p checks ggc_marked_p on the from field.
During ggc_scan_cache_tab, if the from field is live, also the to
field is marked live.
I wrote some code to do sanity testing and found a similar scenario
as before:
- a register attribute is not marked live during root marking
- reg_attrs_htab is traversed, and the hash table entry corresponding
to the register attribute is removed
- value_expr_for_decl is traversed, a from field is found live, so
the to field is also marked live, marking the register attribute live.
Is this valid use of the garbage collector?