https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118790

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org,
                   |                            |rguenth at gcc dot gnu.org

--- Comment #12 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
This looks like a GC bug.
On the id_string.55 DECL_HAS_VALUE_EXPR_P bit is set and DECL_VALUE_EXPR is set
to
COMPONENT_REF during streaming in.
But then
#0  pointer_hash<tree_decl_map>::mark_deleted (e=@0x7fffea128850: 0x1) at
../../gcc/hash-traits.h:204
#1  0x000000000110d844 in hash_table<tree_decl_map_cache_hasher, false,
xcallocator>::mark_deleted (v=@0x7fffea128850: 0x1) at
../../gcc/hash-table.h:552
#2  0x000000000110b81c in hash_table<tree_decl_map_cache_hasher, false,
xcallocator>::clear_slot (this=0x7fffea12a070, slot=0x7fffea128850) at
../../gcc/hash-table.h:969
#3  0x0000000001107f8c in gt_cleare_cache<tree_decl_map_cache_hasher>
(h=0x7fffea12a070) at ../../gcc/hash-table.h:1315
#4  0x0000000001104afe in gt_clear_caches_gt_tree_h () at ./gt-tree.h:497
#5  0x000000000044c95a in gt_clear_caches () at ./gtype-lto.h:1926
#6  0x0000000000771633 in ggc_mark_roots () at ../../gcc/ggc-common.cc:112
#7  0x0000000000490cb8 in ggc_collect (mode=GGC_COLLECT_HEURISTIC) at
../../gcc/ggc-page.cc:2231
#8  0x0000000000b0ce79 in execute_one_pass (pass=<opt_pass* 0x3d1db80
"expand"(277)>) at ../../gcc/passes.cc:2751
marks the it in the value_expr_for_decl as deleted, because is ggc_marked_p
false on it.
But that very same id_string.55 var is then ggc_set_mark marked because there
is
id_string var with *id_string.55 DECL_VALUE_EXPR later in the
value_expr_for_decl hash table.

gt_cleare_cache does only one pass through a hash_map:
  for (typename table::iterator iter = h->begin (); iter != h->end (); ++iter)
    if (!table::is_empty (*iter) && !table::is_deleted (*iter))
      {
        int res = H::keep_cache_entry (*iter);
        if (res == 0)
          h->clear_slot (&*iter);
        else if (res != -1)
          H::ggc_mx (*iter);
      }
So, either the VAR_DECL should be reachable from something other than
DECL_VALUE_EXPR expressions (bet it was originally in local decls of
something), or we need to have two passes over hash_maps, in the first pass
just H::ggc_mx (*iter) on entries where res is not 0 nor -1, and in the second
pass clear_slot of res is 0.
Guess that needs to be done only for hash tables where keep_cache_entry returns
0/1 rather than 0/-1, though no idea how to that out during instantiation.
And I wonder about references from multiple cache hash maps, say
DECL_DEBUG_EXPR refers to something which has DECL_VALUE_EXPR or vice versa.
Wouldn't we then need to do it always in two passes for all the cache hash
tables,
during proper marking walk all those hash tables and just H::ggc_mx (*iter)
when keep_cache_entry returns 1, and then once everything is marked repeat the
walks and only do the clear_slot?

Reply via email to