aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorSimon Marchi <simon.marchi@efficios.com>2025-03-17 23:16:24 -0400
committerSimon Marchi <simon.marchi@efficios.com>2025-03-18 15:45:09 -0400
commitd87251a45bceebbc90eed3161adb8ce75e35f959 (patch)
tree68c0b13c1e76f79a8233767ccf0ad4fb045e6ef2 /gdb
parent545c11e607baeae49d61546ba317c2c460a9c3e7 (diff)
downloadbinutils-d87251a45bceebbc90eed3161adb8ce75e35f959.zip
binutils-d87251a45bceebbc90eed3161adb8ce75e35f959.tar.gz
binutils-d87251a45bceebbc90eed3161adb8ce75e35f959.tar.bz2
gdb/dwarf: use gdb::unordered_map for dwarf2_per_bfd::{quick_file_names_table,type_unit_groups}
Change these two hash tables to use gdb::unordered_map. I changed these two at the same time because they both use the same key, a stmt_list_hash. Unlike other previous patches that used a gdb::unordered_set, use an unordered_map here because the key isn't found in the element itself (well, it was before, because of how htab works, but it didn't need to be). You'll notice that the type_unit_group structure is empty. That structure isn't really needed. It is removed in the following patch. Regression tested on Debian 12 amd64 with a bunch of DWARF target boards. Change-Id: Iec2289958d0f755cab8198f5b72ecab48358ba11 Approved-By: Tom Tromey <tom@tromey.com>
Diffstat (limited to 'gdb')
-rw-r--r--gdb/dwarf2/read-debug-names.c5
-rw-r--r--gdb/dwarf2/read-gdb-index.c2
-rw-r--r--gdb/dwarf2/read.c189
-rw-r--r--gdb/dwarf2/read.h21
4 files changed, 60 insertions, 157 deletions
diff --git a/gdb/dwarf2/read-debug-names.c b/gdb/dwarf2/read-debug-names.c
index 8c265dd..edac713 100644
--- a/gdb/dwarf2/read-debug-names.c
+++ b/gdb/dwarf2/read-debug-names.c
@@ -424,13 +424,12 @@ cooked_index_worker_debug_names::do_reading ()
exceptions.push_back (std::move (exc));
}
- dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd;
- per_bfd->quick_file_names_table
- = create_quick_file_names_table (per_bfd->all_units.size ());
m_results.emplace_back (nullptr,
complaint_handler.release (),
std::move (exceptions),
parent_map ());
+
+ dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd;
cooked_index *table
= (gdb::checked_static_cast<cooked_index *>
(per_bfd->index_table.get ()));
diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c
index f6c73d0..3439163 100644
--- a/gdb/dwarf2/read-gdb-index.c
+++ b/gdb/dwarf2/read-gdb-index.c
@@ -1558,8 +1558,6 @@ dwarf2_read_gdb_index
set_main_name_from_gdb_index (per_objfile, map.get ());
per_bfd->index_table = std::move (map);
- per_bfd->quick_file_names_table =
- create_quick_file_names_table (per_bfd->all_units.size ());
return true;
}
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 5075839..68bba49 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -270,6 +270,8 @@ struct loclists_rnglists_header
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;
@@ -284,12 +286,8 @@ struct stmt_list_hash
struct type_unit_group
{
- /* The data used to construct the hash key. */
- struct stmt_list_hash hash {};
};
-using type_unit_group_up = std::unique_ptr<type_unit_group>;
-
/* These sections are what may appear in a (real or virtual) DWO file. */
struct dwo_sections
@@ -1535,9 +1533,6 @@ dwarf2_per_bfd::start_reading (dwarf_scanner_base_up new_table)
line_header when we're done and don't need to record it here. */
struct quick_file_names
{
- /* The data used to construct the hash key. */
- struct stmt_list_hash hash;
-
/* The number of entries in file_names, real_names. */
unsigned int num_file_names;
@@ -1579,64 +1574,34 @@ struct readnow_functions : public dwarf2_base_index_functions
}
};
-/* Utility hash function for a stmt_list_hash. */
-
-static hashval_t
-hash_stmt_list_entry (const struct stmt_list_hash *stmt_list_hash)
-{
- hashval_t v = 0;
-
- if (stmt_list_hash->dwo_unit != NULL)
- v += (uintptr_t) stmt_list_hash->dwo_unit->dwo_file;
- v += to_underlying (stmt_list_hash->line_sect_off);
- return v;
-}
-
-/* Utility equality function for a stmt_list_hash. */
+/* See read.h. */
-static int
-eq_stmt_list_entry (const struct stmt_list_hash *lhs,
- const struct stmt_list_hash *rhs)
+std::uint64_t
+stmt_list_hash_hash::operator() (const stmt_list_hash &key) const noexcept
{
- if ((lhs->dwo_unit != NULL) != (rhs->dwo_unit != NULL))
- return 0;
- if (lhs->dwo_unit != NULL
- && lhs->dwo_unit->dwo_file != rhs->dwo_unit->dwo_file)
- return 0;
-
- return lhs->line_sect_off == rhs->line_sect_off;
-}
+ std::uint64_t v = 0;
-/* Hash function for a quick_file_names. */
+ if (key.dwo_unit != nullptr)
+ v += ankerl::unordered_dense::hash<dwo_file *> () (key.dwo_unit->dwo_file);
-static hashval_t
-hash_file_name_entry (const void *e)
-{
- const struct quick_file_names *file_data
- = (const struct quick_file_names *) e;
-
- return hash_stmt_list_entry (&file_data->hash);
+ v += (ankerl::unordered_dense::hash<std::uint64_t> ()
+ (to_underlying (key.line_sect_off)));
+ return v;
}
-/* Equality function for a quick_file_names. */
+/* See read.h. */
-static int
-eq_file_name_entry (const void *a, const void *b)
+bool
+stmt_list_hash::operator== (const stmt_list_hash &rhs) const noexcept
{
- const struct quick_file_names *ea = (const struct quick_file_names *) a;
- const struct quick_file_names *eb = (const struct quick_file_names *) b;
-
- return eq_stmt_list_entry (&ea->hash, &eb->hash);
-}
+ if ((this->dwo_unit != nullptr) != (rhs.dwo_unit != nullptr))
+ return false;
-/* See read.h. */
+ if (this->dwo_unit != nullptr
+ && this->dwo_unit->dwo_file != rhs.dwo_unit->dwo_file)
+ return false;
-htab_up
-create_quick_file_names_table (unsigned int nr_initial_entries)
-{
- return htab_up (htab_create_alloc (nr_initial_entries,
- hash_file_name_entry, eq_file_name_entry,
- nullptr, xcalloc, xfree));
+ return this->line_sect_off == rhs.line_sect_off;
}
/* Read in CU (dwarf2_cu object) for PER_CU in the context of PER_OBJFILE. This
@@ -1759,9 +1724,7 @@ dw2_get_file_names_reader (dwarf2_cu *cu, die_info *comp_unit_die)
{
dwarf2_per_cu *this_cu = cu->per_cu;
dwarf2_per_objfile *per_objfile = cu->per_objfile;
- struct attribute *attr;
- void **slot;
- struct quick_file_names *qfn;
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
gdb_assert (! this_cu->is_debug_types);
@@ -1771,29 +1734,24 @@ dw2_get_file_names_reader (dwarf2_cu *cu, die_info *comp_unit_die)
if (comp_unit_die->tag == DW_TAG_partial_unit)
return;
- slot = NULL;
-
line_header_up lh;
- sect_offset line_offset {};
file_and_directory &fnd = find_file_and_directory (comp_unit_die, cu);
+ std::optional<stmt_list_hash> stmt_list_hash_key;
+ attribute *attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, cu);
- attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, cu);
if (attr != nullptr && attr->form_is_unsigned ())
{
- struct quick_file_names find_entry;
-
- line_offset = (sect_offset) attr->as_unsigned ();
+ sect_offset line_offset = (sect_offset) attr->as_unsigned ();
/* We may have already read in this line header (TU line header sharing).
If we have we're done. */
- find_entry.hash.dwo_unit = cu->dwo_unit;
- find_entry.hash.line_sect_off = line_offset;
- slot = htab_find_slot (per_objfile->per_bfd->quick_file_names_table.get (),
- &find_entry, INSERT);
- if (*slot != NULL)
+ stmt_list_hash_key = {cu->dwo_unit, line_offset};
+
+ if (auto it = per_bfd->quick_file_names_table.find (*stmt_list_hash_key);
+ it != per_bfd->quick_file_names_table.end ())
{
- this_cu->file_names = (struct quick_file_names *) *slot;
+ this_cu->file_names = it->second;
return;
}
@@ -1806,12 +1764,11 @@ dw2_get_file_names_reader (dwarf2_cu *cu, die_info *comp_unit_die)
else if (lh == nullptr)
return;
- qfn = XOBNEW (&per_objfile->per_bfd->obstack, struct quick_file_names);
- qfn->hash.dwo_unit = cu->dwo_unit;
- qfn->hash.line_sect_off = line_offset;
+ auto *qfn = XOBNEW (&per_bfd->obstack, quick_file_names);
+
/* There may not be a DW_AT_stmt_list. */
- if (slot != nullptr)
- *slot = qfn;
+ if (stmt_list_hash_key.has_value ())
+ per_bfd->quick_file_names_table.emplace (*stmt_list_hash_key, qfn);
std::vector<const char *> include_names;
if (lh != nullptr)
@@ -1831,9 +1788,8 @@ dw2_get_file_names_reader (dwarf2_cu *cu, die_info *comp_unit_die)
qfn->num_file_names = offset + include_names.size ();
qfn->comp_dir = fnd.intern_comp_dir (per_objfile->objfile);
- qfn->file_names =
- XOBNEWVEC (&per_objfile->per_bfd->obstack, const char *,
- qfn->num_file_names);
+ qfn->file_names
+ = XOBNEWVEC (&per_bfd->obstack, const char *, qfn->num_file_names);
if (offset != 0)
qfn->file_names[0] = per_objfile->objfile->intern (fnd.get_name ());
@@ -2348,9 +2304,6 @@ dwarf2_initialize_objfile (struct objfile *objfile,
dwarf_read_debug_printf ("readnow requested");
create_all_units (per_objfile);
- per_bfd->quick_file_names_table
- = create_quick_file_names_table (per_bfd->all_units.size ());
-
objfile->qf.emplace_front (new readnow_functions);
}
/* Was a GDB index already read when we processed an objfile sharing
@@ -3320,56 +3273,12 @@ cutu_reader::cutu_reader (dwarf2_per_cu *this_cu,
together. A future step could be to put the types in the same symtab as
the CU the types ultimately came from. */
-static hashval_t
-hash_type_unit_group (const void *item)
-{
- const struct type_unit_group *tu_group
- = (const struct type_unit_group *) item;
-
- return hash_stmt_list_entry (&tu_group->hash);
-}
-
-static int
-eq_type_unit_group (const void *item_lhs, const void *item_rhs)
-{
- const struct type_unit_group *lhs = (const struct type_unit_group *) item_lhs;
- const struct type_unit_group *rhs = (const struct type_unit_group *) item_rhs;
-
- return eq_stmt_list_entry (&lhs->hash, &rhs->hash);
-}
-
-/* Allocate a hash table for type unit groups. */
-
-static htab_up
-allocate_type_unit_groups_table ()
-{
- return htab_up (htab_create_alloc (3,
- hash_type_unit_group,
- eq_type_unit_group,
- htab_delete_entry<type_unit_group>,
- xcalloc, xfree));
-}
-
/* Type units that don't have DW_AT_stmt_list are grouped into their own
partial symtabs. We combine several TUs per psymtab to not let the size
of any one psymtab grow too big. */
#define NO_STMT_LIST_TYPE_UNIT_PSYMTAB (1 << 31)
#define NO_STMT_LIST_TYPE_UNIT_PSYMTAB_SIZE 10
-/* Helper routine for get_type_unit_group.
- Create the type_unit_group object used to hold one or more TUs. */
-
-static type_unit_group_up
-create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
-{
- auto tu_group = std::make_unique<type_unit_group> ();
-
- tu_group->hash.dwo_unit = cu->dwo_unit;
- tu_group->hash.line_sect_off = line_offset_struct;
-
- return tu_group;
-}
-
/* Look up the type_unit_group for type unit CU, and create it if necessary.
STMT_LIST is a DW_AT_stmt_list attribute. */
@@ -3377,14 +3286,9 @@ static struct type_unit_group *
get_type_unit_group (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;
- struct type_unit_group *tu_group;
- void **slot;
unsigned int line_offset;
- struct type_unit_group type_unit_group_for_lookup;
-
- if (per_objfile->per_bfd->type_unit_groups == NULL)
- per_objfile->per_bfd->type_unit_groups = allocate_type_unit_groups_table ();
/* Do we need to create a new group, or can we use an existing one? */
@@ -3406,21 +3310,16 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
++tu_stats->nr_stmt_less_type_units;
}
- type_unit_group_for_lookup.hash.dwo_unit = cu->dwo_unit;
- type_unit_group_for_lookup.hash.line_sect_off = (sect_offset) line_offset;
- slot = htab_find_slot (per_objfile->per_bfd->type_unit_groups.get (),
- &type_unit_group_for_lookup, INSERT);
- if (*slot == nullptr)
+ 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)
{
- sect_offset line_offset_struct = (sect_offset) line_offset;
- auto grp = create_type_unit_group (cu, line_offset_struct);
- *slot = grp.release ();
+ (*it).second = std::make_unique<type_unit_group> ();
++tu_stats->nr_symtabs;
}
- tu_group = (struct type_unit_group *) *slot;
- gdb_assert (tu_group != nullptr);
- return tu_group;
+ return it->second.get ();
}
/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
@@ -3526,7 +3425,7 @@ build_type_psymtabs (dwarf2_per_objfile *per_objfile,
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 == NULL);
+ gdb_assert (per_objfile->per_bfd->type_unit_groups.empty ());
if (per_objfile->per_bfd->all_type_units.size () == 0)
return;
@@ -3781,8 +3680,6 @@ cooked_index_worker_debug_info::do_reading ()
create_all_units (m_per_objfile);
build_type_psymtabs (m_per_objfile, &m_index_storage);
- per_bfd->quick_file_names_table
- = create_quick_file_names_table (per_bfd->all_units.size ());
if (!per_bfd->debug_aranges.empty ())
read_addrmap_from_aranges (m_per_objfile, &per_bfd->debug_aranges,
m_index_storage.get_addrmap (),
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index 164c313..44fd7e9 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -467,6 +467,17 @@ 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.
@@ -605,7 +616,8 @@ public:
/* Table of struct type_unit_group objects.
The hash key is the DW_AT_stmt_list value. */
- htab_up type_unit_groups;
+ 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;
@@ -644,7 +656,8 @@ public:
sorted all the TUs into "type unit groups", grouped by their
DW_AT_stmt_list value. Therefore the only sharing done here is with a
CU and its associated TU group if there is one. */
- htab_up quick_file_names_table;
+ gdb::unordered_map<stmt_list_hash, quick_file_names *, stmt_list_hash_hash>
+ quick_file_names_table;
/* The CUs we recently read. */
std::vector<dwarf2_per_cu *> just_read_cus;
@@ -1194,10 +1207,6 @@ extern void finalize_all_units (dwarf2_per_bfd *per_bfd);
extern void create_all_units (dwarf2_per_objfile *per_objfile);
-/* Create a quick_file_names hash table. */
-
-extern htab_up create_quick_file_names_table (unsigned int nr_initial_entries);
-
/* Find the base address of the compilation unit for range lists and
location lists. It will normally be specified by DW_AT_low_pc.
In DWARF-3 draft 4, the base address could be overridden by