Convert dwarf2_per_objfile::die_type_hash to new hash table

Convert dwarf2_per_objfile::die_type_hash, which maps debug info
offsets to `type *`, to gdb::unordered_map.

Change-Id: I5c174af64ee46d38a465008090e812acf03704ec
This commit is contained in:
Simon Marchi 2024-08-22 14:01:58 -04:00
parent 18784a7fe2
commit ee8f65ec48
2 changed files with 43 additions and 80 deletions

View File

@ -21653,52 +21653,6 @@ dwarf2_per_objfile::~dwarf2_per_objfile ()
remove_all_cus ();
}
/* A set of CU "per_cu" pointer, DIE offset, and GDB type pointer.
We store these in a hash table separate from the DIEs, and preserve them
when the DIEs are flushed out of cache.
The CU "per_cu" pointer is needed because offset alone is not enough to
uniquely identify the type. A file may have multiple .debug_types sections,
or the type may come from a DWO file. Furthermore, while it's more logical
to use per_cu->section+offset, with Fission the section with the data is in
the DWO file but we don't know that section at the point we need it.
We have to use something in dwarf2_per_cu_data (or the pointer to it)
because we can enter the lookup routine, get_die_type_at_offset, from
outside this file, and thus won't necessarily have PER_CU->cu.
Fortunately, PER_CU is stable for the life of the objfile. */
struct dwarf2_per_cu_offset_and_type
{
const struct dwarf2_per_cu_data *per_cu;
sect_offset sect_off;
struct type *type;
};
/* Hash function for a dwarf2_per_cu_offset_and_type. */
static hashval_t
per_cu_offset_and_type_hash (const void *item)
{
const struct dwarf2_per_cu_offset_and_type *ofs
= (const struct dwarf2_per_cu_offset_and_type *) item;
return (uintptr_t) ofs->per_cu + to_underlying (ofs->sect_off);
}
/* Equality function for a dwarf2_per_cu_offset_and_type. */
static int
per_cu_offset_and_type_eq (const void *item_lhs, const void *item_rhs)
{
const struct dwarf2_per_cu_offset_and_type *ofs_lhs
= (const struct dwarf2_per_cu_offset_and_type *) item_lhs;
const struct dwarf2_per_cu_offset_and_type *ofs_rhs
= (const struct dwarf2_per_cu_offset_and_type *) item_rhs;
return (ofs_lhs->per_cu == ofs_rhs->per_cu
&& ofs_lhs->sect_off == ofs_rhs->sect_off);
}
/* Set the type associated with DIE to TYPE. Save it in CU's hash
table if necessary. For convenience, return TYPE.
@ -21722,8 +21676,6 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
bool skip_data_location)
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
struct dwarf2_per_cu_offset_and_type **slot, ofs;
struct objfile *objfile = per_objfile->objfile;
struct attribute *attr;
struct dynamic_prop prop;
@ -21779,24 +21731,13 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
type->add_dyn_prop (DYN_PROP_DATA_LOCATION, prop);
}
if (per_objfile->die_type_hash == NULL)
per_objfile->die_type_hash
= htab_up (htab_create_alloc (127,
per_cu_offset_and_type_hash,
per_cu_offset_and_type_eq,
NULL, xcalloc, xfree));
ofs.per_cu = cu->per_cu;
ofs.sect_off = die->sect_off;
ofs.type = type;
slot = (struct dwarf2_per_cu_offset_and_type **)
htab_find_slot (per_objfile->die_type_hash.get (), &ofs, INSERT);
if (*slot)
bool inserted
= per_objfile->die_type_hash.emplace
(per_cu_and_offset {cu->per_cu, die->sect_off}, type).second;
if (!inserted)
complaint (_("A problem internal to GDB: DIE %s has type already set"),
sect_offset_str (die->sect_off));
*slot = XOBNEW (&objfile->objfile_obstack,
struct dwarf2_per_cu_offset_and_type);
**slot = ofs;
return type;
}
@ -21808,19 +21749,9 @@ get_die_type_at_offset (sect_offset sect_off,
dwarf2_per_cu_data *per_cu,
dwarf2_per_objfile *per_objfile)
{
struct dwarf2_per_cu_offset_and_type *slot, ofs;
auto it = per_objfile->die_type_hash.find ({per_cu, sect_off});
if (per_objfile->die_type_hash == NULL)
return NULL;
ofs.per_cu = per_cu;
ofs.sect_off = sect_off;
slot = ((struct dwarf2_per_cu_offset_and_type *)
htab_find (per_objfile->die_type_hash.get (), &ofs));
if (slot)
return slot->type;
else
return NULL;
return it != per_objfile->die_type_hash.end () ? it->second : nullptr;
}
/* Look up the type for DIE in CU in die_type_hash,

View File

@ -627,6 +627,26 @@ struct type_unit_group_unshareable
struct symtab **symtabs = nullptr;
};
struct per_cu_and_offset
{
dwarf2_per_cu_data *per_cu;
sect_offset offset;
bool operator== (const per_cu_and_offset &other) const noexcept
{
return this->per_cu == other.per_cu && this->offset == other.offset;
}
};
struct per_cu_and_offset_hash
{
std::uint64_t operator() (const per_cu_and_offset &key) const noexcept
{
return (std::hash<dwarf2_per_cu_data *> () (key.per_cu)
+ std::hash<sect_offset> () (key.offset));
}
};
/* Collection of data recorded per objfile.
This hangs off of dwarf2_objfile_data_key.
@ -701,10 +721,22 @@ struct dwarf2_per_objfile
other objfiles backed by the same BFD. */
struct dwarf2_per_bfd *per_bfd;
/* Table mapping type DIEs to their struct type *.
This is nullptr if not allocated yet.
The mapping is done via (CU/TU + DIE offset) -> type. */
htab_up die_type_hash;
/* A mapping of (CU "per_cu" pointer, DIE offset) to GDB type pointer.
We store these in a hash table separate from the DIEs, and preserve them
when the DIEs are flushed out of cache.
The CU "per_cu" pointer is needed because offset alone is not enough to
uniquely identify the type. A file may have multiple .debug_types sections,
or the type may come from a DWO file. Furthermore, while it's more logical
to use per_cu->section+offset, with Fission the section with the data is in
the DWO file but we don't know that section at the point we need it.
We have to use something in dwarf2_per_cu_data (or the pointer to it)
because we can enter the lookup routine, get_die_type_at_offset, from
outside this file, and thus won't necessarily have PER_CU->cu.
Fortunately, PER_CU is stable for the life of the objfile. */
gdb::unordered_map<per_cu_and_offset, type *, per_cu_and_offset_hash>
die_type_hash;
/* Table containing line_header indexed by offset and offset_in_dwz. */
htab_up line_header_hash;