Compare commits

...

22 Commits

Author SHA1 Message Date
Simon Marchi
ee8f65ec48 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
2024-08-23 14:41:49 -04:00
Simon Marchi
18784a7fe2 Convert dwarf2_cu::call_site_htab to new hash table
Convert one use of htab_t, mapping (unrelocated) pc to call_site
objects, to `gdb::unordered_map<unrelocated_addr, call_site *>`.

Change-Id: I40a0903253a8589dbdcb75d52ad4d233931f6641
2024-08-23 14:37:55 -04:00
Simon Marchi
6a501c2c93 Convert dwarf_cu::die_hash to new hash table
Convert one use of htab_t, mapping offsets to die_info object, to
`gdb::unordered_map<sect_offset, die_info *>`.

Change-Id: Ic80df22bda551e2d4c2511d167e057f4d6cd2b3e
2024-08-23 14:37:55 -04:00
Simon Marchi
fd85b25156 Convert gdb_bfd.c to new hash table
This converts the BFD cache in gdb_bfd.c to use the new hash table.

Change-Id: Ib6257fe9d4f7f8ef793a2c82d53935a8d2c245a3
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
340e6b6185 Convert more DWARF code to new hash table
This converts more code in the DWARF reader to use the new hash table.

Change-Id: I86f8c0072f0a09642de3d6f033fefd0c8acbc4a3
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
c26bf42ae4 Convert all_bfds to new hash table
This converts gdb_bfd.c to use the new hash table for all_bfds.

This patch slightly changes the htab_t pretty-printer test, which was
relying on all_bfds.  Note that with the new hash table, gdb-specific
printers aren't needed; the libstdc++ printers suffice -- in fact,
they are better, because the true types of the contents are available.

Change-Id: I48b7bd142085287b34bdef8b6db5587581f94280
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
134a3c34a5 Convert typedef hash to new hash table
This converts the typedef hash to use the new hash table.

This patch found a latent bug in the typedef code.  Previously, the
hash function looked at the type name, but the hash equality function
used types_equal -- but that strips typedefs, meaning that equality of
types did not imply equality of hashes.  This patch fixes the problem
and updates the relevant test.

Change-Id: I0d10236b01e74bac79621244a1c0c56f90d65594
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
c2dfac7b84 Convert abbrevs to new hash table
This converts the DWARF abbrevs themselves to use the new hash table.

Change-Id: I0320a733ecefe2cffeb25c068f17322dd3ab23e2
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
5dafb0e289 Convert abbrev cache to new hash table
This converts the DWARF abbrev cache to use the new hash table.

Change-Id: I5e88cd4030715954db2c43f873b77b6b8e73f5aa
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
379d644f7a Convert gnu-v3-abi.c to new hash table
This converts gnu-v3-abi.c to use the new hash table.

This change shows how a std::vector can easily be made directly from
the hash table, simplifying the earlier approach of constructing a
vector and a hash table at the same time.

Change-Id: Ia0c387a035a52300db6b6f5a3a2e5c69efa01155
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
05b4831efd Convert static links to new hash table
This converts the objfile static link table to the new hash map.

Change-Id: If978e895679899ca2af4ef01c12842b4184d88e6
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
4c81a25468 Convert type copying to new hash table
This converts the type copying code to use the new hash map.

Change-Id: I35f0a4946dcc5c5eb84820126cf716b600f3302f
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
d30767bbdc Convert compile/compile.c to new hash table
This converts compile/compile.c to use the new hash table.

Change-Id: I7df3b8d791ece731ae0d1d64cdc91a2e372f5d4f
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
7564aea624 Convert disasm.c to new hash table
This converts disasm.c to use the new hash table.

Change-Id: I2efbe7ecc2964ec49e0b726ad4674e8eafc929f7
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
de8c68c641 Convert py-framefilter.c to new hash table
This converts py-framefilter.c to use the new hash table.

Change-Id: I38f4eaa8ebbcd4fd6e5e8ddc462502a92bf62f5e
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
7f6f1e7f00 Convert breakpoint.c to new hash table
This converts breakpoint.c to use the new hash table.

Change-Id: I6d997a6242969586a7f8f9eb22cc8dd8d3ac97ff
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
c4f180d72d Convert dwarf2/macro.c to new hash table
This converts dwarf2/macro.c to use the new hash table.

Change-Id: I6af0d1178e2db330fe3a89d57763974145ed17c4
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
a0b54aa74d Convert target-descriptions.c to new hash table
This converts target-descriptions.c to use the new hash table.

Change-Id: I03dfc6053c9856c5578548afcfdf58abf8b7ec2c
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
f2f3218633 Convert linespec.c to new hash table
This converts linespec.c to use the new hash table.

Note that more simplification could perhaps be done.  Currently, the
collectors in this code insert an element into a set and then, if the
element has not been seen before, append it to a vector.  If we know
the order does not matter, or if the results can be sorted later, we
could dispense with the vector.  This would simplify the code some
more.  (This technique is used in the vtable patch, later in this
series.)

Change-Id: Ie6828b1520d918d189ab5140dc8094a609152cf2
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
8af6d2db6c Convert filename-seen-cache.h to new hash table
This converts filename-seen-cache.h to use the new hash table.
filename-seen-cache.c is removed.

Change-Id: Iffac1d5e49d1610049b7deeef6e98d49e644366a
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
449c4c6900 Convert compile-c-symbols.c to new hash table
This converts compile-c-symbols.c to use the new hash table.

I made it use a set of string_view instead of a set of `symbol *`, to
avoid calling `symbol::natural_name` over and over.  This appears safe
to do, since I don't expect the storage behing the natural names to
change during the lifetime of the map.

Change-Id: Ie9f9334d4f03b9a8ae6886287f82cd435eee217c
Co-Authored-By: Tom Tromey <tom@tromey.com>
2024-08-23 14:37:54 -04:00
Simon Marchi
1d4b607f0e gdbsupport: add unordered_dense.h 4.4.0
Add a copy of unordered_dense.h from [1].  This file implements an
efficient hash map and hash set with a nice C++ interface (a near
drop-in for std::unordered_map and std::unordered_set).  This is
expected to be used to replace uses of `htab_t`, for improved code
readability and type safety.  Performance-wise, it is preferred to the
std types (std::unordered_map and std::unordered_set) due to it using
open addressing vs closed addressing for the std types.

I chose this particular implementation because it is simple to use, it's
a standalone header and it typically performs well in benchmarks I have
seen (e.g. [2]).  The license being MIT, my understanding is that it's
not a problem to use it and re-distribute it.

Add two additional files, gdbsupport/unordered_map.h and
gdbsupport/unordered_set.h, which make the map and set offered by
gdbsupport/unordered_dense.h available as gdb::unordered_map and
gdb::unordered_set.

[1] https://github.com/martinus/unordered_dense
[2] https://jacksonallan.github.io/c_cpp_hash_tables_benchmark/#conclusion-which-hash-table-to-choose

Change-Id: I0c7469ccf9a14540465479e58b2a5140a2440a7d
2024-08-23 14:37:54 -04:00
51 changed files with 2623 additions and 1210 deletions

View File

@@ -1121,7 +1121,6 @@ COMMON_SFILES = \
f-lang.c \
f-typeprint.c \
f-valprint.c \
filename-seen-cache.c \
filesystem.c \
findcmd.c \
findvar.c \

View File

@@ -21,7 +21,7 @@
#include <ctype.h>
#include "event-top.h"
#include "exceptions.h"
#include "hashtab.h"
#include "gdbsupport/unordered_set.h"
#include "symtab.h"
#include "frame.h"
#include "breakpoint.h"
@@ -12749,25 +12749,20 @@ all_locations_are_pending (struct breakpoint *b, struct program_space *pspace)
static bool
ambiguous_names_p (const bp_location_range &locs)
{
htab_up htab (htab_create_alloc (13, htab_hash_string, htab_eq_string, NULL,
xcalloc, xfree));
gdb::unordered_set<std::string_view> htab;
for (const bp_location &l : locs)
{
const char **slot;
const char *name = l.function_name.get ();
/* Allow for some names to be NULL, ignore them. */
if (name == NULL)
continue;
slot = (const char **) htab_find_slot (htab.get (), (const void *) name,
INSERT);
/* NOTE: We can assume slot != NULL here because xcalloc never
returns NULL. */
if (*slot != NULL)
bool inserted = htab.insert (name).second;
if (!inserted)
return true;
*slot = name;
}
return false;

View File

@@ -30,7 +30,7 @@
#include "gdbtypes.h"
#include "dwarf2/loc.h"
#include "inferior.h"
#include "gdbsupport/unordered_set.h"
/* Compute the name of the pointer representing a local symbol's
address. */
@@ -441,46 +441,6 @@ gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context,
return result;
}
/* A hash function for symbol names. */
static hashval_t
hash_symname (const void *a)
{
const struct symbol *sym = (const struct symbol *) a;
return htab_hash_string (sym->natural_name ());
}
/* A comparison function for hash tables that just looks at symbol
names. */
static int
eq_symname (const void *a, const void *b)
{
const struct symbol *syma = (const struct symbol *) a;
const struct symbol *symb = (const struct symbol *) b;
return strcmp (syma->natural_name (), symb->natural_name ()) == 0;
}
/* If a symbol with the same name as SYM is already in HASHTAB, return
1. Otherwise, add SYM to HASHTAB and return 0. */
static int
symbol_seen (htab_t hashtab, struct symbol *sym)
{
void **slot;
slot = htab_find_slot (hashtab, sym, INSERT);
if (*slot != NULL)
return 1;
*slot = sym;
return 0;
}
/* Generate C code to compute the length of a VLA. */
static void
@@ -626,8 +586,7 @@ generate_c_for_variable_locations (compile_instance *compiler,
/* Ensure that a given name is only entered once. This reflects the
reality of shadowing. */
htab_up symhash (htab_create_alloc (1, hash_symname, eq_symname, NULL,
xcalloc, xfree));
gdb::unordered_set<std::string_view> symset;
while (1)
{
@@ -635,7 +594,9 @@ generate_c_for_variable_locations (compile_instance *compiler,
compute the location of each local variable. */
for (struct symbol *sym : block_iterator_range (block))
{
if (!symbol_seen (symhash.get (), sym))
bool inserted = symset.insert (sym->natural_name ()).second;
if (inserted)
generate_c_for_for_one_variable (compiler, stream, gdbarch,
registers_used, pc, sym);
}

View File

@@ -105,9 +105,9 @@ do_module_cleanup (void *arg, int registers_valid)
static type *
create_copied_type_recursive (objfile *objfile, type *func_type)
{
htab_up copied_types = create_copied_types_hash ();
func_type = copy_type_recursive (func_type, copied_types.get ());
return func_type;
copied_types_hash_t copied_types;
return copy_type_recursive (func_type, copied_types);
}
/* Perform inferior call of MODULE. This function may throw an error.

View File

@@ -60,112 +60,15 @@ static struct cmd_list_element *compile_command_list;
bool compile_debug;
/* Object of this type are stored in the compiler's symbol_err_map. */
struct symbol_error
{
/* The symbol. */
const struct symbol *sym;
/* The error message to emit. This is malloc'd and owned by the
hash table. */
char *message;
};
/* An object that maps a gdb type to a gcc type. */
struct type_map_instance
{
/* The gdb type. */
struct type *type;
/* The corresponding gcc type handle. */
gcc_type gcc_type_handle;
};
/* Hash a type_map_instance. */
static hashval_t
hash_type_map_instance (const void *p)
{
const struct type_map_instance *inst = (const struct type_map_instance *) p;
return htab_hash_pointer (inst->type);
}
/* Check two type_map_instance objects for equality. */
static int
eq_type_map_instance (const void *a, const void *b)
{
const struct type_map_instance *insta = (const struct type_map_instance *) a;
const struct type_map_instance *instb = (const struct type_map_instance *) b;
return insta->type == instb->type;
}
/* Hash function for struct symbol_error. */
static hashval_t
hash_symbol_error (const void *a)
{
const struct symbol_error *se = (const struct symbol_error *) a;
return htab_hash_pointer (se->sym);
}
/* Equality function for struct symbol_error. */
static int
eq_symbol_error (const void *a, const void *b)
{
const struct symbol_error *sea = (const struct symbol_error *) a;
const struct symbol_error *seb = (const struct symbol_error *) b;
return sea->sym == seb->sym;
}
/* Deletion function for struct symbol_error. */
static void
del_symbol_error (void *a)
{
struct symbol_error *se = (struct symbol_error *) a;
xfree (se->message);
xfree (se);
}
/* Constructor for compile_instance. */
compile_instance::compile_instance (struct gcc_base_context *gcc_fe,
const char *options)
: m_gcc_fe (gcc_fe), m_gcc_target_options (options),
m_type_map (htab_create_alloc (10, hash_type_map_instance,
eq_type_map_instance,
xfree, xcalloc, xfree)),
m_symbol_err_map (htab_create_alloc (10, hash_symbol_error,
eq_symbol_error, del_symbol_error,
xcalloc, xfree))
{
}
/* See compile-internal.h. */
bool
compile_instance::get_cached_type (struct type *type, gcc_type *ret) const
{
struct type_map_instance inst, *found;
inst.type = type;
found = (struct type_map_instance *) htab_find (m_type_map.get (), &inst);
if (found != NULL)
if (auto iter = m_type_map.find (type);
iter != m_type_map.end ())
{
*ret = found->gcc_type_handle;
*ret = iter->second;
return true;
}
@@ -177,25 +80,12 @@ compile_instance::get_cached_type (struct type *type, gcc_type *ret) const
void
compile_instance::insert_type (struct type *type, gcc_type gcc_type)
{
struct type_map_instance inst, *add;
void **slot;
auto [it, inserted] = m_type_map.emplace (type, gcc_type);
inst.type = type;
inst.gcc_type_handle = gcc_type;
slot = htab_find_slot (m_type_map.get (), &inst, INSERT);
add = (struct type_map_instance *) *slot;
/* The type might have already been inserted in order to handle
recursive types. */
if (add != NULL && add->gcc_type_handle != gcc_type)
if (!inserted && it->second != gcc_type)
error (_("Unexpected type id from GCC, check you use recent enough GCC."));
if (add == NULL)
{
add = XNEW (struct type_map_instance);
*add = inst;
*slot = add;
}
}
/* See compile-internal.h. */
@@ -204,19 +94,7 @@ void
compile_instance::insert_symbol_error (const struct symbol *sym,
const char *text)
{
struct symbol_error e;
void **slot;
e.sym = sym;
slot = htab_find_slot (m_symbol_err_map.get (), &e, INSERT);
if (*slot == NULL)
{
struct symbol_error *ep = XNEW (struct symbol_error);
ep->sym = sym;
ep->message = xstrdup (text);
*slot = ep;
}
m_symbol_err_map.emplace (sym, text);
}
/* See compile-internal.h. */
@@ -224,20 +102,12 @@ compile_instance::insert_symbol_error (const struct symbol *sym,
void
compile_instance::error_symbol_once (const struct symbol *sym)
{
struct symbol_error search;
struct symbol_error *err;
if (m_symbol_err_map == NULL)
return;
search.sym = sym;
err = (struct symbol_error *) htab_find (m_symbol_err_map.get (), &search);
if (err == NULL || err->message == NULL)
return;
gdb::unique_xmalloc_ptr<char> message (err->message);
err->message = NULL;
error (_("%s"), message.get ());
if (auto iter = m_symbol_err_map.find (sym);
iter != m_symbol_err_map.end () && !iter->second.empty ())
{
std::string message = std::move (iter->second);
error (_("%s"), message.c_str ());
}
}
/* Implement "show debug compile". */

View File

@@ -19,7 +19,7 @@
#define COMPILE_COMPILE_H
#include "gcc-c-interface.h"
#include "gdbsupport/gdb-hashtab.h"
#include "gdbsupport/unordered_map.h"
struct ui_file;
struct gdbarch;
@@ -61,7 +61,10 @@ enum compile_i_scope_types
class compile_instance
{
public:
compile_instance (struct gcc_base_context *gcc_fe, const char *options);
compile_instance (struct gcc_base_context *gcc_fe, const char *options)
: m_gcc_fe (gcc_fe),
m_gcc_target_options (options)
{}
virtual ~compile_instance ()
{
@@ -163,10 +166,10 @@ protected:
std::string m_gcc_target_options;
/* Map from gdb types to gcc types. */
htab_up m_type_map;
gdb::unordered_map<type *, gcc_type> m_type_map;
/* Map from gdb symbols to gcc error messages to emit. */
htab_up m_symbol_err_map;
gdb::unordered_map<const symbol *, std::string> m_symbol_err_map;
};
/* Public function that is called from compile_control case in the

View File

@@ -19,6 +19,7 @@
#include "arch-utils.h"
#include "event-top.h"
#include "gdbsupport/unordered_set.h"
#include "target.h"
#include "value.h"
#include "ui-out.h"
@@ -122,73 +123,25 @@ struct deprecated_dis_line_entry
struct dis_line_entry
{
dis_line_entry (struct symtab *symtab, int line) noexcept
: symtab (symtab),
line (line)
{}
bool operator== (const dis_line_entry &other) const noexcept
{ return this->symtab == other.symtab && this->line == other.line; }
struct symtab *symtab;
int line;
};
/* Hash function for dis_line_entry. */
static hashval_t
hash_dis_line_entry (const void *item)
struct dis_line_entry_hash
{
const struct dis_line_entry *dle = (const struct dis_line_entry *) item;
return htab_hash_pointer (dle->symtab) + dle->line;
}
/* Equal function for dis_line_entry. */
static int
eq_dis_line_entry (const void *item_lhs, const void *item_rhs)
{
const struct dis_line_entry *lhs = (const struct dis_line_entry *) item_lhs;
const struct dis_line_entry *rhs = (const struct dis_line_entry *) item_rhs;
return (lhs->symtab == rhs->symtab
&& lhs->line == rhs->line);
}
/* Create the table to manage lines for mixed source/disassembly. */
static htab_t
allocate_dis_line_table (void)
{
return htab_create_alloc (41,
hash_dis_line_entry, eq_dis_line_entry,
xfree, xcalloc, xfree);
}
/* Add a new dis_line_entry containing SYMTAB and LINE to TABLE. */
static void
add_dis_line_entry (htab_t table, struct symtab *symtab, int line)
{
void **slot;
struct dis_line_entry dle, *dlep;
dle.symtab = symtab;
dle.line = line;
slot = htab_find_slot (table, &dle, INSERT);
if (*slot == NULL)
{
dlep = XNEW (struct dis_line_entry);
dlep->symtab = symtab;
dlep->line = line;
*slot = dlep;
}
}
/* Return non-zero if SYMTAB, LINE are in TABLE. */
static int
line_has_code_p (htab_t table, struct symtab *symtab, int line)
{
struct dis_line_entry dle;
dle.symtab = symtab;
dle.line = line;
return htab_find (table, &dle) != NULL;
}
uint64_t operator() (const dis_line_entry &x) const noexcept
{ return std::hash<symtab *> () (x.symtab) + std::hash<int> () (x.line); }
};
/* Wrapper of target_read_code. */
@@ -747,7 +700,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch,
but if that text is for code that will be disassembled later, then
we'll want to defer printing it until later with its associated code. */
htab_up dis_line_table (allocate_dis_line_table ());
gdb::unordered_set<dis_line_entry, dis_line_entry_hash> dis_line_table;
struct objfile *objfile = main_symtab->compunit ()->objfile ();
@@ -786,7 +739,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch,
pc += length;
if (sal.symtab != NULL)
add_dis_line_entry (dis_line_table.get (), sal.symtab, sal.line);
dis_line_table.emplace (sal.symtab, sal.line);
}
/* Second pass: print the disassembly.
@@ -859,11 +812,9 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch,
/* Several preceding source lines. Print the trailing ones
not associated with code that we'll print later. */
for (l = sal.line - 1; l > last_line; --l)
{
if (line_has_code_p (dis_line_table.get (),
sal.symtab, l))
break;
}
if (dis_line_table.contains ({sal.symtab, l}))
break;
if (l < sal.line - 1)
{
start_preceding_line_to_display = l + 1;

View File

@@ -20,33 +20,6 @@
#include "dwarf2/read.h"
#include "dwarf2/abbrev-cache.h"
/* Hash function for an abbrev table. */
hashval_t
abbrev_cache::hash_table (const void *item)
{
const struct abbrev_table *table = (const struct abbrev_table *) item;
return to_underlying (table->sect_off);
}
/* Comparison function for abbrev table. */
int
abbrev_cache::eq_table (const void *lhs, const void *rhs)
{
const struct abbrev_table *l_table = (const struct abbrev_table *) lhs;
const search_key *key = (const search_key *) rhs;
return (l_table->section == key->section
&& l_table->sect_off == key->offset);
}
abbrev_cache::abbrev_cache ()
: m_tables (htab_create_alloc (20, hash_table, eq_table,
htab_delete_entry<abbrev_table>,
xcalloc, xfree))
{
}
void
abbrev_cache::add (abbrev_table_up table)
{
@@ -54,11 +27,10 @@ abbrev_cache::add (abbrev_table_up table)
if (table == nullptr)
return;
search_key key = { table->section, table->sect_off };
void **slot = htab_find_slot_with_hash (m_tables.get (), &key,
to_underlying (table->sect_off),
INSERT);
bool inserted
= m_tables.emplace (key {table->section,
table->sect_off}, std::move (table)).second;
/* If this one already existed, then it should have been reused. */
gdb_assert (*slot == nullptr);
*slot = (void *) table.release ();
gdb_assert (inserted);
}

View File

@@ -21,12 +21,13 @@
#define GDB_DWARF2_ABBREV_CACHE_H
#include "dwarf2/abbrev.h"
#include "gdbsupport/unordered_map.h"
/* An abbrev cache holds abbrev tables for easier reuse. */
class abbrev_cache
{
public:
abbrev_cache ();
abbrev_cache () = default;
DISABLE_COPY_AND_ASSIGN (abbrev_cache);
/* Find an abbrev table coming from the abbrev section SECTION at
@@ -34,10 +35,11 @@ public:
been registered. */
abbrev_table *find (struct dwarf2_section_info *section, sect_offset offset)
{
search_key key = { section, offset };
if (auto iter = m_tables.find ({ section, offset });
iter != m_tables.end ())
return iter->second.get ();
return (abbrev_table *) htab_find_with_hash (m_tables.get (), &key,
to_underlying (offset));
return nullptr;
}
/* Add TABLE to this cache. Ownership of TABLE is transferred to
@@ -48,18 +50,29 @@ public:
void add (abbrev_table_up table);
private:
static hashval_t hash_table (const void *item);
static int eq_table (const void *lhs, const void *rhs);
struct search_key
struct key
{
struct dwarf2_section_info *section;
dwarf2_section_info *section;
sect_offset offset;
};
struct key_hash
{
std::size_t operator() (const key &k) const noexcept
{
return (std::hash<dwarf2_section_info *> () (k.section)
+ std::hash<std::uint64_t> () (to_underlying (k.offset)));
}
};
struct key_eq
{
bool operator() (const key &lhs, const key &rhs) const noexcept
{ return lhs.section == rhs.section && lhs.offset == rhs.offset; }
};
/* Hash table of abbrev tables. */
htab_up m_tables;
gdb::unordered_map<key, abbrev_table_up, key_hash, key_eq> m_tables;
};
#endif /* GDB_DWARF2_ABBREV_CACHE_H */

View File

@@ -29,52 +29,6 @@
#include "dwarf2/leb.h"
#include "bfd.h"
/* Hash function for an abbrev. */
static hashval_t
hash_abbrev (const void *item)
{
const struct abbrev_info *info = (const struct abbrev_info *) item;
/* Warning: if you change this next line, you must also update the
other code in this class using the _with_hash functions. */
return info->number;
}
/* Comparison function for abbrevs. */
static int
eq_abbrev (const void *lhs, const void *rhs)
{
const struct abbrev_info *l_info = (const struct abbrev_info *) lhs;
const struct abbrev_info *r_info = (const struct abbrev_info *) rhs;
return l_info->number == r_info->number;
}
/* Abbreviation tables.
In DWARF version 2, the description of the debugging information is
stored in a separate .debug_abbrev section. Before we read any
dies from a section we read in all abbreviations and install them
in a hash table. */
abbrev_table::abbrev_table (sect_offset off, struct dwarf2_section_info *sect)
: sect_off (off),
section (sect),
m_abbrevs (htab_create_alloc (20, hash_abbrev, eq_abbrev,
nullptr, xcalloc, xfree))
{
}
/* Add an abbreviation to the table. */
void
abbrev_table::add_abbrev (struct abbrev_info *abbrev)
{
void **slot = htab_find_slot_with_hash (m_abbrevs.get (), abbrev,
abbrev->number, INSERT);
*slot = abbrev;
}
/* Helper function that returns true if a DIE with the given tag might
plausibly be indexed. */

View File

@@ -27,7 +27,7 @@
#ifndef GDB_DWARF2_ABBREV_H
#define GDB_DWARF2_ABBREV_H
#include "hashtab.h"
#include "gdbsupport/unordered_map.h"
struct attr_abbrev
{
@@ -60,7 +60,12 @@ struct abbrev_info
struct abbrev_table;
typedef std::unique_ptr<struct abbrev_table> abbrev_table_up;
/* Top level data structure to contain an abbreviation table. */
/* Top level data structure to contain an abbreviation table.
In DWARF version 2, the description of the debugging information is
stored in a separate .debug_abbrev section. Before we read any
dies from a section we read in all abbreviations and install them
in a hash table. */
struct abbrev_table
{
@@ -76,12 +81,11 @@ struct abbrev_table
const struct abbrev_info *lookup_abbrev (unsigned int abbrev_number) const
{
struct abbrev_info search;
search.number = abbrev_number;
if (auto iter = m_abbrevs.find (abbrev_number);
iter != m_abbrevs.end ())
return iter->second;
return (struct abbrev_info *) htab_find_with_hash (m_abbrevs.get (),
&search,
abbrev_number);
return nullptr;
}
/* Where the abbrev table came from.
@@ -92,15 +96,20 @@ struct abbrev_table
private:
abbrev_table (sect_offset off, struct dwarf2_section_info *sect);
abbrev_table (sect_offset off, struct dwarf2_section_info *sect)
: sect_off (off),
section (sect)
{
}
DISABLE_COPY_AND_ASSIGN (abbrev_table);
/* Add an abbreviation to the table. */
void add_abbrev (struct abbrev_info *abbrev);
void add_abbrev (struct abbrev_info *abbrev)
{ m_abbrevs.emplace (abbrev->number, abbrev); }
/* Hash table of abbrevs. */
htab_up m_abbrevs;
gdb::unordered_map<int, abbrev_info *> m_abbrevs;
/* Storage for the abbrev table. */
auto_obstack m_abbrev_obstack;

View File

@@ -25,6 +25,7 @@
#include "dwarf2/types.h"
#include "../frame.h"
#include "gdbsupport/function-view.h"
#include "gdbsupport/unordered_map.h"
struct dwarf2_locexpr_baton;
struct dwarf2_per_cu_data;
@@ -241,4 +242,6 @@ public:
struct call_site_parameter parameter[];
};
using call_site_htab_t = gdb::unordered_map<unrelocated_addr, call_site *>;
#endif /* CALL_SITE_H */

View File

@@ -119,57 +119,33 @@ dwarf2_cu::addr_type () const
return addr_type;
}
/* A hashtab traversal function that marks the dependent CUs. */
static int
dwarf2_mark_helper (void **slot, void *data)
{
dwarf2_per_cu_data *per_cu = (dwarf2_per_cu_data *) *slot;
dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) data;
dwarf2_cu *cu = per_objfile->get_cu (per_cu);
/* cu->m_dependencies references may not yet have been ever read if
QUIT aborts reading of the chain. As such dependencies remain
valid it is not much useful to track and undo them during QUIT
cleanups. */
if (cu != nullptr)
cu->mark ();
return 1;
}
/* See dwarf2/cu.h. */
void
dwarf2_cu::mark ()
{
if (!m_mark)
if (m_mark)
return;
m_mark = true;
for (dwarf2_per_cu_data *per_cu : m_dependencies)
{
m_mark = true;
if (m_dependencies != nullptr)
htab_traverse_noresize (m_dependencies.get (), dwarf2_mark_helper,
per_objfile);
/* cu->m_dependencies references may not yet have been ever
read if QUIT aborts reading of the chain. As such
dependencies remain valid it is not much useful to track
and undo them during QUIT cleanups. */
dwarf2_cu *cu = per_objfile->get_cu (per_cu);
if (cu == nullptr)
continue;
cu->mark ();
}
}
/* See dwarf2/cu.h. */
void
dwarf2_cu::add_dependence (struct dwarf2_per_cu_data *ref_per_cu)
{
void **slot;
if (m_dependencies == nullptr)
m_dependencies.reset (htab_create_alloc
(5, htab_hash_pointer, htab_eq_pointer,
nullptr, xcalloc, xfree));
slot = htab_find_slot (m_dependencies.get (), ref_per_cu, INSERT);
if (*slot == nullptr)
*slot = ref_per_cu;
}
/* See dwarf2/cu.h. */
buildsym_compunit *
dwarf2_cu::get_builder ()
{

View File

@@ -24,6 +24,7 @@
#include "dwarf2/comp-unit-head.h"
#include <optional>
#include "language.h"
#include "gdbsupport/unordered_set.h"
/* Type used for delaying computation of method physnames.
See comments for compute_delayed_physnames. */
@@ -95,7 +96,8 @@ struct dwarf2_cu
}
/* Add a dependence relationship from this cu to REF_PER_CU. */
void add_dependence (struct dwarf2_per_cu_data *ref_per_cu);
void add_dependence (struct dwarf2_per_cu_data *ref_per_cu)
{ m_dependencies.emplace (ref_per_cu); }
/* The header of the compilation unit. */
struct comp_unit_head header;
@@ -120,9 +122,9 @@ private:
std::unique_ptr<buildsym_compunit> m_builder;
/* A set of pointers to dwarf2_per_cu_data objects for compilation
units referenced by this one. Only set during full symbol processing;
units referenced by this one. Only used during full symbol processing;
partial symbol tables do not have dependencies. */
htab_up m_dependencies;
gdb::unordered_set<dwarf2_per_cu_data *> m_dependencies;
public:
/* The generic symbol table building routines have separate lists for
@@ -151,7 +153,7 @@ public:
/* A hash table of DIE cu_offset for following references with
die_info->offset.sect_off as hash. */
htab_up die_hash;
gdb::unordered_map<sect_offset, die_info *> die_hash;
/* Full DIEs if read in. */
struct die_info *dies = nullptr;
@@ -170,7 +172,7 @@ public:
std::vector<delayed_method_info> method_list;
/* To be copied to symtab->call_site_htab. */
htab_up call_site_htab;
call_site_htab_t call_site_htab;
/* Non-NULL if this CU came from a DWO file.
There is an invariant here that is important to remember:

View File

@@ -35,27 +35,6 @@ die_info::allocate (struct obstack *obstack, int num_attrs)
return die;
}
/* See die.h. */
hashval_t
die_info::hash (const void *item)
{
const struct die_info *die = (const struct die_info *) item;
return to_underlying (die->sect_off);
}
/* See die.h. */
int
die_info::eq (const void *item_lhs, const void *item_rhs)
{
const struct die_info *die_lhs = (const struct die_info *) item_lhs;
const struct die_info *die_rhs = (const struct die_info *) item_rhs;
return die_lhs->sect_off == die_rhs->sect_off;
}
static void
dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
{

View File

@@ -31,14 +31,6 @@ struct die_info
attributes that are needed. */
static die_info *allocate (struct obstack *obstack, int num_attrs);
/* Trivial hash function for die_info: the hash value of a DIE is
its offset in .debug_info for this objfile. */
static hashval_t hash (const void *item);
/* Trivial comparison function for die_info structures: two DIEs
are equal if they have the same offset. */
static int eq (const void *item_lhs, const void *item_rhs);
/* Dump this DIE and any children to MAX_LEVEL. They are written to
gdb_stdlog. Note this is called from the pdie user command in
gdb-gdb.gdb. */

View File

@@ -422,7 +422,8 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile,
struct dwarf2_section_info *str_section,
struct dwarf2_section_info *str_offsets_section,
std::optional<ULONGEST> str_offsets_base,
htab_t include_hash, struct dwarf2_cu *cu)
gdb::unordered_set<const gdb_byte *> &include_hash,
struct dwarf2_cu *cu)
{
struct objfile *objfile = per_objfile->objfile;
enum dwarf_macro_record_type macinfo_type;
@@ -697,7 +698,6 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile,
case DW_MACRO_import_sup:
{
LONGEST offset;
void **slot;
bfd *include_bfd = abfd;
const struct dwarf2_section_info *include_section = section;
const gdb_byte *include_mac_end = mac_end;
@@ -719,9 +719,10 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile,
}
new_mac_ptr = include_section->buffer + offset;
slot = htab_find_slot (include_hash, new_mac_ptr, INSERT);
if (*slot != NULL)
bool inserted = include_hash.insert (new_mac_ptr).second;
if (!inserted)
{
/* This has actually happened; see
http://sourceware.org/bugzilla/show_bug.cgi?id=13568. */
@@ -730,8 +731,6 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile,
}
else
{
*slot = (void *) new_mac_ptr;
dwarf_decode_macro_bytes (per_objfile, builder, include_bfd,
new_mac_ptr, include_mac_end,
current_file, lh, section,
@@ -739,7 +738,7 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile,
str_section, str_offsets_section,
str_offsets_base, include_hash, cu);
htab_remove_elt (include_hash, (void *) new_mac_ptr);
include_hash.erase (new_mac_ptr);
}
}
break;
@@ -788,7 +787,6 @@ dwarf_decode_macros (dwarf2_per_objfile *per_objfile,
struct macro_source_file *current_file = 0;
enum dwarf_macro_record_type macinfo_type;
const gdb_byte *opcode_definitions[256];
void **slot;
abfd = section->get_bfd_owner ();
@@ -933,14 +931,11 @@ dwarf_decode_macros (dwarf2_per_objfile *per_objfile,
command-line macro definitions/undefinitions. This flag is unset when we
reach the first DW_MACINFO_start_file entry. */
htab_up include_hash (htab_create_alloc (1, htab_hash_pointer,
htab_eq_pointer,
NULL, xcalloc, xfree));
gdb::unordered_set<const gdb_byte *> include_hash;
mac_ptr = section->buffer + offset;
slot = htab_find_slot (include_hash.get (), mac_ptr, INSERT);
*slot = (void *) mac_ptr;
include_hash.insert (mac_ptr);
dwarf_decode_macro_bytes (per_objfile, builder, abfd, mac_ptr, mac_end,
current_file, lh, section, section_is_gnu, 0,
offset_size, str_section, str_offsets_section,
str_offsets_base, include_hash.get (), cu);
str_offsets_base, include_hash, cu);
}

View File

@@ -96,6 +96,7 @@
#include "gdbsupport/thread-pool.h"
#include "run-on-main-thread.h"
#include "dwarf2/parent-map.h"
#include "gdbsupport/unordered_dense.h"
/* When == 1, print basic high level tracing messages.
When > 1, be more verbose.
@@ -2876,12 +2877,8 @@ dw_expand_symtabs_matching_file_matcher
if (file_matcher == NULL)
return;
htab_up visited_found (htab_create_alloc (10, htab_hash_pointer,
htab_eq_pointer,
NULL, xcalloc, xfree));
htab_up visited_not_found (htab_create_alloc (10, htab_hash_pointer,
htab_eq_pointer,
NULL, xcalloc, xfree));
gdb::unordered_set<quick_file_names *> visited_found;
gdb::unordered_set<quick_file_names *> visited_not_found;
/* The rule is CUs specify all the files, including those used by
any TU, so there's no need to scan TUs here. */
@@ -2924,9 +2921,9 @@ dw_expand_symtabs_matching_file_matcher
if (file_data == NULL)
continue;
if (htab_find (visited_not_found.get (), file_data) != NULL)
if (visited_not_found.contains (file_data))
continue;
else if (htab_find (visited_found.get (), file_data) != NULL)
else if (visited_found.contains (file_data))
{
per_cu->mark = 1;
continue;
@@ -2957,11 +2954,10 @@ dw_expand_symtabs_matching_file_matcher
}
}
void **slot = htab_find_slot (per_cu->mark
? visited_found.get ()
: visited_not_found.get (),
file_data, INSERT);
*slot = file_data;
if (per_cu->mark)
visited_found.insert (file_data);
else
visited_not_found.insert (file_data);
}
}
@@ -5495,11 +5491,8 @@ load_full_comp_unit (dwarf2_per_cu_data *this_cu,
struct dwarf2_cu *cu = reader.cu;
const gdb_byte *info_ptr = reader.info_ptr;
gdb_assert (cu->die_hash == NULL);
cu->die_hash.reset (htab_create_alloc
(cu->header.get_length_without_initial () / 12,
die_info::hash, die_info::eq,
nullptr, xcalloc, xfree));
gdb_assert (cu->die_hash.empty ());
cu->die_hash.reserve (cu->header.get_length_without_initial () / 12);
if (reader.comp_unit_die->has_children)
reader.comp_unit_die->child
@@ -6036,21 +6029,21 @@ void dwarf2_per_objfile::set_type_for_signatured_type
included by PER_CU. */
static void
recursively_compute_inclusions (std::vector<compunit_symtab *> *result,
htab_t all_children, htab_t all_type_symtabs,
dwarf2_per_cu_data *per_cu,
dwarf2_per_objfile *per_objfile,
struct compunit_symtab *immediate_parent)
recursively_compute_inclusions
(std::vector<compunit_symtab *> *result,
gdb::unordered_set<dwarf2_per_cu_data *> &all_children,
gdb::unordered_set<compunit_symtab *> &all_type_symtabs,
dwarf2_per_cu_data *per_cu,
dwarf2_per_objfile *per_objfile,
struct compunit_symtab *immediate_parent)
{
void **slot = htab_find_slot (all_children, per_cu, INSERT);
if (*slot != NULL)
if (bool inserted = all_children.emplace (per_cu).second;
!inserted)
{
/* This inclusion and its children have been processed. */
return;
}
*slot = per_cu;
/* Only add a CU if it has a symbol table. */
compunit_symtab *cust = per_objfile->get_symtab (per_cu);
if (cust != NULL)
@@ -6059,10 +6052,9 @@ recursively_compute_inclusions (std::vector<compunit_symtab *> *result,
seen it yet (type unit per_cu's can share symtabs). */
if (per_cu->is_debug_types)
{
slot = htab_find_slot (all_type_symtabs, cust, INSERT);
if (*slot == NULL)
if (bool inserted = all_type_symtabs.insert (cust).second;
inserted)
{
*slot = cust;
result->push_back (cust);
if (cust->user == NULL)
cust->user = immediate_parent;
@@ -6101,16 +6093,12 @@ compute_compunit_symtab_includes (dwarf2_per_cu_data *per_cu,
if (cust == NULL)
return;
htab_up all_children (htab_create_alloc (1, htab_hash_pointer,
htab_eq_pointer,
NULL, xcalloc, xfree));
htab_up all_type_symtabs (htab_create_alloc (1, htab_hash_pointer,
htab_eq_pointer,
NULL, xcalloc, xfree));
gdb::unordered_set<dwarf2_per_cu_data *> all_children;
gdb::unordered_set<compunit_symtab *> all_type_symtabs;
for (dwarf2_per_cu_data *ptr : per_cu->imported_symtabs)
recursively_compute_inclusions (&result_symtabs, all_children.get (),
all_type_symtabs.get (), ptr,
recursively_compute_inclusions (&result_symtabs, all_children,
all_type_symtabs, ptr,
per_objfile, cust);
/* Now we have a transitive closure of all the included symtabs. */
@@ -10195,7 +10183,6 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
struct objfile *objfile = per_objfile->objfile;
struct gdbarch *gdbarch = objfile->arch ();
struct attribute *attr;
void **slot;
int nparams;
struct die_info *child_die;
@@ -10215,21 +10202,6 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
}
unrelocated_addr pc = attr->as_address ();
if (cu->call_site_htab == nullptr)
cu->call_site_htab.reset (htab_create_alloc (16, call_site::hash,
call_site::eq, nullptr,
xcalloc, xfree));
struct call_site call_site_local (pc, nullptr, nullptr);
slot = htab_find_slot (cu->call_site_htab.get (), &call_site_local, INSERT);
if (*slot != NULL)
{
complaint (_("Duplicate PC %s for DW_TAG_call_site "
"DIE %s [in module %s]"),
paddress (gdbarch, (CORE_ADDR) pc), sect_offset_str (die->sect_off),
objfile_name (objfile));
return;
}
/* Count parameters at the caller. */
nparams = 0;
@@ -10254,7 +10226,16 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
struct call_site,
sizeof (*call_site) + sizeof (call_site->parameter[0]) * nparams))
struct call_site (pc, cu->per_cu, per_objfile);
*slot = call_site;
bool inserted = cu->call_site_htab.emplace (pc, call_site).second;
if (!inserted)
{
complaint (_("Duplicate PC %s for DW_TAG_call_site "
"DIE %s [in module %s]"),
paddress (gdbarch, (CORE_ADDR) pc), sect_offset_str (die->sect_off),
objfile_name (objfile));
return;
}
/* We never call the destructor of call_site, so we must ensure it is
trivially destructible. */
@@ -15776,10 +15757,8 @@ read_die_and_children (const struct die_reader_specs *reader,
return NULL;
}
void **slot = htab_find_slot_with_hash (reader->cu->die_hash.get (), die,
to_underlying (die->sect_off),
INSERT);
*slot = die;
bool inserted = reader->cu->die_hash.emplace (die->sect_off, die).second;
gdb_assert (inserted);
if (die->has_children)
die->child = read_die_and_siblings_1 (reader, cur_ptr, new_info_ptr, die);
@@ -20274,7 +20253,6 @@ static struct die_info *
follow_die_offset (sect_offset sect_off, int offset_in_dwz,
struct dwarf2_cu **ref_cu)
{
struct die_info temp_die;
struct dwarf2_cu *target_cu, *cu = *ref_cu;
dwarf2_per_objfile *per_objfile = cu->per_objfile;
@@ -20330,11 +20308,9 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
}
*ref_cu = target_cu;
temp_die.sect_off = sect_off;
return (struct die_info *) htab_find_with_hash (target_cu->die_hash.get (),
&temp_die,
to_underlying (sect_off));
auto it = target_cu->die_hash.find (sect_off);
return it != target_cu->die_hash.end () ? it->second : nullptr;
}
/* Follow reference attribute ATTR of SRC_DIE.
@@ -20688,9 +20664,7 @@ static struct die_info *
follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
struct dwarf2_cu **ref_cu)
{
struct die_info temp_die;
struct dwarf2_cu *sig_cu;
struct die_info *die;
dwarf2_per_objfile *per_objfile = (*ref_cu)->per_objfile;
@@ -20711,11 +20685,9 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
sig_cu = per_objfile->get_cu (sig_type);
gdb_assert (sig_cu != NULL);
gdb_assert (to_underlying (sig_type->type_offset_in_section) != 0);
temp_die.sect_off = sig_type->type_offset_in_section;
die = (struct die_info *) htab_find_with_hash (sig_cu->die_hash.get (),
&temp_die,
to_underlying (temp_die.sect_off));
if (die)
auto die_it = sig_cu->die_hash.find (sig_type->type_offset_in_section);
if (die_it != sig_cu->die_hash.end ())
{
/* For .gdb_index version 7 keep track of included TUs.
http://sourceware.org/bugzilla/show_bug.cgi?id=15021. */
@@ -20724,7 +20696,7 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
(*ref_cu)->per_cu->imported_symtabs.push_back (sig_cu->per_cu);
*ref_cu = sig_cu;
return die;
return die_it->second;
}
return NULL;
@@ -20900,11 +20872,8 @@ read_signatured_type (signatured_type *sig_type,
struct dwarf2_cu *cu = reader.cu;
const gdb_byte *info_ptr = reader.info_ptr;
gdb_assert (cu->die_hash == NULL);
cu->die_hash.reset (htab_create_alloc
(cu->header.get_length_without_initial () / 12,
die_info::hash, die_info::eq,
nullptr, xcalloc, xfree));
gdb_assert (cu->die_hash.empty ());
cu->die_hash.reserve (cu->header.get_length_without_initial () / 12);
if (reader.comp_unit_die->has_children)
reader.comp_unit_die->child
@@ -21684,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.
@@ -21753,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;
@@ -21810,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;
}
@@ -21839,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;

View File

@@ -201,7 +201,8 @@ struct extension_language_ops
COPIED_TYPES is used to prevent cycles / duplicates and is passed to
preserve_one_value. */
void (*preserve_values) (const struct extension_language_defn *,
struct objfile *objfile, htab_t copied_types);
struct objfile *objfile,
copied_types_hash_t &copied_types);
/* Return non-zero if there is a stop condition for the breakpoint.
This is used to implement the restriction that a breakpoint may have

View File

@@ -584,7 +584,8 @@ apply_ext_lang_ptwrite_filter (btrace_thread_info *btinfo)
preserve_one_value. */
void
preserve_ext_lang_values (struct objfile *objfile, htab_t copied_types)
preserve_ext_lang_values (struct objfile *objfile,
copied_types_hash_t &copied_types)
{
for (const struct extension_language_defn *extlang : extension_languages)
{

View File

@@ -22,8 +22,8 @@
#include "mi/mi-cmds.h"
#include "gdbsupport/array-view.h"
#include "hashtab.h"
#include <optional>
#include "gdbtypes.h"
struct breakpoint;
struct command_line;
@@ -306,7 +306,8 @@ extern enum ext_lang_bt_status apply_ext_lang_frame_filter
extern void apply_ext_lang_ptwrite_filter
(struct btrace_thread_info *btinfo);
extern void preserve_ext_lang_values (struct objfile *, htab_t copied_types);
extern void preserve_ext_lang_values (struct objfile *,
copied_types_hash_t &copied_types);
extern const struct extension_language_defn *get_breakpoint_cond_ext_lang
(struct breakpoint *b, enum extension_language skip_lang);

View File

@@ -1,58 +0,0 @@
/* Filename-seen cache for the GNU debugger, GDB.
Copyright (C) 1986-2024 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "filename-seen-cache.h"
#include "filenames.h"
/* Initial size of the table. It automagically grows from here. */
#define INITIAL_FILENAME_SEEN_CACHE_SIZE 100
/* filename_seen_cache constructor. */
filename_seen_cache::filename_seen_cache ()
: m_tab (htab_create_alloc (INITIAL_FILENAME_SEEN_CACHE_SIZE,
filename_hash, filename_eq,
NULL, xcalloc, xfree))
{
}
/* See filename-seen-cache.h. */
void
filename_seen_cache::clear ()
{
htab_empty (m_tab.get ());
}
/* See filename-seen-cache.h. */
bool
filename_seen_cache::seen (const char *file)
{
void **slot;
/* Is FILE in tab? */
slot = htab_find_slot (m_tab.get (), file, INSERT);
if (*slot != NULL)
return true;
/* No; add it to tab. */
*slot = (char *) file;
return false;
}

View File

@@ -20,46 +20,45 @@
#ifndef FILENAME_SEEN_CACHE_H
#define FILENAME_SEEN_CACHE_H
#include "gdbsupport/function-view.h"
#include "gdbsupport/gdb-hashtab.h"
#include "gdbsupport/unordered_set.h"
#include "filenames.h"
/* Cache to watch for file names already seen. */
class filename_seen_cache
{
public:
filename_seen_cache ();
filename_seen_cache () = default;
DISABLE_COPY_AND_ASSIGN (filename_seen_cache);
/* Empty the cache, but do not delete it. */
void clear ();
/* Empty the cache. */
void clear ()
{ m_tab.clear (); }
/* If FILE is not already in the table of files in CACHE, add it and
/* If FILE is not already in the table of files of the cache, add it and
return false; otherwise return true.
NOTE: We don't manage space for FILE, we assume FILE lives as
long as the caller needs. */
bool seen (const char *file);
/* Traverse all cache entries, calling CALLBACK on each. The
filename is passed as argument to CALLBACK. */
void traverse (gdb::function_view<void (const char *filename)> callback)
{
auto erased_cb = [] (void **slot, void *info) -> int
{
auto filename = (const char *) *slot;
auto restored_cb = (decltype (callback) *) info;
(*restored_cb) (filename);
return 1;
};
htab_traverse_noresize (m_tab.get (), erased_cb, &callback);
}
bool seen (const char *file)
{ return !m_tab.insert (file).second; }
private:
struct hash
{
std::size_t operator() (const char *s) const noexcept
{ return filename_hash (s); }
};
struct eq
{
bool operator() (const char *lhs, const char *rhs) const noexcept
{ return filename_eq (lhs, rhs); }
};
/* Table of files seen so far. */
htab_up m_tab;
gdb::unordered_set<const char *, hash, eq> m_tab;
};
#endif /* FILENAME_SEEN_CACHE_H */

View File

@@ -34,6 +34,7 @@
#include "inferior.h"
#include "cli/cli-style.h"
#include <unordered_map>
#include "gdbsupport/unordered_set.h"
#if CXX_STD_THREAD
@@ -80,12 +81,12 @@ struct gdb_bfd_section_data
void *map_addr;
};
/* A hash table holding every BFD that gdb knows about. This is not
/* A hash set holding every BFD that gdb knows about. This is not
to be confused with 'gdb_bfd_cache', which is used for sharing
BFDs; in contrast, this hash is used just to implement
"maint info bfd". */
static htab_t all_bfds;
static gdb::unordered_set<bfd *> all_bfds;
/* An object of this type is stored in each BFD's user data. */
@@ -153,10 +154,6 @@ registry_accessor<bfd>::get (bfd *abfd)
return &gdata->registry_fields;
}
/* A hash table storing all the BFDs maintained in the cache. */
static htab_t gdb_bfd_cache;
/* When true gdb will reuse an existing bfd object if the filename,
modification time, and file size all match. */
@@ -202,34 +199,39 @@ struct gdb_bfd_cache_search
dev_t device_id;
};
/* A hash function for BFDs. */
static hashval_t
hash_bfd (const void *b)
struct bfd_cache_hash
{
const bfd *abfd = (const struct bfd *) b;
using is_transparent = void;
/* It is simplest to just hash the filename. */
return htab_hash_string (bfd_get_filename (abfd));
}
std::size_t operator() (bfd *abfd) const noexcept
{ return htab_hash_string (bfd_get_filename (abfd)); }
/* An equality function for BFDs. Note that this expects the caller
to search using struct gdb_bfd_cache_search only, not BFDs. */
std::size_t operator() (const gdb_bfd_cache_search &search) const noexcept
{ return htab_hash_string (search.filename); }
};
static int
eq_bfd (const void *a, const void *b)
struct bfd_cache_eq
{
const bfd *abfd = (const struct bfd *) a;
const struct gdb_bfd_cache_search *s
= (const struct gdb_bfd_cache_search *) b;
struct gdb_bfd_data *gdata = (struct gdb_bfd_data *) bfd_usrdata (abfd);
using is_transparent = void;
return (gdata->mtime == s->mtime
&& gdata->size == s->size
&& gdata->inode == s->inode
&& gdata->device_id == s->device_id
&& strcmp (bfd_get_filename (abfd), s->filename) == 0);
}
bool operator() (bfd *lhs, bfd *rhs) const noexcept
{ return lhs == rhs; }
bool operator() (const gdb_bfd_cache_search &s, bfd *abfd) const noexcept
{
auto gdata = static_cast<gdb_bfd_data *> (bfd_usrdata (abfd));
return (gdata->mtime == s.mtime
&& gdata->size == s.size
&& gdata->inode == s.inode
&& gdata->device_id == s.device_id
&& strcmp (bfd_get_filename (abfd), s.filename) == 0);
}
};
/* A hash set storing all the BFDs maintained in the cache. */
static gdb::unordered_set<bfd *, bfd_cache_hash, bfd_cache_eq> gdb_bfd_cache;
/* See gdb_bfd.h. */
@@ -482,7 +484,6 @@ static void
gdb_bfd_init_data (struct bfd *abfd, struct stat *st)
{
struct gdb_bfd_data *gdata;
void **slot;
gdb_assert (bfd_usrdata (abfd) == nullptr);
@@ -493,9 +494,8 @@ gdb_bfd_init_data (struct bfd *abfd, struct stat *st)
bfd_set_usrdata (abfd, gdata);
/* This is the first we've seen it, so add it to the hash table. */
slot = htab_find_slot (all_bfds, abfd, INSERT);
gdb_assert (slot && !*slot);
*slot = abfd;
bool inserted = all_bfds.emplace (abfd).second;
gdb_assert (inserted);
}
/* See gdb_bfd.h. */
@@ -504,8 +504,6 @@ gdb_bfd_ref_ptr
gdb_bfd_open (const char *name, const char *target, int fd,
bool warn_if_slow)
{
hashval_t hash;
void **slot;
bfd *abfd;
struct gdb_bfd_cache_search search;
struct stat st;
@@ -532,10 +530,6 @@ gdb_bfd_open (const char *name, const char *target, int fd,
std::lock_guard<std::recursive_mutex> guard (gdb_bfd_mutex);
#endif
if (gdb_bfd_cache == NULL)
gdb_bfd_cache = htab_create_alloc (1, hash_bfd, eq_bfd, NULL,
xcalloc, xfree);
if (fd == -1)
{
fd = gdb_open_cloexec (name, O_RDONLY | O_BINARY, 0).release ();
@@ -562,19 +556,18 @@ gdb_bfd_open (const char *name, const char *target, int fd,
search.inode = st.st_ino;
search.device_id = st.st_dev;
/* Note that this must compute the same result as hash_bfd. */
hash = htab_hash_string (name);
/* Note that we cannot use htab_find_slot_with_hash here, because
opening the BFD may fail; and this would violate hashtab
invariants. */
abfd = (struct bfd *) htab_find_with_hash (gdb_bfd_cache, &search, hash);
if (bfd_sharing && abfd != NULL)
if (bfd_sharing)
{
bfd_cache_debug_printf ("Reusing cached bfd %s for %s",
host_address_to_string (abfd),
bfd_get_filename (abfd));
close (fd);
return gdb_bfd_ref_ptr::new_reference (abfd);
if (auto iter = gdb_bfd_cache.find (search);
iter != gdb_bfd_cache.end ())
{
abfd = *iter;
bfd_cache_debug_printf ("Reusing cached bfd %s for %s",
host_address_to_string (abfd),
bfd_get_filename (abfd));
close (fd);
return gdb_bfd_ref_ptr::new_reference (abfd);
}
}
abfd = bfd_fopen (name, target, FOPEN_RB, fd);
@@ -589,9 +582,8 @@ gdb_bfd_open (const char *name, const char *target, int fd,
if (bfd_sharing)
{
slot = htab_find_slot_with_hash (gdb_bfd_cache, &search, hash, INSERT);
gdb_assert (!*slot);
*slot = abfd;
bool inserted = gdb_bfd_cache.emplace (abfd).second;
gdb_assert (inserted);
}
/* It's important to pass the already-computed stat info here,
@@ -686,7 +678,6 @@ void
gdb_bfd_unref (struct bfd *abfd)
{
struct gdb_bfd_data *gdata;
struct gdb_bfd_cache_search search;
bfd *archive_bfd;
if (abfd == NULL)
@@ -713,28 +704,14 @@ gdb_bfd_unref (struct bfd *abfd)
bfd_get_filename (abfd));
archive_bfd = gdata->archive_bfd;
search.filename = bfd_get_filename (abfd);
if (gdb_bfd_cache && search.filename)
{
hashval_t hash = htab_hash_string (search.filename);
void **slot;
search.mtime = gdata->mtime;
search.size = gdata->size;
search.inode = gdata->inode;
search.device_id = gdata->device_id;
slot = htab_find_slot_with_hash (gdb_bfd_cache, &search, hash,
NO_INSERT);
if (slot && *slot)
htab_clear_slot (gdb_bfd_cache, slot);
}
if (bfd_get_filename (abfd) != nullptr)
gdb_bfd_cache.erase (abfd);
delete gdata;
bfd_set_usrdata (abfd, NULL); /* Paranoia. */
htab_remove_elt (all_bfds, abfd);
all_bfds.erase (abfd);
gdb_bfd_close_or_warn (abfd);
@@ -1145,25 +1122,6 @@ gdb_bfd_errmsg (bfd_error_type error_tag, char **matching)
return ret;
}
/* A callback for htab_traverse that prints a single BFD. */
static int
print_one_bfd (void **slot, void *data)
{
bfd *abfd = (struct bfd *) *slot;
struct gdb_bfd_data *gdata = (struct gdb_bfd_data *) bfd_usrdata (abfd);
struct ui_out *uiout = (struct ui_out *) data;
ui_out_emit_tuple tuple_emitter (uiout, NULL);
uiout->field_signed ("refcount", gdata->refc);
uiout->field_string ("addr", host_address_to_string (abfd));
uiout->field_string ("filename", bfd_get_filename (abfd),
file_name_style.style ());
uiout->text ("\n");
return 1;
}
/* Implement the 'maint info bfd' command. */
static void
@@ -1177,7 +1135,17 @@ maintenance_info_bfds (const char *arg, int from_tty)
uiout->table_header (40, ui_left, "filename", "Filename");
uiout->table_body ();
htab_traverse_noresize (all_bfds, print_one_bfd, uiout);
for (auto abfd : all_bfds)
{
auto gdata = static_cast<gdb_bfd_data *> (bfd_usrdata (abfd));
ui_out_emit_tuple tuple_emitter (uiout, nullptr);
uiout->field_signed ("refcount", gdata->refc);
uiout->field_string ("addr", host_address_to_string (abfd));
uiout->field_string ("filename", bfd_get_filename (abfd),
file_name_style.style ());
uiout->text ("\n");
}
}
/* BFD related per-inferior data. */
@@ -1272,9 +1240,6 @@ void _initialize_gdb_bfd ();
void
_initialize_gdb_bfd ()
{
all_bfds = htab_create_alloc (10, htab_hash_pointer, htab_eq_pointer,
NULL, xcalloc, xfree);
add_cmd ("bfds", class_maintenance, maintenance_info_bfds, _("\
List the BFDs that are currently open."),
&maintenanceinfolist);

View File

@@ -5372,46 +5372,6 @@ recursive_dump_type (struct type *type, int spaces)
obstack_free (&dont_print_type_obstack, NULL);
}
/* Trivial helpers for the libiberty hash table, for mapping one
type to another. */
struct type_pair
{
type_pair (struct type *old_, struct type *newobj_)
: old (old_), newobj (newobj_)
{}
struct type * const old, * const newobj;
};
static hashval_t
type_pair_hash (const void *item)
{
const struct type_pair *pair = (const struct type_pair *) item;
return htab_hash_pointer (pair->old);
}
static int
type_pair_eq (const void *item_lhs, const void *item_rhs)
{
const struct type_pair *lhs = (const struct type_pair *) item_lhs;
const struct type_pair *rhs = (const struct type_pair *) item_rhs;
return lhs->old == rhs->old;
}
/* Allocate the hash table used by copy_type_recursive to walk
types without duplicates. */
htab_up
create_copied_types_hash ()
{
return htab_up (htab_create_alloc (1, type_pair_hash, type_pair_eq,
htab_delete_entry<type_pair>,
xcalloc, xfree));
}
/* Recursively copy (deep copy) a dynamic attribute list of a type. */
static struct dynamic_prop_list *
@@ -5443,27 +5403,20 @@ copy_dynamic_prop_list (struct obstack *storage,
it is not associated with OBJFILE. */
struct type *
copy_type_recursive (struct type *type, htab_t copied_types)
copy_type_recursive (struct type *type, copied_types_hash_t &copied_types)
{
void **slot;
struct type *new_type;
if (!type->is_objfile_owned ())
return type;
struct type_pair pair (type, nullptr);
if (auto iter = copied_types.find (type);
iter != copied_types.end ())
return iter->second;
slot = htab_find_slot (copied_types, &pair, INSERT);
if (*slot != NULL)
return ((struct type_pair *) *slot)->newobj;
new_type = type_allocator (type->arch ()).new_type ();
struct type *new_type = type_allocator (type->arch ()).new_type ();
/* We must add the new type to the hash table immediately, in case
we encounter this type again during a recursive call below. */
struct type_pair *stored = new type_pair (type, new_type);
*slot = stored;
copied_types.emplace (type, new_type);
/* Copy the common fields of types. For the main type, we simply
copy the entire thing and then update specific fields as needed. */

View File

@@ -44,7 +44,6 @@
written such that they can be used as both rvalues and lvalues.
*/
#include "hashtab.h"
#include "gdbsupport/array-view.h"
#include "gdbsupport/gdb-hashtab.h"
#include <optional>
@@ -56,6 +55,7 @@
#include "dwarf2.h"
#include "gdbsupport/gdb_obstack.h"
#include "gmp-utils.h"
#include "gdbsupport/unordered_map.h"
/* Forward declarations for prototypes. */
struct field;
@@ -2789,10 +2789,10 @@ extern int class_or_union_p (const struct type *);
extern void maintenance_print_type (const char *, int);
extern htab_up create_copied_types_hash ();
using copied_types_hash_t = gdb::unordered_map<type *, type *>;
extern struct type *copy_type_recursive (struct type *type,
htab_t copied_types);
copied_types_hash_t &copied_types);
extern struct type *copy_type (const struct type *type);

View File

@@ -33,6 +33,7 @@
#include "cli/cli-style.h"
#include "dwarf2/loc.h"
#include "inferior.h"
#include "gdbsupport/unordered_map.h"
static struct cp_abi_ops gnu_v3_abi_ops;
@@ -791,51 +792,32 @@ gnuv3_method_ptr_to_value (struct value **this_p, struct value *method_ptr)
return value_from_pointer (lookup_pointer_type (method_type), ptr_value);
}
/* Objects of this type are stored in a hash table and a vector when
printing the vtables for a class. */
struct value_and_voffset
struct vtable_value_hash_t
{
/* The value representing the object. */
struct value *value;
/* The maximum vtable offset we've found for any object at this
offset in the outermost object. */
int max_voffset;
std::size_t operator() (value *val) const noexcept
{ return val->address () + val->embedded_offset (); }
};
/* Hash function for value_and_voffset. */
static hashval_t
hash_value_and_voffset (const void *p)
struct vtable_value_eq_t
{
const struct value_and_voffset *o = (const struct value_and_voffset *) p;
bool operator() (value *lhs, value *rhs) const noexcept
{
return (lhs->address () + lhs->embedded_offset ()
== rhs->address () + rhs->embedded_offset ());
}
};
return o->value->address () + o->value->embedded_offset ();
}
using vtable_hash_t
= gdb::unordered_map<value *, int, vtable_value_hash_t, vtable_value_eq_t>;
/* Equality function for value_and_voffset. */
static int
eq_value_and_voffset (const void *a, const void *b)
{
const struct value_and_voffset *ova = (const struct value_and_voffset *) a;
const struct value_and_voffset *ovb = (const struct value_and_voffset *) b;
return (ova->value->address () + ova->value->embedded_offset ()
== ovb->value->address () + ovb->value->embedded_offset ());
}
/* Comparison function for value_and_voffset. */
/* Comparison function used for sorting the vtable entries. */
static bool
compare_value_and_voffset (const struct value_and_voffset *va,
const struct value_and_voffset *vb)
compare_value_and_voffset (const std::pair<value *, int> &va,
const std::pair<value *, int> &vb)
{
CORE_ADDR addra = (va->value->address ()
+ va->value->embedded_offset ());
CORE_ADDR addrb = (vb->value->address ()
+ vb->value->embedded_offset ());
CORE_ADDR addra = va.first->address () + va.first->embedded_offset ();
CORE_ADDR addrb = vb.first->address () + vb.first->embedded_offset ();
return addra < addrb;
}
@@ -843,18 +825,14 @@ compare_value_and_voffset (const struct value_and_voffset *va,
/* A helper function used when printing vtables. This determines the
key (most derived) sub-object at each address and also computes the
maximum vtable offset seen for the corresponding vtable. Updates
OFFSET_HASH and OFFSET_VEC with a new value_and_voffset object, if
needed. VALUE is the object to examine. */
OFFSET_HASH with a new value_and_voffset object, if needed. VALUE
is the object to examine. */
static void
compute_vtable_size (htab_t offset_hash,
std::vector<value_and_voffset *> *offset_vec,
struct value *value)
compute_vtable_size (vtable_hash_t &offset_hash, struct value *value)
{
int i;
struct type *type = check_typedef (value->type ());
void **slot;
struct value_and_voffset search_vo, *current_vo;
gdb_assert (type->code () == TYPE_CODE_STRUCT);
@@ -864,18 +842,7 @@ compute_vtable_size (htab_t offset_hash,
return;
/* Update the hash and the vec, if needed. */
search_vo.value = value;
slot = htab_find_slot (offset_hash, &search_vo, INSERT);
if (*slot)
current_vo = (struct value_and_voffset *) *slot;
else
{
current_vo = XNEW (struct value_and_voffset);
current_vo->value = value;
current_vo->max_voffset = -1;
*slot = current_vo;
offset_vec->push_back (current_vo);
}
int &current_max_voffset = offset_hash.emplace (value, -1).first->second;
/* Update the value_and_voffset object with the highest vtable
offset from this class. */
@@ -890,15 +857,15 @@ compute_vtable_size (htab_t offset_hash,
{
int voffset = TYPE_FN_FIELD_VOFFSET (fn, j);
if (voffset > current_vo->max_voffset)
current_vo->max_voffset = voffset;
if (voffset > current_max_voffset)
current_max_voffset = voffset;
}
}
}
/* Recurse into base classes. */
for (i = 0; i < TYPE_N_BASECLASSES (type); ++i)
compute_vtable_size (offset_hash, offset_vec, value_field (value, i));
compute_vtable_size (offset_hash, value_field (value, i));
}
/* Helper for gnuv3_print_vtable that prints a single vtable. */
@@ -999,23 +966,22 @@ gnuv3_print_vtable (struct value *value)
return;
}
htab_up offset_hash (htab_create_alloc (1, hash_value_and_voffset,
eq_value_and_voffset,
xfree, xcalloc, xfree));
std::vector<value_and_voffset *> result_vec;
vtable_hash_t offset_hash;
compute_vtable_size (offset_hash, value);
compute_vtable_size (offset_hash.get (), &result_vec, value);
std::vector<std::pair<struct value *, int>> result_vec (offset_hash.begin (),
offset_hash.end ());
std::sort (result_vec.begin (), result_vec.end (),
compare_value_and_voffset);
count = 0;
for (value_and_voffset *iter : result_vec)
for (auto &item : result_vec)
{
if (iter->max_voffset >= 0)
if (item.second >= 0)
{
if (count > 0)
gdb_printf ("\n");
print_one_vtable (gdbarch, iter->value, iter->max_voffset, &opts);
print_one_vtable (gdbarch, item.first, item.second, &opts);
++count;
}
}

View File

@@ -596,7 +596,7 @@ extern bool gdbscm_auto_load_enabled (const struct extension_language_defn *);
extern void gdbscm_preserve_values
(const struct extension_language_defn *,
struct objfile *, htab_t copied_types);
struct objfile *, copied_types_hash_t &copied_types);
extern enum ext_lang_rc gdbscm_apply_val_pretty_printer
(const struct extension_language_defn *,

View File

@@ -94,8 +94,8 @@ struct tyscm_deleter
return;
gdb_assert (htab != nullptr);
htab_up copied_types = create_copied_types_hash ();
htab_traverse_noresize (htab, tyscm_copy_type_recursive, copied_types.get ());
copied_types_hash_t copied_types;
htab_traverse_noresize (htab, tyscm_copy_type_recursive, &copied_types);
htab_delete (htab);
}
};
@@ -375,12 +375,11 @@ static int
tyscm_copy_type_recursive (void **slot, void *info)
{
type_smob *t_smob = (type_smob *) *slot;
htab_t copied_types = (htab_t) info;
copied_types_hash_t &copied_types = *static_cast<copied_types_hash_t *> (info);
htab_t htab;
eqable_gdb_smob **new_slot;
type_smob t_smob_for_lookup;
htab_empty (copied_types);
t_smob->type = copy_type_recursive (t_smob->type, copied_types);
/* The eq?-hashtab that the type lived in is going away.

View File

@@ -86,7 +86,8 @@ static SCM substitute_symbol;
void
gdbscm_preserve_values (const struct extension_language_defn *extlang,
struct objfile *objfile, htab_t copied_types)
struct objfile *objfile,
copied_types_hash_t &copied_types)
{
value_smob *iter;

View File

@@ -47,6 +47,7 @@
#include "gdbsupport/def-vector.h"
#include <algorithm>
#include "inferior.h"
#include "gdbsupport/unordered_set.h"
/* An enumeration of the various things a user might attempt to
complete for a linespec location. */
@@ -3363,12 +3364,9 @@ namespace {
class decode_compound_collector
{
public:
decode_compound_collector ()
: m_unique_syms (htab_create_alloc (1, htab_hash_pointer,
htab_eq_pointer, NULL,
xcalloc, xfree))
{
}
decode_compound_collector () = default;
DISABLE_COPY_AND_ASSIGN (decode_compound_collector);
/* Return all symbols collected. */
std::vector<block_symbol> release_symbols ()
@@ -3382,7 +3380,7 @@ public:
private:
/* A hash table of all symbols we found. We use this to avoid
adding any symbol more than once. */
htab_up m_unique_syms;
gdb::unordered_set<const symbol *> m_unique_syms;
/* The result vector. */
std::vector<block_symbol> m_symbols;
@@ -3391,7 +3389,6 @@ private:
bool
decode_compound_collector::operator () (block_symbol *bsym)
{
void **slot;
struct type *t;
struct symbol *sym = bsym->symbol;
@@ -3405,12 +3402,10 @@ decode_compound_collector::operator () (block_symbol *bsym)
&& t->code () != TYPE_CODE_NAMESPACE)
return true; /* Continue iterating. */
slot = htab_find_slot (m_unique_syms.get (), sym, INSERT);
if (!*slot)
{
*slot = sym;
m_symbols.push_back (*bsym);
}
bool inserted = m_unique_syms.insert (sym).second;
if (inserted)
m_symbols.push_back (*bsym);
return true; /* Continue iterating. */
}
@@ -3634,14 +3629,20 @@ namespace {
class symtab_collector
{
public:
symtab_collector ()
: m_symtab_table (htab_create (1, htab_hash_pointer, htab_eq_pointer,
NULL))
{
}
symtab_collector () = default;
DISABLE_COPY_AND_ASSIGN (symtab_collector);
/* Callable as a symbol_found_callback_ftype callback. */
bool operator () (symtab *sym);
bool operator () (struct symtab *symtab)
{
bool inserted = m_symtab_table.insert (symtab).second;
if (inserted)
m_symtabs.push_back (symtab);
return false;
}
/* Return an rvalue reference to the collected symtabs. */
std::vector<symtab *> &&release_symtabs ()
@@ -3654,24 +3655,9 @@ private:
std::vector<symtab *> m_symtabs;
/* This is used to ensure the symtabs are unique. */
htab_up m_symtab_table;
gdb::unordered_set<const symtab *> m_symtab_table;
};
bool
symtab_collector::operator () (struct symtab *symtab)
{
void **slot;
slot = htab_find_slot (m_symtab_table.get (), symtab, INSERT);
if (!*slot)
{
*slot = symtab;
m_symtabs.push_back (symtab);
}
return false;
}
} // namespace
/* Given a file name, return a list of all matching symtabs. If

View File

@@ -153,39 +153,6 @@ set_objfile_main_name (struct objfile *objfile,
objfile->per_bfd->language_of_main = lang;
}
/* Helper structure to map blocks to static link properties in hash tables. */
struct static_link_htab_entry
{
const struct block *block;
const struct dynamic_prop *static_link;
};
/* Return a hash code for struct static_link_htab_entry *P. */
static hashval_t
static_link_htab_entry_hash (const void *p)
{
const struct static_link_htab_entry *e
= (const struct static_link_htab_entry *) p;
return htab_hash_pointer (e->block);
}
/* Return whether P1 an P2 (pointers to struct static_link_htab_entry) are
mappings for the same block. */
static int
static_link_htab_entry_eq (const void *p1, const void *p2)
{
const struct static_link_htab_entry *e1
= (const struct static_link_htab_entry *) p1;
const struct static_link_htab_entry *e2
= (const struct static_link_htab_entry *) p2;
return e1->block == e2->block;
}
/* Register STATIC_LINK as the static link for BLOCK, which is part of OBJFILE.
Must not be called more than once for each BLOCK. */
@@ -194,25 +161,10 @@ objfile_register_static_link (struct objfile *objfile,
const struct block *block,
const struct dynamic_prop *static_link)
{
void **slot;
struct static_link_htab_entry lookup_entry;
struct static_link_htab_entry *entry;
if (objfile->static_links == NULL)
objfile->static_links.reset (htab_create_alloc
(1, &static_link_htab_entry_hash, static_link_htab_entry_eq, NULL,
xcalloc, xfree));
/* Create a slot for the mapping, make sure it's the first mapping for this
block and then create the mapping itself. */
lookup_entry.block = block;
slot = htab_find_slot (objfile->static_links.get (), &lookup_entry, INSERT);
gdb_assert (*slot == NULL);
entry = XOBNEW (&objfile->objfile_obstack, static_link_htab_entry);
entry->block = block;
entry->static_link = static_link;
*slot = (void *) entry;
/* Enter the mapping and make sure it's the first mapping for this
block. */
bool inserted = objfile->static_links.emplace (block, static_link).second;
gdb_assert (inserted);
}
/* Look for a static link for BLOCK, which is part of OBJFILE. Return NULL if
@@ -222,19 +174,11 @@ const struct dynamic_prop *
objfile_lookup_static_link (struct objfile *objfile,
const struct block *block)
{
struct static_link_htab_entry *entry;
struct static_link_htab_entry lookup_entry;
if (auto iter = objfile->static_links.find (block);
iter != objfile->static_links.end ())
return iter->second;
if (objfile->static_links == NULL)
return NULL;
lookup_entry.block = block;
entry = ((struct static_link_htab_entry *)
htab_find (objfile->static_links.get (), &lookup_entry));
if (entry == NULL)
return NULL;
gdb_assert (entry->block == block);
return entry->static_link;
return nullptr;
}

View File

@@ -32,6 +32,7 @@
#include "jit.h"
#include "quick-symbol.h"
#include <forward_list>
#include "gdbsupport/unordered_map.h"
struct htab;
struct objfile_data;
@@ -855,7 +856,8 @@ public:
Very few blocks have a static link, so it's more memory efficient to
store these here rather than in struct block. Static links must be
allocated on the objfile's obstack. */
htab_up static_links;
gdb::unordered_map<const block *, const dynamic_prop *>
static_links;
/* JIT-related data for this objfile, if the objfile is a JITer;
that is, it produces JITed objfiles. */

View File

@@ -17,6 +17,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "gdbsupport/unordered_set.h"
#include "objfiles.h"
#include "symtab.h"
#include "language.h"
@@ -27,7 +28,6 @@
#include "stack.h"
#include "source.h"
#include "annotate.h"
#include "hashtab.h"
#include "demangle.h"
#include "mi/mi-cmds.h"
#include "python-internal.h"
@@ -731,25 +731,37 @@ py_print_args (PyObject *filter,
return EXT_LANG_BT_OK;
}
using levels_printed_hash = gdb::unordered_set<frame_info *>;
/* Print a single frame to the designated output stream, detecting
whether the output is MI or console, and formatting the output
according to the conventions of that protocol. FILTER is the
frame-filter associated with this frame. FLAGS is an integer
describing the various print options. The FLAGS variables is
described in "apply_frame_filter" function. ARGS_TYPE is an
enumerator describing the argument format. OUT is the output
stream to print, INDENT is the level of indention for this frame
(in the case of elided frames), and LEVELS_PRINTED is a hash-table
containing all the frames level that have already been printed.
If a frame level has been printed, do not print it again (in the
case of elided frames). Returns EXT_LANG_BT_ERROR on error, with any
GDB exceptions converted to a Python exception, or EXT_LANG_BT_OK
on success. It can also throw an exception RETURN_QUIT. */
according to the conventions of that protocol.
FILTER is the frame-filter associated with this frame.
FLAGS is an integer describing the various print options. The FLAGS
variables is described in "apply_frame_filter" function.
ARGS_TYPE is an enumerator describing the argument format.
OUT is the output stream to print to.
INDENT is the level of indention for this frame (in the case of elided
frames).
LEVELS_PRINTED is a hash-table containing all the frames for which the
level has already been printed. If a level has been printed, do not print
it again (in the case of elided frames).
Returns EXT_LANG_BT_ERROR on error, with any GDB exceptions converted to a
Python exception, or EXT_LANG_BT_OK on success. It can also throw an
exception RETURN_QUIT. */
static enum ext_lang_bt_status
py_print_frame (PyObject *filter, frame_filter_flags flags,
enum ext_lang_frame_args args_type,
struct ui_out *out, int indent, htab_t levels_printed)
struct ui_out *out, int indent,
levels_printed_hash &levels_printed)
{
int has_addr = 0;
CORE_ADDR address = 0;
@@ -859,23 +871,18 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
&& (location_print
|| (out->is_mi_like_p () && (print_frame_info || print_args))))
{
struct frame_info **slot;
int level;
slot = (frame_info **) htab_find_slot (levels_printed,
frame.get(), INSERT);
level = frame_relative_level (frame);
/* Check if this frame has already been printed (there are cases
where elided synthetic dummy-frames have to 'borrow' the frame
architecture from the eliding frame. If that is the case, do
not print 'level', but print spaces. */
if (*slot == frame)
not print the level, but print spaces. */
bool inserted = levels_printed.insert (frame.get ()).second;
if (!inserted)
out->field_skip ("level");
else
{
*slot = frame.get ();
int level = frame_relative_level (frame);
annotate_frame_begin (print_level ? level : 0,
gdbarch, address);
out->text ("#");
@@ -1197,10 +1204,7 @@ gdbpy_apply_frame_filter (const struct extension_language_defn *extlang,
if (iterable == Py_None)
return EXT_LANG_BT_NO_FILTERS;
htab_up levels_printed (htab_create (20,
htab_hash_pointer,
htab_eq_pointer,
NULL));
levels_printed_hash levels_printed;
while (true)
{
@@ -1232,7 +1236,7 @@ gdbpy_apply_frame_filter (const struct extension_language_defn *extlang,
try
{
success = py_print_frame (item.get (), flags, args_type, out, 0,
levels_printed.get ());
levels_printed);
}
catch (const gdb_exception_error &except)
{

View File

@@ -1174,15 +1174,13 @@ struct typy_deleter
operating on. */
gdbpy_enter enter_py;
htab_up copied_types = create_copied_types_hash ();
copied_types_hash_t copied_types;
while (obj)
{
type_object *next = obj->next;
htab_empty (copied_types.get ());
obj->type = copy_type_recursive (obj->type, copied_types.get ());
obj->type = copy_type_recursive (obj->type, copied_types);
obj->next = NULL;
obj->prev = NULL;

View File

@@ -233,7 +233,8 @@ valpy_init (PyObject *self, PyObject *args, PyObject *kwds)
each. */
void
gdbpy_preserve_values (const struct extension_language_defn *extlang,
struct objfile *objfile, htab_t copied_types)
struct objfile *objfile,
copied_types_hash_t &copied_types)
{
value_object *iter;

View File

@@ -474,7 +474,7 @@ extern enum ext_lang_bt_status gdbpy_apply_frame_filter
struct ui_out *out, int frame_low, int frame_high);
extern void gdbpy_preserve_values (const struct extension_language_defn *,
struct objfile *objfile,
htab_t copied_types);
copied_types_hash_t &copied_types);
extern enum ext_lang_bp_stop gdbpy_breakpoint_cond_says_stop
(const struct extension_language_defn *, struct breakpoint *);
extern int gdbpy_breakpoint_has_cond (const struct extension_language_defn *,

View File

@@ -2537,7 +2537,7 @@ reread_symbols (int from_tty)
objfile->sect_index_text = -1;
objfile->compunit_symtabs = NULL;
objfile->template_symbols = NULL;
objfile->static_links.reset (nullptr);
objfile->static_links.clear ();
/* obstack_init also initializes the obstack so it is
empty. We could use obstack_specify_allocation but

View File

@@ -396,17 +396,10 @@ linetable_entry::pc (const struct objfile *objfile) const
call_site *
compunit_symtab::find_call_site (CORE_ADDR pc) const
{
if (m_call_site_htab == nullptr)
return nullptr;
CORE_ADDR delta = this->objfile ()->text_section_offset ();
unrelocated_addr unrelocated_pc = (unrelocated_addr) (pc - delta);
struct call_site call_site_local (unrelocated_pc, nullptr, nullptr);
void **slot
= htab_find_slot (m_call_site_htab, &call_site_local, NO_INSERT);
if (slot != nullptr)
return (call_site *) *slot;
auto it = m_call_site_htab->find (static_cast<unrelocated_addr> (pc - delta));
if (it != m_call_site_htab->end ())
return it->second;
/* See if the arch knows another PC we should try. On some
platforms, GCC emits a DWARF call site that is offset from the
@@ -416,22 +409,20 @@ compunit_symtab::find_call_site (CORE_ADDR pc) const
if (pc == new_pc)
return nullptr;
unrelocated_pc = (unrelocated_addr) (new_pc - delta);
call_site new_call_site_local (unrelocated_pc, nullptr, nullptr);
slot = htab_find_slot (m_call_site_htab, &new_call_site_local, NO_INSERT);
if (slot == nullptr)
return nullptr;
it = m_call_site_htab->find (static_cast<unrelocated_addr> (new_pc - delta));
if (it != m_call_site_htab->end ())
return it->second;
return (call_site *) *slot;
return nullptr;
}
/* See symtab.h. */
void
compunit_symtab::set_call_site_htab (htab_up call_site_htab)
compunit_symtab::set_call_site_htab (call_site_htab_t &&call_site_htab)
{
gdb_assert (m_call_site_htab == nullptr);
m_call_site_htab = call_site_htab.release ();
m_call_site_htab = new call_site_htab_t (std::move (call_site_htab));
}
/* See symtab.h. */
@@ -500,8 +491,7 @@ void
compunit_symtab::finalize ()
{
this->forget_cached_source_info ();
if (m_call_site_htab != nullptr)
htab_delete (m_call_site_htab);
delete m_call_site_htab;
}
/* The relocated address of the minimal symbol, using the section

View File

@@ -24,6 +24,7 @@
#include <vector>
#include <string>
#include <set>
#include "dwarf2/call-site.h"
#include "gdbsupport/gdb_vecs.h"
#include "gdbtypes.h"
#include "gdbsupport/gdb_obstack.h"
@@ -1957,7 +1958,7 @@ struct compunit_symtab
symtab *primary_filetab () const;
/* Set m_call_site_htab. */
void set_call_site_htab (htab_up call_site_htab);
void set_call_site_htab (call_site_htab_t &&call_site_htab);
/* Find call_site info for PC. */
call_site *find_call_site (CORE_ADDR pc) const;
@@ -2024,7 +2025,7 @@ struct compunit_symtab
unsigned int m_epilogue_unwind_valid : 1;
/* struct call_site entries for this compilation unit or NULL. */
htab_t m_call_site_htab;
call_site_htab_t *m_call_site_htab;
/* The macro table for this symtab. Like the blockvector, this
is shared between different symtabs in a given compilation unit.

View File

@@ -21,6 +21,7 @@
#include "arch-utils.h"
#include "cli/cli-cmds.h"
#include "gdbsupport/unordered_set.h"
#include "gdbtypes.h"
#include "reggroups.h"
#include "target.h"
@@ -30,7 +31,6 @@
#include "osabi.h"
#include "gdbsupport/gdb_obstack.h"
#include "hashtab.h"
#include "inferior.h"
#include <algorithm>
#include "completer.h"
@@ -1042,16 +1042,12 @@ tdesc_use_registers (struct gdbarch *gdbarch,
data->arch_regs = std::move (early_data->arch_regs);
/* Build up a set of all registers, so that we can assign register
numbers where needed. The hash table expands as necessary, so
the initial size is arbitrary. */
htab_up reg_hash (htab_create (37, htab_hash_pointer, htab_eq_pointer,
NULL));
numbers where needed. */
gdb::unordered_set<tdesc_reg *> reg_hash;
for (const tdesc_feature_up &feature : target_desc->features)
for (const tdesc_reg_up &reg : feature->registers)
{
void **slot = htab_find_slot (reg_hash.get (), reg.get (), INSERT);
*slot = reg.get ();
reg_hash.insert (reg.get ());
/* Add reggroup if its new. */
if (!reg->group.empty ())
if (reggroup_find (gdbarch, reg->group.c_str ()) == NULL)
@@ -1064,7 +1060,7 @@ tdesc_use_registers (struct gdbarch *gdbarch,
architecture. */
for (const tdesc_arch_reg &arch_reg : data->arch_regs)
if (arch_reg.reg != NULL)
htab_remove_elt (reg_hash.get (), arch_reg.reg);
reg_hash.erase (arch_reg.reg);
/* Assign numbers to the remaining registers and add them to the
list of registers. The new numbers are always above gdbarch_num_regs.
@@ -1082,7 +1078,7 @@ tdesc_use_registers (struct gdbarch *gdbarch,
{
for (const tdesc_feature_up &feature : target_desc->features)
for (const tdesc_reg_up &reg : feature->registers)
if (htab_find (reg_hash.get (), reg.get ()) != NULL)
if (reg_hash.contains (reg.get ()))
{
int regno = unk_reg_cb (gdbarch, feature.get (),
reg->name.c_str (), num_regs);
@@ -1093,7 +1089,7 @@ tdesc_use_registers (struct gdbarch *gdbarch,
data->arch_regs.emplace_back (nullptr, nullptr);
data->arch_regs[regno] = tdesc_arch_reg (reg.get (), NULL);
num_regs = regno + 1;
htab_remove_elt (reg_hash.get (), reg.get ());
reg_hash.erase (reg.get ());
}
}
}
@@ -1105,7 +1101,7 @@ tdesc_use_registers (struct gdbarch *gdbarch,
unnumbered registers. */
for (const tdesc_feature_up &feature : target_desc->features)
for (const tdesc_reg_up &reg : feature->registers)
if (htab_find (reg_hash.get (), reg.get ()) != NULL)
if (reg_hash.contains (reg.get ()))
{
data->arch_regs.emplace_back (reg.get (), nullptr);
num_regs++;

View File

@@ -78,10 +78,18 @@ proc do_check_holder {name {flags ""} {show_typedefs 1} {show_methods 1}
proc do_check_typedef_holder {name {flags ""} {show_typedefs 1} {show_methods 1}
{raw 0}} {
set contents {
{ field public "double a;" }
{ field public "ns::scoped_double b;" }
{ field public "global_double c;" }
if {$raw} {
set contents {
{ field public "double a;" }
{ field public "ns::scoped_double b;" }
{ field public "global_double c;" }
}
} else {
set contents {
{ field public "class_double a;" }
{ field public "class_double b;" }
{ field public "class_double c;" }
}
}
if {$show_typedefs} {
@@ -89,8 +97,13 @@ proc do_check_typedef_holder {name {flags ""} {show_typedefs 1} {show_methods 1}
}
if {$show_methods} {
lappend contents { method private "double method1(ns::scoped_double);" }
lappend contents { method private "double method2(global_double);" }
if {$raw} {
lappend contents { method private "double method1(ns::scoped_double);" }
lappend contents { method private "double method2(global_double);" }
} else {
lappend contents { method private "class_double method1(class_double);" }
lappend contents { method private "class_double method2(class_double);" }
}
}
if {$raw} {

View File

@@ -261,7 +261,8 @@ proc test_python_helper {} {
}
# Test the htab_t pretty-printer.
gdb_test -prompt $outer_prompt_re "print all_bfds" "htab_t with ${::decimal} elements = \\{${::hex}.*\\}"
gdb_test -prompt $outer_prompt_re "print varobj_table" \
"htab_t with ${::decimal} elements"
# Test the intrusive_list pretty-printer. A bug occured in the
# pretty-printer for lists with more than one element. Verify that

View File

@@ -194,49 +194,19 @@ print_offset_data::finish (struct type *type, int level,
/* A hash function for a typedef_field. */
static hashval_t
hash_typedef_field (const void *p)
{
const struct decl_field *tf = (const struct decl_field *) p;
return htab_hash_string (TYPE_SAFE_NAME (tf->type));
}
/* An equality function for a typedef field. */
static int
eq_typedef_field (const void *a, const void *b)
{
const struct decl_field *tfa = (const struct decl_field *) a;
const struct decl_field *tfb = (const struct decl_field *) b;
return types_equal (tfa->type, tfb->type);
}
/* See typeprint.h. */
void
typedef_hash_table::recursively_update (struct type *t)
{
int i;
for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (t); ++i)
for (int i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (t); ++i)
{
struct decl_field *tdef = &TYPE_TYPEDEF_FIELD (t, i);
void **slot;
slot = htab_find_slot (m_table.get (), tdef, INSERT);
/* Only add a given typedef name once. Really this shouldn't
happen; but it is safe enough to do the updates breadth-first
and thus use the most specific typedef. */
if (*slot == NULL)
*slot = tdef;
decl_field *child_type = &TYPE_TYPEDEF_FIELD (t, i);
m_table.emplace (child_type->type, child_type);
}
/* Recurse into superclasses. */
for (i = 0; i < TYPE_N_BASECLASSES (t); ++i)
for (int i = 0; i < TYPE_N_BASECLASSES (t); ++i)
recursively_update (TYPE_BASECLASS (t, i));
}
@@ -250,7 +220,6 @@ typedef_hash_table::add_template_parameters (struct type *t)
for (i = 0; i < TYPE_N_TEMPLATE_ARGUMENTS (t); ++i)
{
struct decl_field *tf;
void **slot;
/* We only want type-valued template parameters in the hash. */
if (TYPE_TEMPLATE_ARGUMENT (t, i)->aclass () != LOC_TYPEDEF)
@@ -260,45 +229,10 @@ typedef_hash_table::add_template_parameters (struct type *t)
tf->name = TYPE_TEMPLATE_ARGUMENT (t, i)->linkage_name ();
tf->type = TYPE_TEMPLATE_ARGUMENT (t, i)->type ();
slot = htab_find_slot (m_table.get (), tf, INSERT);
if (*slot == NULL)
*slot = tf;
m_table.emplace (tf->type, tf);
}
}
/* See typeprint.h. */
typedef_hash_table::typedef_hash_table ()
: m_table (htab_create_alloc (10, hash_typedef_field, eq_typedef_field,
NULL, xcalloc, xfree))
{
}
/* Helper function for typedef_hash_table::copy. */
static int
copy_typedef_hash_element (void **slot, void *nt)
{
htab_t new_table = (htab_t) nt;
void **new_slot;
new_slot = htab_find_slot (new_table, *slot, INSERT);
if (*new_slot == NULL)
*new_slot = *slot;
return 1;
}
/* See typeprint.h. */
typedef_hash_table::typedef_hash_table (const typedef_hash_table &table)
{
m_table.reset (htab_create_alloc (10, hash_typedef_field, eq_typedef_field,
NULL, xcalloc, xfree));
htab_traverse_noresize (table.m_table.get (), copy_typedef_hash_element,
m_table.get ());
}
/* Look up the type T in the global typedef hash. If it is found,
return the typedef name. If it is not found, apply the
type-printers, if any, given by start_script_type_printers and return the
@@ -308,29 +242,21 @@ const char *
typedef_hash_table::find_global_typedef (const struct type_print_options *flags,
struct type *t)
{
void **slot;
struct decl_field tf, *new_tf;
if (flags->global_typedefs == NULL)
return NULL;
tf.name = NULL;
tf.type = t;
slot = htab_find_slot (flags->global_typedefs->m_table.get (), &tf, INSERT);
if (*slot != NULL)
{
new_tf = (struct decl_field *) *slot;
return new_tf->name;
}
if (auto it = flags->global_typedefs->m_table.find (t);
it != flags->global_typedefs->m_table.end ())
return it->second->name;
/* Put an entry into the hash table now, in case
apply_ext_lang_type_printers recurses. */
new_tf = XOBNEW (&flags->global_typedefs->m_storage, struct decl_field);
decl_field *new_tf
= XOBNEW (&flags->global_typedefs->m_storage, struct decl_field);
new_tf->name = NULL;
new_tf->type = t;
*slot = new_tf;
flags->global_typedefs->m_table.emplace (new_tf->type, new_tf);
gdb::unique_xmalloc_ptr<char> applied
= apply_ext_lang_type_printers (flags->global_printers, t);
@@ -350,15 +276,9 @@ typedef_hash_table::find_typedef (const struct type_print_options *flags,
{
if (flags->local_typedefs != NULL)
{
struct decl_field tf, *found;
tf.name = NULL;
tf.type = t;
htab_t table = flags->local_typedefs->m_table.get ();
found = (struct decl_field *) htab_find (table, &tf);
if (found != NULL)
return found->name;
if (auto iter = flags->local_typedefs->m_table.find (t);
iter != flags->local_typedefs->m_table.end ())
return iter->second->name;
}
return find_global_typedef (flags, t);

View File

@@ -20,6 +20,8 @@
#define TYPEPRINT_H
#include "gdbsupport/gdb_obstack.h"
#include "gdbsupport/unordered_set.h"
#include "gdbtypes.h"
enum language;
struct ui_file;
@@ -123,10 +125,12 @@ class typedef_hash_table
public:
/* Create a new typedef-lookup hash table. */
typedef_hash_table ();
typedef_hash_table () = default;
/* Copy a typedef hash. */
typedef_hash_table (const typedef_hash_table &);
typedef_hash_table (const typedef_hash_table &other)
: m_table (other.m_table)
{}
typedef_hash_table &operator= (const typedef_hash_table &) = delete;
@@ -149,9 +153,24 @@ private:
static const char *find_global_typedef (const struct type_print_options *flags,
struct type *t);
struct hash
{
std::size_t operator() (type *type) const noexcept
{
/* Use check_typedef: the hash must agree with equals, and types_equal
strips typedefs. */
return htab_hash_string (TYPE_SAFE_NAME (check_typedef (type)));
}
};
struct eq
{
bool operator() (type *lhs, type *rhs) const noexcept
{ return types_equal (lhs, rhs); }
};
/* The actual hash table. */
htab_up m_table;
gdb::unordered_map<type *, decl_field *, hash, eq> m_table;
/* Storage for typedef_field objects that must be synthesized. */
auto_obstack m_storage;

View File

@@ -2468,7 +2468,7 @@ add_internal_function (gdb::unique_xmalloc_ptr<char> &&name,
}
void
value::preserve (struct objfile *objfile, htab_t copied_types)
value::preserve (struct objfile *objfile, copied_types_hash_t &copied_types)
{
if (m_type->objfile_owner () == objfile)
m_type = copy_type_recursive (m_type, copied_types);
@@ -2481,7 +2481,7 @@ value::preserve (struct objfile *objfile, htab_t copied_types)
static void
preserve_one_internalvar (struct internalvar *var, struct objfile *objfile,
htab_t copied_types)
copied_types_hash_t &copied_types)
{
switch (var->kind)
{
@@ -2504,7 +2504,7 @@ preserve_one_internalvar (struct internalvar *var, struct objfile *objfile,
static void
preserve_one_varobj (struct varobj *varobj, struct objfile *objfile,
htab_t copied_types)
copied_types_hash_t &copied_types)
{
if (varobj->type->is_objfile_owned ()
&& varobj->type->objfile_owner () == objfile)
@@ -2528,22 +2528,21 @@ preserve_values (struct objfile *objfile)
{
/* Create the hash table. We allocate on the objfile's obstack, since
it is soon to be deleted. */
htab_up copied_types = create_copied_types_hash ();
copied_types_hash_t copied_types;
for (const value_ref_ptr &item : value_history)
item->preserve (objfile, copied_types.get ());
item->preserve (objfile, copied_types);
for (auto &pair : internalvars)
preserve_one_internalvar (&pair.second, objfile, copied_types.get ());
preserve_one_internalvar (&pair.second, objfile, copied_types);
/* For the remaining varobj, check that none has type owned by OBJFILE. */
all_root_varobjs ([&copied_types, objfile] (struct varobj *varobj)
{
preserve_one_varobj (varobj, objfile,
copied_types.get ());
preserve_one_varobj (varobj, objfile, copied_types);
});
preserve_ext_lang_values (objfile, copied_types.get ());
preserve_ext_lang_values (objfile, copied_types);
}
static void

View File

@@ -24,12 +24,12 @@
#include "extension.h"
#include "gdbsupport/gdb_ref_ptr.h"
#include "gmp-utils.h"
#include "gdbtypes.h"
struct block;
struct expression;
struct regcache;
struct symbol;
struct type;
struct ui_file;
struct language_defn;
struct value_print_options;
@@ -593,7 +593,7 @@ public:
/* Update this value before discarding OBJFILE. COPIED_TYPES is
used to prevent cycles / duplicates. */
void preserve (struct objfile *objfile, htab_t copied_types);
void preserve (struct objfile *objfile, copied_types_hash_t &copied_types);
/* Unpack a bitfield of BITSIZE bits found at BITPOS in the object
at VALADDR + EMBEDDEDOFFSET that has the type of DEST_VAL and

2032
gdbsupport/unordered_dense.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
/* Copyright (C) 2024 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef GDBSUPPORT_UNORDERED_MAP_H
#define GDBSUPPORT_UNORDERED_MAP_H
#include "unordered_dense.h"
namespace gdb
{
template<typename Key,
typename T,
typename Hash = ankerl::unordered_dense::hash<Key>,
typename KeyEqual = std::equal_to<Key>>
using unordered_map
= ankerl::unordered_dense::map
<Key, T, Hash, KeyEqual, std::allocator<std::pair<Key, T>>,
ankerl::unordered_dense::bucket_type::standard>;
} /* namespace gdb */
#endif /* GDBSUPPORT_UNORDERED_MAP_H */

View File

@@ -0,0 +1,36 @@
/* Copyright (C) 2024 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef GDBSUPPORT_UNORDERED_SET_H
#define GDBSUPPORT_UNORDERED_SET_H
#include "unordered_dense.h"
namespace gdb
{
template<typename Key,
typename Hash = ankerl::unordered_dense::hash<Key>,
typename KeyEqual = std::equal_to<Key>>
using unordered_set
= ankerl::unordered_dense::set
<Key, Hash, KeyEqual, std::allocator<Key>,
ankerl::unordered_dense::bucket_type::standard>;
} /* namespace gdb */
#endif /* GDBSUPPORT_UNORDERED_SET_H */