dwarf_output::copier::entry is the main struct describing each input DIE encountered. These live as long as the copier lives, and thus are the "permanent" record about each input DIE. These are created via copier::enter from either copier::add_child or copier::add_reference. Thus, an entry will exist for an input DIE not yet encountered in the copying walk, if another DIE's attributes contained a reference to it.
All entry objects live in the copier::_m_entries map, which is a hash table keyed by the <impl>::debug_info_entry::identity () value, which is actually a globally-unique pointer. For <impl>=dwarf, this is actually the Dwarf_Die::addr value, i.e. the pointer to the file data mapped in memory. For the other implementations, it's the address of the debug_info_entry object itself. Once a new DIE has been finalized, entry::_m_final points to its instance in the collector. Before that, entry::_m_pending might point to a pending_entry. If both of those are NULL, then this is an entry that has only been encountered in a reference attribute, and no other members are set except for _m_offset (used in the debugging output). dwarf_output::copier::pending_entry describes an input DIE currently being copied, but not yet made final. This first exists while the copier is copying that entry on the initial copying walk. It lives until the entry can be finalized, when it is freed and replaced by setting _m_final. It's somewhat important to do this as early as we can manage, because duplicative identical input DIEs each have their own entry, and thus their own pending_entry before they're final. The pending_entry's members are where the most memory is consumed in the copier. The quicker we can finalize entries, the less memory we consume during the copying of the whole tree. In the current code, a pending_entry lives until the hairy bookkeeping figures out that it can do the finalization. In the new plan's first cut, each pending_entry will live until the whole first copying walk is done. (The exception being that if the input uses DW_TAG_imported_unit, then any shared duplicate entries will have been finalized in the copying of the first CU containing them, and thereafter another CU's copying walk will encounter an entry that already has its _m_final set.) In the new plan's second walk, each entry will be finalized so its pending_entry can be freed. Because of the aforementioned memory consumption, we will want to do early finalization during the first copying walk whenever possible. That is, do the "second walk" work for any subtree that has no references to other entries that are not yet final. Is that all clear? I'm not sure it's entirely necessary wrap one's head around all the hairy bookkeeping of the current plan. The new plan is replacing it with something easier to understand anyway. There will still be some hairy magic for cases of circular references. An entry can't be truly final until all its references are final, and thus that's a circular requirement. That's why we need the "placed" stage, where a value_reference already in the collector gets reified with the actual iterator into its referent's parent's children vector. Thanks, Roland _______________________________________________ elfutils-devel mailing list [email protected] https://fedorahosted.org/mailman/listinfo/elfutils-devel
