(remove_AT): Update string ref counts.
(remove_child_TAG): Don't call free_die.
(free_die): Delete.
(break_out_includes): Don't call free_die on DW_TAG_GNU_BINCL
or DW_TAG_GNU_EINCL.
(prune_unused_types_walk_attribs): Reset string refcounts.
(prune_unused_types_update_strings): New.
(prune_unused_types_prune): Don't make unnecessary stores. Don't
call free_die. Do call prune_unused_types_update_strings.
(prune_unused_types): Empty debug_str_hash.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@113012
138bc75d-0d04-0410-961f-
82ee72b054a4
+2006-04-17 Geoffrey Keating <geoffk@apple.com>
+
+ * dwarf2out.c (free_AT): Delete.
+ (remove_AT): Update string ref counts.
+ (remove_child_TAG): Don't call free_die.
+ (free_die): Delete.
+ (break_out_includes): Don't call free_die on DW_TAG_GNU_BINCL
+ or DW_TAG_GNU_EINCL.
+ (prune_unused_types_walk_attribs): Reset string refcounts.
+ (prune_unused_types_update_strings): New.
+ (prune_unused_types_prune): Don't make unnecessary stores. Don't
+ call free_die. Do call prune_unused_types_update_strings.
+ (prune_unused_types): Empty debug_str_hash.
+
2006-04-17 Roger Sayle <roger@eyesopen.com>
* expr.c (expand_assignment): Optimize away no-op moves where the
2006-04-17 Roger Sayle <roger@eyesopen.com>
* expr.c (expand_assignment): Optimize away no-op moves where the
static bool is_ada (void);
static void remove_AT (dw_die_ref, enum dwarf_attribute);
static void remove_child_TAG (dw_die_ref, enum dwarf_tag);
static bool is_ada (void);
static void remove_AT (dw_die_ref, enum dwarf_attribute);
static void remove_child_TAG (dw_die_ref, enum dwarf_tag);
-static inline void free_die (dw_die_ref);
static void add_child_die (dw_die_ref, dw_die_ref);
static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree);
static dw_die_ref lookup_type_die (tree);
static void add_child_die (dw_die_ref, dw_die_ref);
static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree);
static dw_die_ref lookup_type_die (tree);
return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83;
}
return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83;
}
-/* Free up the memory used by A. */
-
-static inline void free_AT (dw_attr_ref);
-static inline void
-free_AT (dw_attr_ref a)
-{
- if (AT_class (a) == dw_val_class_str)
- if (a->dw_attr_val.v.val_str->refcount)
- a->dw_attr_val.v.val_str->refcount--;
-}
-
/* Remove the specified attribute if present. */
static void
/* Remove the specified attribute if present. */
static void
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
if (a->dw_attr == attr_kind)
{
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
if (a->dw_attr == attr_kind)
{
+ if (AT_class (a) == dw_val_class_str)
+ if (a->dw_attr_val.v.val_str->refcount)
+ a->dw_attr_val.v.val_str->refcount--;
+
/* VEC_ordered_remove should help reduce the number of abbrevs
that are needed. */
VEC_ordered_remove (dw_attr_node, die->die_attr, ix);
/* VEC_ordered_remove should help reduce the number of abbrevs
that are needed. */
VEC_ordered_remove (dw_attr_node, die->die_attr, ix);
die->die_child = next;
else
prev->die_sib = next;
die->die_child = next;
else
prev->die_sib = next;
-/* Free up the memory used by DIE, by removing its children and
- anything associated with its attributes. DIEs are garbage
- collected, so there is no actual freeing to do; the only real work is
- to decrease string reference counts. */
-
-static void
-free_die (dw_die_ref die)
-{
- dw_die_ref child_die = die->die_child;
-
- die->die_child = NULL;
-
- while (child_die != NULL)
- {
- dw_die_ref tmp_die = child_die;
- dw_attr_ref a;
- unsigned ix;
-
- child_die = child_die->die_sib;
-
- for (ix = 0; VEC_iterate (dw_attr_node, tmp_die->die_attr, ix, a); ix++)
- free_AT (a);
-
- free_die (tmp_die);
- }
-}
-
/* Add a child DIE below its parent. We build the lists up in reverse
addition order, and correct that in reverse_all_dies. */
/* Add a child DIE below its parent. We build the lists up in reverse
addition order, and correct that in reverse_all_dies. */
*ptr = c->die_sib;
if (c->die_tag == DW_TAG_GNU_BINCL)
*ptr = c->die_sib;
if (c->die_tag == DW_TAG_GNU_BINCL)
- {
- unit = push_new_compile_unit (unit, c);
- free_die (c);
- }
+ unit = push_new_compile_unit (unit, c);
else if (c->die_tag == DW_TAG_GNU_EINCL)
else if (c->die_tag == DW_TAG_GNU_EINCL)
- {
- unit = pop_compile_unit (unit);
- free_die (c);
- }
+ unit = pop_compile_unit (unit);
else
add_child_die (unit, c);
}
else
add_child_die (unit, c);
}
a->dw_attr_val.v.val_unsigned =
maybe_emit_file (a->dw_attr_val.v.val_unsigned);
}
a->dw_attr_val.v.val_unsigned =
maybe_emit_file (a->dw_attr_val.v.val_unsigned);
}
+ /* Set the string's refcount to 0 so that prune_unused_types_mark
+ accounts properly for it. */
+ if (AT_class (a) == dw_val_class_str)
+ a->dw_attr_val.v.val_str->refcount = 0;
prune_unused_types_walk (c);
}
prune_unused_types_walk (c);
}
+/* Increment the string counts on strings referred to from DIE's
+ attributes. */
+
+static void
+prune_unused_types_update_strings (dw_die_ref die)
+{
+ dw_attr_ref a;
+ unsigned ix;
+
+ for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ if (AT_class (a) == dw_val_class_str)
+ {
+ struct indirect_string_node *s = a->dw_attr_val.v.val_str;
+ s->refcount++;
+ /* Avoid unnecessarily putting strings that are used less than
+ twice in the hash table. */
+ if (s->refcount == 2
+ || (s->refcount == 1
+ && (debug_str_section->common.flags & SECTION_MERGE) != 0))
+ {
+ void ** slot;
+ slot = htab_find_slot_with_hash (debug_str_hash, s->str,
+ htab_hash_string (s->str),
+ INSERT);
+ gcc_assert (*slot == NULL);
+ *slot = s;
+ }
+ }
+}
/* Remove from the tree DIE any dies that aren't marked. */
static void
prune_unused_types_prune (dw_die_ref die)
{
/* Remove from the tree DIE any dies that aren't marked. */
static void
prune_unused_types_prune (dw_die_ref die)
{
gcc_assert (die->die_mark);
gcc_assert (die->die_mark);
- p = NULL;
- for (c = die->die_child; c; c = n)
+ p = &die->die_child;
+ while (*p)
- n = c->die_sib;
- if (c->die_mark)
+ dw_die_ref c = *p;
+ if (c && ! c->die_mark)
- prune_unused_types_prune (c);
- p = c;
+ do {
+ c = c->die_sib;
+ } while (c && ! c->die_mark);
+ *p = c;
- if (p)
- p->die_sib = n;
- else
- die->die_child = n;
- free_die (c);
+ prune_unused_types_update_strings (c);
+ prune_unused_types_prune (c);
+ p = &c->die_sib;
for (i = 0; i < arange_table_in_use; i++)
prune_unused_types_mark (arange_table[i], 1);
for (i = 0; i < arange_table_in_use; i++)
prune_unused_types_mark (arange_table[i], 1);
- /* Get rid of nodes that aren't marked. */
+ /* Get rid of nodes that aren't marked; and update the string counts. */
+ if (debug_str_hash)
+ htab_empty (debug_str_hash);
prune_unused_types_prune (comp_unit_die);
for (node = limbo_die_list; node; node = node->next)
prune_unused_types_prune (node->die);
prune_unused_types_prune (comp_unit_die);
for (node = limbo_die_list; node; node = node->next)
prune_unused_types_prune (node->die);