This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: some notes on dwarf_output::copier


> The copier is instantiated when a dwarf_output object is instantiated
> and it creates the compile_units, which will call copier::make_unit ()
> through the cu_maker for each cu. make_unit () will create a
> copier::unit_copier for each cu using the
> compile_units_type::const_iterator, and then calls final_unit () on it,
> which just does a sanity check on the result, making sure there are no
> undefined entries left, and returns the final die_info_pair.

Correct.  I think this spot is where the main control flow of the second
walk will be done.

> An entry_copier lives as long as the copier is transforming the
> input_die. It holds the copier, the copier::entry input die, and a
> copier::pending_entry output which gets created in the constructor from
> the input die tag. The constructor set the input copier::entry
> _m_building field to the entry_copier to indicate it is being
> constructed. The destructor clears it again. It doesn't hold the actual
> input_die as state, all methods take an input_die as argument.

Correct.  The main reason for this kind of object is that running its
destructor is the unwind-protect mechanism.  That is, the destructor gets
run even when an exception is thrown during the copying.  It's also
possible to replace use of a temporary object that has a destructor with
just using 'try { ... } finally { ... }' clauses.  Feel free to do that
when it seems simpler.

We also take advantage of the fact that we have this temporary object to
use a pointer to it as the circularity detection mechanism (_m_building).

> entry_copier::populate (as called from the unit_copier constructor)
> takes an input_die, sets the _m_pending field of the input entry to the
> output pending_entry of the entry_copier. It will populate the
> _m_attributes if the _m_out entry from the given input_die and call
> add_child() for each child of the given input_die. After that it will
> clear the _m_out field to indicate the we are done with the
> pending_entry. And call entry::defined_self () on the _m_in entry.

Right.  defined_self triggers the final steps of state changes based on the
reference counts.  All that will be changing and hopefully become far
simpler in the new plan.

> When the _m_attributes set of the entry is populated the value maker
> will call back into the entry_copier::add_reference() for each reference
> value. add_reference() will setup the copier to enter the input_die to
> which the attribute is pointing and provide a "backptr" to the
> entry::refer() method that fill it in with either the finalized entry
> itself (if it is finalized) or to the entry itself and pushes the
> backptr to the _m_pending_refs of pending_entry.

Correct.

> entry_copier::add_child will setup the copier to start copying the given
> child die and create a new copier::entry for it, add the child to the
> _m_out pending_entry. If the child is already know, but not yet final
> (because it comes from an DW_TAG_imported_unit in a logical walk) it
> will update the _m_parent and create a new entry_copier and populate
> that.

Right.  That entry_copier is a temporary that lives only inside that
add_child frame, during the recursion into entry_copier::populate.

> entry_copier::final_unit() as called from make_unit() will do sanity
> checks to make sure the _m_in entry has really been finalized and return
> the die_info_pair stored in the collector.

Right.  It may make sense to remove this method and change the details of
the unit_copier class and what methods it has, or perhaps final_unit can
stay as the place where all the finalization happens.  Whatever works.

> A copier::entry holds the following state: _m_offset, the Dwarff_Off of
> the original die, _m_cost, the cost of the original die,

Right.  _m_offset serves the original_offset method, and is only kept to
use in the debugging output and the collector's stats output.  Nothing
about the actual workings uses it.  Likewise _m_cost is the "cost", meaning
bytes occupied by the encoding, and is just for the statistics output where
we can show how much we saved by reducing duplicates.  I have some thought
that eventually this cost calculation could be used in the output routines
to decide when it's worthwhile to generate a shared partial_unit vs just
copying very small DIEs in the output.


Thanks,
Roland

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]