On 10/11/11 11:05:18, Eric Botcazou wrote:
> > One easy way to address the current issue is to call
> > tree_int_cst_equal() if the integer constant tree pointers
> > do not match:
> >
> >     if ((c1 != c2) && !tree_int_cst_equal (c1, c2))
> >       /* integer constants aren't equal.  */
> 
> You have two objects C1 and C2 for the same constant and you're comparing
> them. One was created first, say C1.  If C1 was still live when C2 was
> created, why was C2 created in the first class?  If C1 wasn't live
> anymore when C2 was created, why are you still using C1 here?

Eric, this note provides some more detail in addition to my
earlier reply to Richard.

The problem is that the references to object C1 and C2 live in
a hash table, and that although the referenced nodes will be retained
by the garbage collector, their mapping in int_cst_hash_table is
deleted by the GC.

Thus, if we follow the diagram:

 tree (type) -> [ upc_block_factor_for_type ]
                 -> tree (integer constant)
 tree (integer constant) -> [ int_cst_hash_table ] {unique map}
                         -> tree (integer constant)

Given two tree nodes, P (prototype) and F (function) they declare
a parameter that is pointer to a UPC shared object and this pointer
is declared with a UPC blocking factor of 1000.  Without garbage
collection, the mappings look like this:

 P.param -> C1, F.param -> C1 where C1 is an integer constant of
                           the form (sizetype, 1000).

but when GC kicks in, it decides that the hash table entry
in int_cst_hash_table can be deleted because it doesn't think
that C1 is live.  Therefore the next attempt to map (sizetype, 1000)
will yield a new integral constant tree node, C2.  Then the mapping
changes to: P.param -> C1, F.param -> C2, and we can no longer use

  TYPE_UPC_BLOCKING_FACTOR (P.param) == TYPE_UPC_BLOCKING_FACTOR (F.param)

to check that the blocking factors of P.param and F.param are equal.

For the GC to know that int_cst_hash_table
entry is needed, perhaps the upc_block_factor_for_type needs
to be traversed, and then each integer constant needs to be
"marked", or the constant has to be hashed into int_cst_hash_table
and the actual hash table entry has to be marked.

I am not familiar with the details of garbage collection and
pretty much just try use existing code as a model.  Apparently,
this sequence of statements is insufficient to tell the GC that it should
mark the integer constants referenced in this hash table as "in use".

  static GTY ((if_marked ("tree_map_marked_p"),
             param_is (struct tree_map)))
       htab_t upc_block_factor_for_type;
[...]
 upc_block_factor_for_type = htab_create_ggc (512, tree_map_hash
                                              tree_map_eq, 0);

Reading the GC code:

static int
ggc_htab_delete (void **slot, void *info)
{
  const struct ggc_cache_tab *r = (const struct ggc_cache_tab *) info;

  if (! (*r->marked_p) (*slot))
    htab_clear_slot (*r->base, slot);
  else
    (*r->cb) (*slot);

  return 1;
}

It appears that the int_cst_hash_table entry for C1 needs to be
marked or it will be cleared.  I don't know how to set things
up so that so that the garbage collecting mechanisms are in
place to do that, and was hoping that tree_map_hash table
would provide the required mechanisms.  Apparently, this is
not the case.

I had hoped that this declaration would be sufficient to convince
the GC to consider all mapped integer constant nodes to be "live".
If not, then perhaps I need a GC hook associated with
upc_block_factor_for_type that does something like the following:

  for t (each used upc_block_factor_for_type entry):
    c = t.to  # the mapped integer constant
    if is_integer_constant (c):
      h = int_cst_hash_table.hash(c)
      gc_mark_htab (int_cst_hash_table, h)

or perhaps this is sufficient?

  for t (each used upc_block_factor_for_type entry):
    c = t.to
    gc_mark_tree_node (c)

However, I thought that this would already have been done
automatically by the GC hash tree implementation.

If either of those methods are required, I would appreciate
suggestions/pointers/code that would help me make sure that
this approach is implemented correctly.

thanks,
- Gary

Reply via email to