summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2011-02-16 09:14:23 +0100
committerMark Wielaard <mjw@redhat.com>2011-03-16 15:05:27 +0100
commit4c6a8c74352f95bd4a39851ddc6ff936959f0d8f (patch)
tree5852ba2f5065d0c9fdece13083215bbf1b902a17
parentb8d66b1de27b1c407115fb15e572e9b5b00dc871 (diff)
downloadelfutils-4c6a8c74352f95bd4a39851ddc6ff936959f0d8f.tar.gz
Don't finalize entries on first go, just create and store die_info for them.
Do all finalization for the whole CU after walking the whole tree.
-rw-r--r--libdw/c++/dwarf_output41
1 files changed, 24 insertions, 17 deletions
diff --git a/libdw/c++/dwarf_output b/libdw/c++/dwarf_output
index 58a0b76c..401aec67 100644
--- a/libdw/c++/dwarf_output
+++ b/libdw/c++/dwarf_output
@@ -1000,11 +1000,11 @@ namespace elfutils
inline die_info_pair *add_entry (int tag,
const children_type *children,
const attrs_type *attrs,
- size_t local_hash)
+ die_info *info)
{
std::pair <die_map::iterator, bool>
ins = _m_unique.insert (std::make_pair (die_type (tag, children, attrs),
- die_info (local_hash)));
+ *info));
die_info_pair &x = *ins.first;
if (ins.second)
x.second.assert_unused ();
@@ -1285,9 +1285,14 @@ namespace elfutils
// Set if _m_children contains any entries not already final.
bool _m_unfinished_children;
+ // The die_info that will be used when putting the die into
+ // the collector. Stores local hash as soon as all children
+ // are defined in defined_self ().
+ die_info *_m_info;
+
inline pending_entry (int tag)
: _m_finalizing (NULL), _m_self (NULL), _m_matched (NULL),
- _m_tag (tag), _m_unfinished_children (false)
+ _m_tag (tag), _m_unfinished_children (false), _m_info (NULL)
{}
inline ~pending_entry ()
@@ -1397,8 +1402,8 @@ namespace elfutils
it != _m_children.end ();
++it)
{
- die_info_pair *final_child = get_final_child (*it);
- size_t child_lhash = final_child->second._m_local_hash;
+ size_t child_lhash;
+ child_lhash = (*it)->_m_pending->_m_info->_m_local_hash;
subr::hash_combine (children_hash, child_lhash);
}
subr::hash_combine (lhash, children_hash);
@@ -1416,9 +1421,6 @@ namespace elfutils
bool fresh = false;
if (_m_matched == NULL)
{
- size_t lhash = calculate_local_hash ();
-
- // XXX We should drop this cache, or use the lhash in it...
attrs_matcher equalator (c);
const debug_info_entry::attributes_type *attrs
= &co->add_attributes (_m_tag, _m_attributes, equalator)->first;
@@ -1428,7 +1430,7 @@ namespace elfutils
(_m_children, std::ptr_fun (get_final_child)),
fresh);
- _m_matched = co->add_entry (_m_tag, children, attrs, lhash);
+ _m_matched = co->add_entry (_m_tag, children, attrs, _m_info);
}
// Final bookkeeping in the collector for this copied entry.
@@ -1627,10 +1629,9 @@ namespace elfutils
}
/* We are no longer an undefined entry, so decrement the count.
- Then finalize as much as we can now. We attempt finalization
- even when the count is nonzero, so that a leaf entry with no
- forward references finishes immediately, and so then can its
- parents and on up if they don't own any pending references. */
+ But don't finalize yet. Since all children are known now we
+ can create a candidate die_info that includes the local hash
+ for this entry. */
inline void defined_self (copier *c)
{
assert (_m_final == NULL);
@@ -1638,9 +1639,9 @@ namespace elfutils
assert (c->_m_undefined_entries > 0);
--c->_m_undefined_entries;
dump () << " defined_self => " << c->_m_undefined_entries << "\n";
- finalize (c);
- if (_m_final == NULL)
- assert (c->_m_undefined_entries > 0);
+
+ size_t lhash = _m_pending->calculate_local_hash ();
+ _m_pending->_m_info = new die_info (lhash);
}
/* A reference-following matching operation noticed along
@@ -1907,11 +1908,17 @@ namespace elfutils
return *_m_copier;
}
- /* Complain if we still have dangling references.
+ /* Try to finalize everything at once.
+ Complain if we still have dangling references.
If not, it should be impossible to have pending entries left. */
inline die_info_pair *final_unit () const
{
assert (_m_out == NULL);
+
+ // We should now be able to finalize everything at once.
+ if (_m_copier->_m_undefined_entries == 0)
+ _m_in->finalize (_m_copier);
+
if (unlikely (_m_in->_m_final == NULL))
{
_m_in->dump_entry ();