summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2011-01-20 15:28:59 +0100
committerMark Wielaard <mjw@redhat.com>2011-03-16 15:05:27 +0100
commit4a5f27364dcd30d43c49ac7292e29cd7cf7530d8 (patch)
tree1f8c03bddd36907be1f4c599ed9ef4b4e1dacd59
parent17a29217e9145989ca15479132f8d6d8f80f0258 (diff)
downloadelfutils-4a5f27364dcd30d43c49ac7292e29cd7cf7530d8.tar.gz
Introduce local_hash for dwarf_output debug_info_die.
Very simplistic local_hash implementation. Just takes tag name, attributes and children sizes into account. But is good enough to make all the dwarf_edit_output tests pass. Some dwarfcmp-test-self tests fail though. it also generates a significant number of collissions for the dwarf_output_collector attr_sets.
-rw-r--r--libdw/c++/dwarf_output59
1 files changed, 46 insertions, 13 deletions
diff --git a/libdw/c++/dwarf_output b/libdw/c++/dwarf_output
index ac546267..d9852535 100644
--- a/libdw/c++/dwarf_output
+++ b/libdw/c++/dwarf_output
@@ -393,6 +393,18 @@ namespace elfutils
{
return 0;
}
+
+ /* The hash as used for a reference attribute value that points
+ to this die. Only uses "local" (non-reference) values. The
+ culculation should match the pending_entry::local_hash ()
+ method result. */
+ inline size_t local_hash () const
+ {
+ size_t hash = _m_tag;
+ subr::hash_combine (hash, _m_attributes->size ());
+ subr::hash_combine (hash, _m_children->size ());
+ return hash;
+ }
};
struct value::value_reference
@@ -409,13 +421,12 @@ namespace elfutils
: _base (i, dummy)
{}
- /* The hash of a value_reference is its referent's identity,
- because we can have multiple value_reference objects that
- wind up pointing to the same entry. This method is virtual
- for the circular_reference case, below. */
+ /* The hash of a value_reference is its referent's local hash,
+ which only takes non-reference values into account. This
+ method is virtual for the circular_reference case, below. */
virtual size_t hash () const
{
- return ref->identity ();
+ return ref->local_hash ();
}
};
@@ -1179,9 +1190,10 @@ namespace elfutils
{
private:
const std::vector<entry *> *_m_entry;
+ const size_t _m_hash; // The local hash of the reference die (entry).
inline circular_reference (const circular_reference &)
- : value::value_reference ()
+ : value::value_reference (), _m_hash (0)
{
throw std::logic_error ("cannot copy-construct");
}
@@ -1189,7 +1201,8 @@ namespace elfutils
public:
inline circular_reference (const entry *die, copier *)
: value::value_reference (),
- _m_entry (new std::vector<entry *> (1, const_cast<entry *> (die)))
+ _m_entry (new std::vector<entry *> (1, const_cast<entry *> (die))),
+ _m_hash (die->local_hash ())
{
die->dump () << " new circular_reference " << this << "\n";
}
@@ -1229,14 +1242,11 @@ namespace elfutils
}
/* We have a special case for a reference attribute that is part
- of a circular chain. That value always hashes as zero, so that
- each entry in a circular chain of references has the same hash
- value as any entry that it otherwise matches and that has any
- (eventually) circular reference as the corresponding
- attribute's value. */
+ of a circular chain. It gets calculated from the
+ pending_entry. */
virtual size_t hash () const
{
- return 0;
+ return _m_hash;
}
};
@@ -1449,6 +1459,20 @@ namespace elfutils
subr::for_each (_m_children, std::mem_fun (&entry::dump_entry));
self->dump (false, true) << " ends\n";
}
+
+ /* This should match the calculation of local_hash () of an
+ debug_info_die. If we already matched, just take the hash of
+ the matched die instead of recalculating. */
+ inline size_t local_hash () const
+ {
+ if (_m_matched != NULL)
+ return _m_matched->first.local_hash ();
+
+ size_t hash = _m_tag;
+ subr::hash_combine (hash, _m_attributes.size ());
+ subr::hash_combine (hash, _m_children.size ());
+ return hash;
+ }
};
// This keeps state in the pending_entry's _m_finalizing pointer while live.
@@ -1753,6 +1777,15 @@ namespace elfutils
assert (_m_pending != NULL);
return _m_parent->_m_pending->child (_m_self_idx);
}
+
+ /* The local hash of the debug_info_entry if we are already
+ final, otherwise calculate it from the pending_entry. */
+ inline size_t local_hash () const
+ {
+ if (_m_final)
+ return _m_final->first.local_hash ();
+ return _m_pending->local_hash ();
+ }
};
// This object lives while we are copying one particular input DIE.