gdb/dwarf: remove type_unit_group

The type_unit_group is an indirection between a stmt_list_hash (possible
dwo_unit + line table section offset) and a type_unit_group_unshareable
that provides no real value.  In dwarf2_per_objfile, we maintain a
stmt_list_hash -> type_unit_group mapping, and in dwarf2_per_objfile, we
maintain a type_unit_group_unshareable mapping.  The type_unit_group
type is empty and only exists to have an identity and to be a link
between the two mappings.

This patch changes it so that we have a single stmt_list_hash ->
type_unit_group_unshareable mapping.

Regression tested on Debian 12 amd64 with a bunch of DWARF target
boards.

Change-Id: I9c5778ecb18963f353e9dd058e0f8152f7d8930c
Approved-By: Tom Tromey <tom@tromey.com>
This commit is contained in:
Simon Marchi 2025-03-17 23:16:25 -04:00
parent d87251a45b
commit c08c2adbb0
2 changed files with 46 additions and 79 deletions

View File

@ -265,29 +265,6 @@ struct loclists_rnglists_header
unsigned int offset_entry_count;
};
/* A struct that can be used as a hash key for tables based on DW_AT_stmt_list.
This includes type_unit_group and quick_file_names. */
struct stmt_list_hash
{
bool operator== (const stmt_list_hash &other) const noexcept;
/* The DWO unit this table is from or NULL if there is none. */
struct dwo_unit *dwo_unit;
/* Offset in .debug_line or .debug_line.dwo. */
sect_offset line_sect_off;
};
/* Each element of dwarf2_per_bfd->type_unit_groups is a pointer to
an object of this type. This contains elements of type unit groups
that can be shared across objfiles. The non-shareable parts are in
type_unit_group_unshareable. */
struct type_unit_group
{
};
/* These sections are what may appear in a (real or virtual) DWO file. */
struct dwo_sections
@ -2552,7 +2529,7 @@ fill_in_sig_entry_from_dwo_entry (dwarf2_per_objfile *per_objfile,
gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0
|| (to_underlying (sig_entry->type_offset_in_section)
== to_underlying (dwo_entry->type_offset_in_tu)));
gdb_assert (sig_entry->type_unit_group == NULL);
gdb_assert (!sig_entry->type_unit_group_key.has_value ());
gdb_assert (sig_entry->dwo_unit == NULL
|| sig_entry->dwo_unit == dwo_entry);
@ -3279,14 +3256,13 @@ cutu_reader::cutu_reader (dwarf2_per_cu *this_cu,
#define NO_STMT_LIST_TYPE_UNIT_PSYMTAB (1 << 31)
#define NO_STMT_LIST_TYPE_UNIT_PSYMTAB_SIZE 10
/* Look up the type_unit_group for type unit CU, and create it if necessary.
STMT_LIST is a DW_AT_stmt_list attribute. */
/* Get the type unit group key for type unit CU. STMT_LIST is a DW_AT_stmt_list
attribute. */
static struct type_unit_group *
get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
static stmt_list_hash
get_type_unit_group_key (struct dwarf2_cu *cu, const struct attribute *stmt_list)
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
unsigned int line_offset;
@ -3310,16 +3286,7 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
++tu_stats->nr_stmt_less_type_units;
}
stmt_list_hash key {cu->dwo_unit, static_cast<sect_offset> (line_offset)};
auto [it, inserted] = per_bfd->type_unit_groups.emplace (key, nullptr);
if (inserted)
{
(*it).second = std::make_unique<type_unit_group> ();
++tu_stats->nr_symtabs;
}
return it->second.get ();
return {cu->dwo_unit, static_cast<sect_offset> (line_offset)};
}
/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
@ -3424,9 +3391,6 @@ build_type_psymtabs (dwarf2_per_objfile *per_objfile,
abbrev_table_up abbrev_table;
sect_offset abbrev_offset;
/* It's up to the caller to not call us multiple times. */
gdb_assert (per_objfile->per_bfd->type_unit_groups.empty ());
if (per_objfile->per_bfd->all_type_units.size () == 0)
return;
@ -4753,16 +4717,15 @@ rust_union_quirks (struct dwarf2_cu *cu)
/* See read.h. */
type_unit_group_unshareable *
dwarf2_per_objfile::get_type_unit_group_unshareable (type_unit_group *tu_group)
dwarf2_per_objfile::get_type_unit_group_unshareable
(stmt_list_hash tu_group_key)
{
auto iter = m_type_units.find (tu_group);
if (iter != m_type_units.end ())
return iter->second.get ();
auto [it, inserted] = m_type_units.emplace (tu_group_key, nullptr);
type_unit_group_unshareable_up uniq (new type_unit_group_unshareable);
type_unit_group_unshareable *result = uniq.get ();
m_type_units[tu_group] = std::move (uniq);
return result;
if (inserted)
it->second = std::make_unique<type_unit_group_unshareable> ();
return it->second.get ();
}
struct type *
@ -5034,7 +4997,7 @@ process_full_type_unit (dwarf2_cu *cu)
of it with end_expandable_symtab. Otherwise, complete the addition of
this TU's symbols to the existing symtab. */
type_unit_group_unshareable *tug_unshare =
per_objfile->get_type_unit_group_unshareable (sig_type->type_unit_group);
per_objfile->get_type_unit_group_unshareable (*sig_type->type_unit_group_key);
if (tug_unshare->compunit_symtab == NULL)
{
buildsym_compunit *builder = cu->get_builder ();
@ -6222,7 +6185,6 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
void
dwarf2_cu::setup_type_unit_groups (struct die_info *die)
{
struct type_unit_group *tu_group;
int first_time;
struct attribute *attr;
unsigned int i;
@ -6235,16 +6197,15 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
/* If we're using .gdb_index (includes -readnow) then
per_cu->type_unit_group may not have been set up yet. */
if (sig_type->type_unit_group == NULL)
sig_type->type_unit_group = get_type_unit_group (this, attr);
tu_group = sig_type->type_unit_group;
if (!sig_type->type_unit_group_key.has_value ())
sig_type->type_unit_group_key = get_type_unit_group_key (this, attr);
/* If we've already processed this stmt_list there's no real need to
do it again, we could fake it and just recreate the part we need
(file name,index -> symtab mapping). If data shows this optimization
is useful we can do it then. */
type_unit_group_unshareable *tug_unshare
= per_objfile->get_type_unit_group_unshareable (tu_group);
= per_objfile->get_type_unit_group_unshareable (*sig_type->type_unit_group_key);
first_time = tug_unshare->compunit_symtab == NULL;
/* We have to handle the case of both a missing DW_AT_stmt_list or bad

View File

@ -55,7 +55,6 @@ struct dwarf2_per_cu;
struct mapped_index;
struct mapped_debug_names;
struct signatured_type;
struct type_unit_group;
/* One item on the queue of compilation units to read in full symbols
for. */
@ -74,6 +73,27 @@ struct dwarf2_queue_item
dwarf2_per_objfile *per_objfile;
};
/* A struct that can be used as a hash key for tables based on DW_AT_stmt_list.
This includes type_unit_group and quick_file_names. */
struct stmt_list_hash
{
bool operator== (const stmt_list_hash &other) const noexcept;
/* The DWO unit this table is from or NULL if there is none. */
struct dwo_unit *dwo_unit;
/* Offset in .debug_line or .debug_line.dwo. */
sect_offset line_sect_off;
};
struct stmt_list_hash_hash
{
using is_avalanching = void;
std::uint64_t operator() (const stmt_list_hash &key) const noexcept;
};
/* A deleter for dwarf2_per_cu that knows to downcast to signatured_type as
appropriate. This approach lets us avoid a virtual destructor, which saves
a bit of space. */
@ -376,8 +396,9 @@ struct signatured_type : public dwarf2_per_cu
sect_offset type_offset_in_section {};
/* Type units are grouped by their DW_AT_stmt_list entry so that they
can share them. This points to the containing symtab. */
struct type_unit_group *type_unit_group = nullptr;
can share them. This is the key of the group this type unit is part
of. */
std::optional<stmt_list_hash> type_unit_group_key;
/* Containing DWO unit.
This field is valid iff per_cu.reading_dwo_directly. */
@ -467,17 +488,6 @@ struct dwp_file;
using dwp_file_up = std::unique_ptr<dwp_file>;
struct stmt_list_hash;
struct stmt_list_hash_hash
{
using is_avalanching = void;
std::uint64_t operator() (const stmt_list_hash &key) const noexcept;
};
using type_unit_group_up = std::unique_ptr<type_unit_group>;
/* Some DWARF data can be shared across objfiles who share the same BFD,
this data is stored in this object.
@ -614,11 +624,6 @@ public:
std::vector<dwarf2_per_cu *> all_comp_units_index_cus;
std::vector<dwarf2_per_cu *> all_comp_units_index_tus;
/* Table of struct type_unit_group objects.
The hash key is the DW_AT_stmt_list value. */
gdb::unordered_map<stmt_list_hash, type_unit_group_up, stmt_list_hash_hash>
type_unit_groups;
/* Set of signatured_types, used to look up by signature. */
signatured_type_set signatured_types;
@ -828,10 +833,10 @@ struct dwarf2_per_objfile
/* Set the compunit_symtab associated to PER_CU. */
void set_symtab (const dwarf2_per_cu *per_cu, compunit_symtab *symtab);
/* Get the type_unit_group_unshareable corresponding to TU_GROUP. If one
/* Get the type_unit_group_unshareable corresponding to TU_GROUP_KEY. If one
does not exist, create it. */
type_unit_group_unshareable *get_type_unit_group_unshareable
(type_unit_group *tu_group);
(stmt_list_hash tu_group_key);
struct type *get_type_for_signatured_type (signatured_type *sig_type) const;
@ -898,9 +903,10 @@ private:
expanded yet. */
std::vector<compunit_symtab *> m_symtabs;
/* Map from a type unit group to the corresponding unshared
/* Map from a type unit group key to the corresponding unshared
structure. */
gdb::unordered_map<type_unit_group *, type_unit_group_unshareable_up>
gdb::unordered_map<stmt_list_hash, type_unit_group_unshareable_up,
stmt_list_hash_hash>
m_type_units;
/* Map from signatured types to the corresponding struct type. */