From 7188ed02d2a7e3fce00a0214e70457c5ef56df6b Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Wed, 27 May 2020 11:14:11 -0400 Subject: [PATCH] Replace dwarf2_per_cu_data::cu backlink with per-objfile map The dwarf2_per_cu_data type is going to become objfile-independent, while the dwarf2_cu type will stay object-dependent. This patch removes the backlink from dwarf2_per_cu_data to dwarf2_cu, in favor of the dwarf2_per_objfile::m_dwarf2_cus map. It maps dwarf2_per_cu_data objects to the corresponding dwarf2_cu objects for this objfile. If a CU has been read in in the context of this objfile, then an entry will be present in the map. The dwarf2_cu objects that are read in are currently kept in a linked list rooted in the dwarf2_per_bfd. Except that the dwarf2_cu objects are not simply linked together, they are interleaved with their corresponding dwarf2_per_cu_data objects. So if we have CUs A and B read in, the dwarf2_per_bfd::read_in_chain will point to a chain like this (DPCD == dwarf2_per_cu_data, DC == dwarf2_cu): DPCD A -> DC A -> DPCD B -> DC B Obviously, this can't stay as is, since a same CU can be read in for an objfile but not read in for another objfile sharing the same BFD, and the dwarf2_per_cu_data::cu link is removed. This is all replaced by the dwarf2_per_objfile::m_dwarf2_cus map. gdb/ChangeLog: * dwarf2/read.h (struct dwarf2_cu): Forward-declare. (struct dwarf2_per_bfd) : Remove, move to dwarf2_per_objfile. : Remove. (struct dwarf2_per_objfile) : New methods. : New member. (struct dwarf2_per_cu_data) : Remove. * dwarf2/read.c (struct dwarf2_cu) : Remove. (age_cached_comp_units, free_one_cached_comp_unit): Remove, moved to methods of dwarf2_per_objfile. (dwarf2_clear_marks): Remove. (dwarf2_queue_item::~dwarf2_queue_item): Update. (dwarf2_per_bfd::~dwarf2_per_bfd): Don't free dwarf2_cus. (dwarf2_per_bfd::free_cached_comp_units): Remove. (dwarf2_per_objfile::remove_all_cus): New. (class free_cached_comp_units) <~free_cached_comp_units>: Update. (load_cu): Update. (dw2_do_instantiate_symtab): Adjust. (fill_in_sig_entry_from_dwo_entry): Adjust. (cutu_reader::init_tu_and_read_dwo_dies): Update. (cutu_reader::cutu_reader): Likewise. (cutu_reader::keep): Use dwarf2_per_objfile::set_cu. (cutu_reader::cutu_reader): Use dwarf2_per_objfile::get_cu. (process_psymtab_comp_unit): Use dwarf2_per_objfile::remove_cu and dwarf2_per_objfile::age_comp_units. (load_partial_comp_unit): Update. (maybe_queue_comp_unit): Use dwarf2_per_objfile::get_cu. (process_queue): Likewise. (find_partial_die): Use dwarf2_per_objfile::get_cu instead of cu backlink. (dwarf2_read_addr_index): Likewise. (follow_die_offset): Likewise. (dwarf2_fetch_die_loc_sect_off): Likewise. (dwarf2_fetch_constant_bytes): Likewise. (dwarf2_fetch_die_type_sect_off): Likewise. (follow_die_sig_1): Likewise. (load_full_type_unit): Likewise. (read_signatured_type): Likewise. (dwarf2_cu::dwarf2_cu): Don't set cu field. (dwarf2_cu::~dwarf2_cu): Remove. (dwarf2_per_objfile::get_cu): New. (dwarf2_per_objfile::set_cu): New. (age_cached_comp_units): Rename to... (dwarf2_per_objfile::age_comp_units): ... this. Adjust to std::unordered_map. (free_one_cached_comp_unit): Rename to... (dwarf2_per_objfile::remove_cu): ... this. Adjust to std::unordered_map. (dwarf2_per_objfile::~dwarf2_per_objfile): New. (dwarf2_mark_helper): Use dwarf2_per_objfile::get_cu, expect a dwarf2_per_objfile in data. (dwarf2_mark): Pass dwarf2_per_objfile in data to htab_traverse. (dwarf2_clear_marks): Remove. Change-Id: Ia33ac71c79b2de4710569008e22a6563a1505cde --- gdb/ChangeLog | 58 ++++++++ gdb/dwarf2/read.c | 355 ++++++++++++++++++++++------------------------ gdb/dwarf2/read.h | 35 +++-- 3 files changed, 247 insertions(+), 201 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 9a281943bca..990844b3959 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,61 @@ +2020-05-27 Simon Marchi + + * dwarf2/read.h (struct dwarf2_cu): Forward-declare. + (struct dwarf2_per_bfd) : Remove, + move to dwarf2_per_objfile. + : Remove. + (struct dwarf2_per_objfile) : New methods. + : New member. + (struct dwarf2_per_cu_data) : Remove. + * dwarf2/read.c (struct dwarf2_cu) : Remove. + (age_cached_comp_units, free_one_cached_comp_unit): Remove, + moved to methods of dwarf2_per_objfile. + (dwarf2_clear_marks): Remove. + (dwarf2_queue_item::~dwarf2_queue_item): Update. + (dwarf2_per_bfd::~dwarf2_per_bfd): Don't free dwarf2_cus. + (dwarf2_per_bfd::free_cached_comp_units): Remove. + (dwarf2_per_objfile::remove_all_cus): New. + (class free_cached_comp_units) <~free_cached_comp_units>: + Update. + (load_cu): Update. + (dw2_do_instantiate_symtab): Adjust. + (fill_in_sig_entry_from_dwo_entry): Adjust. + (cutu_reader::init_tu_and_read_dwo_dies): Update. + (cutu_reader::cutu_reader): Likewise. + (cutu_reader::keep): Use dwarf2_per_objfile::set_cu. + (cutu_reader::cutu_reader): Use dwarf2_per_objfile::get_cu. + (process_psymtab_comp_unit): Use dwarf2_per_objfile::remove_cu + and dwarf2_per_objfile::age_comp_units. + (load_partial_comp_unit): Update. + (maybe_queue_comp_unit): Use dwarf2_per_objfile::get_cu. + (process_queue): Likewise. + (find_partial_die): Use dwarf2_per_objfile::get_cu instead of cu + backlink. + (dwarf2_read_addr_index): Likewise. + (follow_die_offset): Likewise. + (dwarf2_fetch_die_loc_sect_off): Likewise. + (dwarf2_fetch_constant_bytes): Likewise. + (dwarf2_fetch_die_type_sect_off): Likewise. + (follow_die_sig_1): Likewise. + (load_full_type_unit): Likewise. + (read_signatured_type): Likewise. + (dwarf2_cu::dwarf2_cu): Don't set cu field. + (dwarf2_cu::~dwarf2_cu): Remove. + (dwarf2_per_objfile::get_cu): New. + (dwarf2_per_objfile::set_cu): New. + (age_cached_comp_units): Rename to... + (dwarf2_per_objfile::age_comp_units): ... this. Adjust + to std::unordered_map. + (free_one_cached_comp_unit): Rename to... + (dwarf2_per_objfile::remove_cu): ... this. Adjust + to std::unordered_map. + (dwarf2_per_objfile::~dwarf2_per_objfile): New. + (dwarf2_mark_helper): Use dwarf2_per_objfile::get_cu, expect + a dwarf2_per_objfile in data. + (dwarf2_mark): Pass dwarf2_per_objfile in data to htab_traverse. + (dwarf2_clear_marks): Remove. + 2020-05-27 Simon Marchi * dwarf2/read.c (class cutu_reader) : Replace diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index c2dc34477f7..6319d4b2859 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -401,7 +401,6 @@ struct dwarf2_cu { explicit dwarf2_cu (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile); - ~dwarf2_cu (); DISABLE_COPY_AND_ASSIGN (dwarf2_cu); @@ -468,12 +467,6 @@ public: unit, including partial DIEs. */ auto_obstack comp_unit_obstack; - /* When multiple dwarf2_cu structures are living in memory, this field - chains them all together, so that they can be released efficiently. - We will probably also want a generation counter so that most-recently-used - compilation units are cached... */ - struct dwarf2_per_cu_data *read_in_chain = nullptr; - /* Backlink to our per_cu entry. */ struct dwarf2_per_cu_data *per_cu; @@ -1553,11 +1546,6 @@ static void prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die, enum language pretend_language); -static void age_cached_comp_units (struct dwarf2_per_objfile *dwarf2_per_objfile); - -static void free_one_cached_comp_unit (dwarf2_per_cu_data *target_per_cu, - dwarf2_per_objfile *per_objfile); - static struct type *set_die_type (struct die_info *, struct type *, struct dwarf2_cu *); @@ -1581,8 +1569,6 @@ static void dwarf2_add_dependence (struct dwarf2_cu *, static void dwarf2_mark (struct dwarf2_cu *); -static void dwarf2_clear_marks (struct dwarf2_per_cu_data *); - static struct type *get_die_type_at_offset (sect_offset, dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile); @@ -1629,8 +1615,7 @@ dwarf2_queue_item::~dwarf2_queue_item () inconsistent state, so discard it. */ if (per_cu->queued) { - if (per_cu->cu != NULL) - free_one_cached_comp_unit (per_cu, per_objfile); + per_objfile->remove_cu (per_cu); per_cu->queued = 0; } } @@ -1772,9 +1757,6 @@ dwarf2_per_bfd::dwarf2_per_bfd (bfd *obfd, const dwarf2_debug_sections *names, dwarf2_per_bfd::~dwarf2_per_bfd () { - /* Cached DIE trees use xmalloc and the comp_unit_obstack. */ - free_cached_comp_units (); - for (dwarf2_per_cu_data *per_cu : all_comp_units) per_cu->imported_symtabs_free (); @@ -1784,21 +1766,15 @@ dwarf2_per_bfd::~dwarf2_per_bfd () /* Everything else should be on this->obstack. */ } -/* See declaration. */ +/* See read.h. */ void -dwarf2_per_bfd::free_cached_comp_units () +dwarf2_per_objfile::remove_all_cus () { - dwarf2_per_cu_data *per_cu = read_in_chain; - dwarf2_per_cu_data **last_chain = &read_in_chain; - while (per_cu != NULL) - { - dwarf2_per_cu_data *next_cu = per_cu->cu->read_in_chain; + for (auto pair : m_dwarf2_cus) + delete pair.second; - delete per_cu->cu; - *last_chain = next_cu; - per_cu = next_cu; - } + m_dwarf2_cus.clear (); } /* A helper class that calls free_cached_comp_units on @@ -1815,7 +1791,7 @@ public: ~free_cached_comp_units () { - m_per_objfile->per_bfd->free_cached_comp_units (); + m_per_objfile->remove_all_cus (); } DISABLE_COPY_AND_ASSIGN (free_cached_comp_units); @@ -2344,12 +2320,13 @@ load_cu (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile, else load_full_comp_unit (per_cu, per_objfile, skip_partial, language_minimal); - if (per_cu->cu == nullptr) + dwarf2_cu *cu = per_objfile->get_cu (per_cu); + if (cu == nullptr) return nullptr; /* Dummy CU. */ - dwarf2_find_base_address (per_cu->cu->dies, per_cu->cu); + dwarf2_find_base_address (cu->dies, cu); - return per_cu->cu; + return cu; } /* Read in the symbols for PER_CU in the context of DWARF"_PER_OBJFILE. */ @@ -2391,7 +2368,7 @@ dw2_do_instantiate_symtab (dwarf2_per_cu_data *per_cu, /* Age the cache, releasing compilation units that have not been used recently. */ - age_cached_comp_units (dwarf2_per_objfile); + dwarf2_per_objfile->age_comp_units (); } /* Ensure that the symbols for PER_CU have been read in. DWARF2_PER_OBJFILE is @@ -6465,7 +6442,7 @@ fill_in_sig_entry_from_dwo_entry (struct dwarf2_per_objfile *dwarf2_per_objfile, /* Make sure we're not clobbering something we don't expect to. */ gdb_assert (! sig_entry->per_cu.queued); - gdb_assert (sig_entry->per_cu.cu == NULL); + gdb_assert (dwarf2_per_objfile->get_cu (&sig_entry->per_cu) == NULL); if (per_bfd->using_index) { gdb_assert (sig_entry->per_cu.v.quick != NULL); @@ -6923,8 +6900,9 @@ cutu_reader::init_tu_and_read_dwo_dies (dwarf2_per_cu_data *this_cu, } else { - /* If an existing_cu is provided, this_cu->cu must be NULL. */ - gdb_assert (this_cu->cu == NULL); + /* If an existing_cu is provided, a dwarf2_cu must not exist for this_cu + in per_objfile yet. */ + gdb_assert (per_objfile->get_cu (this_cu) == nullptr); m_new_cu.reset (new dwarf2_cu (this_cu, per_objfile)); cu = m_new_cu.get (); } @@ -7013,8 +6991,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu, } else { - /* If an existing_cu is provided, this_cu->cu must be NULL. */ - gdb_assert (this_cu->cu == NULL); + /* If an existing_cu is provided, a dwarf2_cu must not exist for this_cu + in per_objfile yet. */ + gdb_assert (dwarf2_per_objfile->get_cu (this_cu) == nullptr); m_new_cu.reset (new dwarf2_cu (this_cu, dwarf2_per_objfile)); cu = m_new_cu.get (); } @@ -7154,16 +7133,10 @@ cutu_reader::keep () gdb_assert (!dummy_p); if (m_new_cu != NULL) { - /* We know that m_this_cu->cu is set, since we are in the process of - parsing the CU. */ - gdb_assert (m_this_cu->cu != nullptr); - dwarf2_per_objfile *dwarf2_per_objfile = m_this_cu->cu->per_objfile; - - /* Link this CU into read_in_chain. */ - m_this_cu->cu->read_in_chain = dwarf2_per_objfile->per_bfd->read_in_chain; - dwarf2_per_objfile->per_bfd->read_in_chain = m_this_cu; - /* The chain owns it now. */ - m_new_cu.release (); + /* Save this dwarf2_cu in the per_objfile. The per_objfile owns it + now. */ + dwarf2_per_objfile *per_objfile = m_new_cu->per_objfile; + per_objfile->set_cu (m_this_cu, m_new_cu.release ()); } } @@ -7201,7 +7174,7 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu, this_cu->is_debug_types ? "type" : "comp", sect_offset_str (this_cu->sect_off)); - gdb_assert (this_cu->cu == NULL); + gdb_assert (dwarf2_per_objfile->get_cu (this_cu) == nullptr); abbrev_section = (dwo_file != NULL ? &dwo_file->sections.abbrev @@ -7563,8 +7536,7 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu, necessary because we skipped some symbols when we first read in the compilation unit (see load_partial_dies). This problem could be avoided, but the benefit is unclear. */ - if (this_cu->cu != NULL) - free_one_cached_comp_unit (this_cu, per_objfile); + per_objfile->remove_cu (this_cu); cutu_reader reader (this_cu, per_objfile, nullptr, nullptr, false); @@ -7593,10 +7565,10 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu, reader.comp_unit_die, pretend_language); - this_cu->lang = this_cu->cu->language; + this_cu->lang = reader.cu->language; /* Age out any secondary CUs. */ - age_cached_comp_units (per_objfile); + per_objfile->age_comp_units (); } /* Reader function for build_type_psymtabs. */ @@ -8951,7 +8923,9 @@ maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu, not queue PER_CU, just tell our caller to load its DIEs. */ if (per_cu->per_bfd->reading_partial_symbols) { - if (per_cu->cu == NULL || per_cu->cu->dies == NULL) + dwarf2_cu *cu = per_objfile->get_cu (per_cu); + + if (cu == NULL || cu->dies == NULL) return 1; return 0; } @@ -8967,9 +8941,10 @@ maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu, /* If the compilation unit is already loaded, just mark it as used. */ - if (per_cu->cu != NULL) + dwarf2_cu *cu = per_objfile->get_cu (per_cu); + if (cu != nullptr) { - per_cu->cu->last_used = 0; + cu->last_used = 0; return 0; } @@ -8996,47 +8971,51 @@ process_queue (struct dwarf2_per_objfile *dwarf2_per_objfile) while (!dwarf2_per_objfile->per_bfd->queue.empty ()) { dwarf2_queue_item &item = dwarf2_per_objfile->per_bfd->queue.front (); + dwarf2_per_cu_data *per_cu = item.per_cu; - if (!dwarf2_per_objfile->symtab_set_p (item.per_cu) - /* Skip dummy CUs. */ - && item.per_cu->cu != NULL) + if (!dwarf2_per_objfile->symtab_set_p (per_cu)) { - struct dwarf2_per_cu_data *per_cu = item.per_cu; - unsigned int debug_print_threshold; - char buf[100]; + dwarf2_cu *cu = dwarf2_per_objfile->get_cu (per_cu); - if (per_cu->is_debug_types) - { - struct signatured_type *sig_type = - (struct signatured_type *) per_cu; - - sprintf (buf, "TU %s at offset %s", - hex_string (sig_type->signature), - sect_offset_str (per_cu->sect_off)); - /* There can be 100s of TUs. - Only print them in verbose mode. */ - debug_print_threshold = 2; - } - else + /* Skip dummy CUs. */ + if (cu != nullptr) { - sprintf (buf, "CU at offset %s", - sect_offset_str (per_cu->sect_off)); - debug_print_threshold = 1; - } + unsigned int debug_print_threshold; + char buf[100]; + + if (per_cu->is_debug_types) + { + struct signatured_type *sig_type = + (struct signatured_type *) per_cu; + + sprintf (buf, "TU %s at offset %s", + hex_string (sig_type->signature), + sect_offset_str (per_cu->sect_off)); + /* There can be 100s of TUs. + Only print them in verbose mode. */ + debug_print_threshold = 2; + } + else + { + sprintf (buf, "CU at offset %s", + sect_offset_str (per_cu->sect_off)); + debug_print_threshold = 1; + } - if (dwarf_read_debug >= debug_print_threshold) - fprintf_unfiltered (gdb_stdlog, "Expanding symtab of %s\n", buf); + if (dwarf_read_debug >= debug_print_threshold) + fprintf_unfiltered (gdb_stdlog, "Expanding symtab of %s\n", buf); - if (per_cu->is_debug_types) - process_full_type_unit (per_cu->cu, item.pretend_language); - else - process_full_comp_unit (per_cu->cu, item.pretend_language); + if (per_cu->is_debug_types) + process_full_type_unit (cu, item.pretend_language); + else + process_full_comp_unit (cu, item.pretend_language); - if (dwarf_read_debug >= debug_print_threshold) - fprintf_unfiltered (gdb_stdlog, "Done expanding %s\n", buf); + if (dwarf_read_debug >= debug_print_threshold) + fprintf_unfiltered (gdb_stdlog, "Done expanding %s\n", buf); + } } - item.per_cu->queued = 0; + per_cu->queued = 0; dwarf2_per_objfile->per_bfd->queue.pop (); } @@ -9112,7 +9091,8 @@ load_full_comp_unit (dwarf2_per_cu_data *this_cu, { gdb_assert (! this_cu->is_debug_types); - cutu_reader reader (this_cu, per_objfile, NULL, this_cu->cu, skip_partial); + dwarf2_cu *existing_cu = per_objfile->get_cu (this_cu); + cutu_reader reader (this_cu, per_objfile, NULL, existing_cu, skip_partial); if (reader.dummy_p) return; @@ -18693,7 +18673,6 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu) { struct dwarf2_per_objfile *dwarf2_per_objfile = cu->per_objfile; struct objfile *objfile = dwarf2_per_objfile->objfile; - struct dwarf2_per_cu_data *per_cu = NULL; struct partial_die_info *pd = NULL; if (offset_in_dwz == cu->per_cu->is_dwz @@ -18704,7 +18683,6 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu) return { cu, pd }; /* We missed recording what we needed. Load all dies and try again. */ - per_cu = cu->per_cu; } else { @@ -18716,22 +18694,26 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu) sect_offset_str (cu->header.sect_off), sect_offset_str (sect_off), bfd_get_filename (objfile->obfd)); } - per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz, - dwarf2_per_objfile); + dwarf2_per_cu_data *per_cu + = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz, + dwarf2_per_objfile); - if (per_cu->cu == NULL || per_cu->cu->partial_dies == NULL) - load_partial_comp_unit (per_cu, cu->per_objfile, nullptr); + cu = dwarf2_per_objfile->get_cu (per_cu); + if (cu == NULL || cu->partial_dies == NULL) + load_partial_comp_unit (per_cu, dwarf2_per_objfile, nullptr); - per_cu->cu->last_used = 0; - pd = per_cu->cu->find_partial_die (sect_off); + cu = dwarf2_per_objfile->get_cu (per_cu); + + cu->last_used = 0; + pd = cu->find_partial_die (sect_off); } /* If we didn't find it, and not all dies have been loaded, load them all and try again. */ - if (pd == NULL && per_cu->load_all_dies == 0) + if (pd == NULL && cu->per_cu->load_all_dies == 0) { - per_cu->load_all_dies = 1; + cu->per_cu->load_all_dies = 1; /* This is nasty. When we reread the DIEs, somewhere up the call chain THIS_CU->cu may already be in use. So we can't just free it and @@ -18739,9 +18721,9 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu) DIEs alone (which can still be in use, e.g. in scan_partial_symbols), and clobber THIS_CU->cu->partial_dies with the hash table for the new set. */ - load_partial_comp_unit (per_cu, cu->per_objfile, cu); + load_partial_comp_unit (cu->per_cu, dwarf2_per_objfile, cu); - pd = per_cu->cu->find_partial_die (sect_off); + pd = cu->find_partial_die (sect_off); } if (pd == NULL) @@ -18749,7 +18731,7 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu) _("could not find partial DIE %s " "in cache [from module %s]\n"), sect_offset_str (sect_off), bfd_get_filename (objfile->obfd)); - return { per_cu->cu, pd }; + return { cu, pd }; } /* See if we can figure out if the class lives in a namespace. We do @@ -19429,7 +19411,7 @@ dwarf2_read_addr_index (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *dwarf2_per_objfile, unsigned int addr_index) { - struct dwarf2_cu *cu = per_cu->cu; + struct dwarf2_cu *cu = dwarf2_per_objfile->get_cu (per_cu); gdb::optional addr_base; int addr_size; @@ -22270,7 +22252,7 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz, if (maybe_queue_comp_unit (cu, per_cu, dwarf2_per_objfile, cu->language)) load_full_comp_unit (per_cu, dwarf2_per_objfile, false, cu->language); - target_cu = per_cu->cu; + target_cu = dwarf2_per_objfile->get_cu (per_cu); } else if (cu->dies == NULL) { @@ -22330,7 +22312,7 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, struct dwarf2_locexpr_baton retval; struct objfile *objfile = dwarf2_per_objfile->objfile; - dwarf2_cu *cu = per_cu->cu; + dwarf2_cu *cu = dwarf2_per_objfile->get_cu (per_cu); if (cu == nullptr) cu = load_cu (per_cu, dwarf2_per_objfile, false); @@ -22415,7 +22397,7 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, retval.per_objfile = dwarf2_per_objfile; retval.per_cu = cu->per_cu; - age_cached_comp_units (dwarf2_per_objfile); + dwarf2_per_objfile->age_comp_units (); return retval; } @@ -22471,7 +22453,7 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off, enum bfd_endian byte_order; struct objfile *objfile = per_objfile->objfile; - dwarf2_cu *cu = per_cu->cu; + dwarf2_cu *cu = per_objfile->get_cu (per_cu); if (cu == nullptr) cu = load_cu (per_cu, per_objfile, false); @@ -22594,7 +22576,7 @@ dwarf2_fetch_die_type_sect_off (sect_offset sect_off, { struct die_info *die; - dwarf2_cu *cu = per_cu->cu; + dwarf2_cu *cu = per_objfile->get_cu (per_cu); if (cu == nullptr) cu = load_cu (per_cu, per_objfile, false); @@ -22644,7 +22626,7 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type, language_minimal)) read_signatured_type (sig_type, dwarf2_per_objfile); - sig_cu = sig_type->per_cu.cu; + sig_cu = dwarf2_per_objfile->get_cu (&sig_type->per_cu); 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; @@ -22818,11 +22800,11 @@ load_full_type_unit (dwarf2_per_cu_data *per_cu, gdb_assert (per_cu->is_debug_types); sig_type = (struct signatured_type *) per_cu; - gdb_assert (per_cu->cu == NULL); + gdb_assert (per_objfile->get_cu (per_cu) == nullptr); read_signatured_type (sig_type, per_objfile); - gdb_assert (per_cu->cu != NULL); + gdb_assert (per_objfile->get_cu (per_cu) != nullptr); } /* Read in a signatured type and build its CU and DIEs. @@ -22836,7 +22818,7 @@ read_signatured_type (signatured_type *sig_type, struct dwarf2_per_cu_data *per_cu = &sig_type->per_cu; gdb_assert (per_cu->is_debug_types); - gdb_assert (per_cu->cu == NULL); + gdb_assert (per_objfile->get_cu (per_cu) == nullptr); cutu_reader reader (per_cu, per_objfile, nullptr, nullptr, false); @@ -23543,14 +23525,6 @@ dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu, producer_is_codewarrior (false), processing_has_namespace_info (false) { - per_cu->cu = this; -} - -/* Destroy a dwarf2_cu. */ - -dwarf2_cu::~dwarf2_cu () -{ - per_cu->cu = NULL; } /* Initialize basic fields of dwarf_cu CU according to DIE COMP_UNIT_DIE. */ @@ -23574,72 +23548,80 @@ prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die, cu->producer = dwarf2_string_attr (comp_unit_die, DW_AT_producer, cu); } -/* Increase the age counter on each cached compilation unit, and free - any that are too old. */ +/* See read.h. */ -static void -age_cached_comp_units (struct dwarf2_per_objfile *dwarf2_per_objfile) +dwarf2_cu * +dwarf2_per_objfile::get_cu (dwarf2_per_cu_data *per_cu) { - struct dwarf2_per_cu_data *per_cu, **last_chain; + auto it = m_dwarf2_cus.find (per_cu); + if (it == m_dwarf2_cus.end ()) + return nullptr; - dwarf2_clear_marks (dwarf2_per_objfile->per_bfd->read_in_chain); - per_cu = dwarf2_per_objfile->per_bfd->read_in_chain; - while (per_cu != NULL) + return it->second; +} + +/* See read.h. */ + +void +dwarf2_per_objfile::set_cu (dwarf2_per_cu_data *per_cu, dwarf2_cu *cu) +{ + gdb_assert (this->get_cu (per_cu) == nullptr); + + m_dwarf2_cus[per_cu] = cu; +} + +/* See read.h. */ + +void +dwarf2_per_objfile::age_comp_units () +{ + /* Start by clearing all marks. */ + for (auto pair : m_dwarf2_cus) + pair.second->mark = false; + + /* Traverse all CUs, mark them and their dependencies if used recently + enough. */ + for (auto pair : m_dwarf2_cus) { - per_cu->cu->last_used ++; - if (per_cu->cu->last_used <= dwarf_max_cache_age) - dwarf2_mark (per_cu->cu); - per_cu = per_cu->cu->read_in_chain; + dwarf2_cu *cu = pair.second; + + cu->last_used++; + if (cu->last_used <= dwarf_max_cache_age) + dwarf2_mark (cu); } - per_cu = dwarf2_per_objfile->per_bfd->read_in_chain; - last_chain = &dwarf2_per_objfile->per_bfd->read_in_chain; - while (per_cu != NULL) + /* Delete all CUs still not marked. */ + for (auto it = m_dwarf2_cus.begin (); it != m_dwarf2_cus.end ();) { - struct dwarf2_per_cu_data *next_cu; + dwarf2_cu *cu = it->second; - next_cu = per_cu->cu->read_in_chain; - - if (!per_cu->cu->mark) + if (!cu->mark) { - delete per_cu->cu; - *last_chain = next_cu; + delete cu; + it = m_dwarf2_cus.erase (it); } else - last_chain = &per_cu->cu->read_in_chain; - - per_cu = next_cu; + it++; } } -/* Remove a single compilation unit from the cache. */ +/* See read.h. */ -static void -free_one_cached_comp_unit (dwarf2_per_cu_data *target_per_cu, - dwarf2_per_objfile *dwarf2_per_objfile) +void +dwarf2_per_objfile::remove_cu (dwarf2_per_cu_data *per_cu) { - struct dwarf2_per_cu_data *per_cu, **last_chain; - - per_cu = dwarf2_per_objfile->per_bfd->read_in_chain; - last_chain = &dwarf2_per_objfile->per_bfd->read_in_chain; - while (per_cu != NULL) - { - struct dwarf2_per_cu_data *next_cu; + auto it = m_dwarf2_cus.find (per_cu); + if (it == m_dwarf2_cus.end ()) + return; - next_cu = per_cu->cu->read_in_chain; + delete it->second; - if (per_cu == target_per_cu) - { - delete per_cu->cu; - per_cu->cu = NULL; - *last_chain = next_cu; - break; - } - else - last_chain = &per_cu->cu->read_in_chain; + m_dwarf2_cus.erase (it); +} - per_cu = next_cu; - } +dwarf2_per_objfile::~dwarf2_per_objfile () +{ + remove_all_cus (); } /* A set of CU "per_cu" pointer, DIE offset, and GDB type pointer. @@ -23841,27 +23823,30 @@ dwarf2_add_dependence (struct dwarf2_cu *cu, /* Subroutine of dwarf2_mark to pass to htab_traverse. Set the mark field in every compilation unit in the - cache that we must keep because we are keeping CU. */ + cache that we must keep because we are keeping CU. + + DATA is the dwarf2_per_objfile object in which to look up CUs. */ static int dwarf2_mark_helper (void **slot, void *data) { - struct dwarf2_per_cu_data *per_cu; - - per_cu = (struct dwarf2_per_cu_data *) *slot; + 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->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 (per_cu->cu == NULL) + if (cu == nullptr) return 1; - if (per_cu->cu->mark) + if (cu->mark) return 1; - per_cu->cu->mark = true; - if (per_cu->cu->dependencies != NULL) - htab_traverse (per_cu->cu->dependencies, dwarf2_mark_helper, NULL); + cu->mark = true; + + if (cu->dependencies != nullptr) + htab_traverse (cu->dependencies, dwarf2_mark_helper, per_objfile); return 1; } @@ -23874,19 +23859,11 @@ dwarf2_mark (struct dwarf2_cu *cu) { if (cu->mark) return; + cu->mark = true; - if (cu->dependencies != NULL) - htab_traverse (cu->dependencies, dwarf2_mark_helper, NULL); -} -static void -dwarf2_clear_marks (struct dwarf2_per_cu_data *per_cu) -{ - while (per_cu) - { - per_cu->cu->mark = false; - per_cu = per_cu->cu->read_in_chain; - } + if (cu->dependencies != nullptr) + htab_traverse (cu->dependencies, dwarf2_mark_helper, cu->per_objfile); } /* Trivial hash function for partial_die_info: the hash value of a DIE diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h index b75be312217..996cf55af22 100644 --- a/gdb/dwarf2/read.h +++ b/gdb/dwarf2/read.h @@ -43,6 +43,7 @@ struct tu_stats int nr_all_type_units_reallocs; }; +struct dwarf2_cu; struct dwarf2_debug_sections; struct dwarf2_per_cu_data; struct mapped_index; @@ -115,9 +116,6 @@ struct dwarf2_per_bfd TU. */ signatured_type *get_tu (int index); - /* Free all cached compilation units. */ - void free_cached_comp_units (); - /* A convenience function to allocate a dwarf2_per_cu_data. The returned object has its "index" field set properly. The object is allocated on the dwarf2_per_bfd obstack. */ @@ -189,10 +187,6 @@ public: are doing. */ struct tu_stats tu_stats {}; - /* A chain of compilation units that are currently read in, so that - they can be freed later. */ - dwarf2_per_cu_data *read_in_chain = NULL; - /* A table mapping DW_AT_dwo_name values to struct dwo_file objects. This is NULL if the table hasn't been allocated yet. */ htab_up dwo_files; @@ -303,6 +297,8 @@ struct dwarf2_per_objfile : objfile (objfile), per_bfd (per_bfd) {} + ~dwarf2_per_objfile (); + /* Return pointer to string at .debug_line_str offset as read from BUF. BUF is assumed to be in a compilation unit described by CU_HEADER. Return *BYTES_READ_PTR count of bytes read from BUF. */ @@ -344,6 +340,22 @@ struct dwarf2_per_objfile UNSIGNED_P controls if the integer is unsigned or not. */ struct type *int_type (int size_in_bytes, bool unsigned_p) const; + /* Get the dwarf2_cu matching PER_CU for this objfile. */ + dwarf2_cu *get_cu (dwarf2_per_cu_data *per_cu); + + /* Set the dwarf2_cu matching PER_CU for this objfile. */ + void set_cu (dwarf2_per_cu_data *per_cu, dwarf2_cu *cu); + + /* Remove/free the dwarf2_cu matching PER_CU for this objfile. */ + void remove_cu (dwarf2_per_cu_data *per_cu); + + /* Free all cached compilation units. */ + void remove_all_cus (); + + /* Increase the age counter on each CU compilation unit and free + any that are too old. */ + void age_comp_units (); + /* Back link. */ struct objfile *objfile; @@ -372,6 +384,10 @@ private: /* Map from signatured types to the corresponding struct type. */ std::unordered_map m_type_map; + + /* Map from the objfile-independent dwarf2_per_cu_data instances to the + corresponding objfile-dependent dwarf2_cu instances. */ + std::unordered_map m_dwarf2_cus; }; /* Get the dwarf2_per_objfile associated to OBJFILE. */ @@ -455,11 +471,6 @@ struct dwarf2_per_cu_data not the DWO file. */ struct dwarf2_section_info *section; - /* Set to non-NULL iff this CU is currently loaded. When it gets freed out - of the CU cache it gets reset to NULL again. This is left as NULL for - dummy CUs (a CU header, but nothing else). */ - struct dwarf2_cu *cu; - /* The unit type of this CU. */ enum dwarf_unit_type unit_type; -- 2.39.2