diff options
author | Mark Wielaard <mjw@redhat.com> | 2011-01-20 15:28:59 +0100 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2011-03-16 15:05:27 +0100 |
commit | 4a5f27364dcd30d43c49ac7292e29cd7cf7530d8 (patch) | |
tree | 1f8c03bddd36907be1f4c599ed9ef4b4e1dacd59 | |
parent | 17a29217e9145989ca15479132f8d6d8f80f0258 (diff) | |
download | elfutils-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_output | 59 |
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. |