public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Simon Marchi <simon.marchi@efficios.com>
To: gdb-patches@sourceware.org
Cc: Simon Marchi <simon.marchi@efficios.com>
Subject: [PATCH v2 40/42] Replace dwarf2_per_cu_data::cu backlink with per-objfile map
Date: Tue, 12 May 2020 17:18:22 -0400	[thread overview]
Message-ID: <20200512211824.6834-41-simon.marchi@efficios.com> (raw)
In-Reply-To: <20200512210913.5593-1-simon.marchi@efficios.com>

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) <free_cached_comp_units>: Remove,
	move to dwarf2_per_objfile.
	<read_in_chain>: Remove.
	(struct dwarf2_per_objfile) <get_cu, set_cu, remove_cu,
	remove_all_cus, age_comp_units>: New methods.
	<m_dwarf2_cus>: New member.
	(struct dwarf2_per_cu_data) <cu>: Remove.
	* dwarf2/read.c (struct dwarf2_cu) <read_in_chain>: 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.
---
 gdb/dwarf2/read.c | 355 ++++++++++++++++++++++------------------------
 gdb/dwarf2/read.h |  35 +++--
 2 files changed, 189 insertions(+), 201 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index acc148a87d5..9bc19a089b0 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 @@ struct dwarf2_cu
      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 @@ class free_cached_comp_units
 
   ~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
@@ -6427,7 +6404,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);
@@ -6885,8 +6862,9 @@ cutu_reader::init_tu_and_read_dwo_dies (dwarf2_per_cu_data *this_cu,
     }
   else
     {
-      /* If and 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 ();
     }
@@ -6975,8 +6953,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 ();
     }
@@ -7116,16 +7095,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 ());
     }
 }
 
@@ -7163,7 +7136,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
@@ -7525,8 +7498,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);
 
@@ -7555,10 +7527,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.  */
@@ -8913,7 +8885,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;
     }
@@ -8929,9 +8903,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;
     }
 
@@ -8958,47 +8933,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 ();
     }
 
@@ -9074,7 +9053,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;
 
@@ -18653,7 +18633,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
@@ -18664,7 +18643,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
     {
@@ -18676,22 +18654,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
@@ -18699,9 +18681,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)
@@ -18709,7 +18691,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
@@ -19389,7 +19371,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<ULONGEST> addr_base;
   int addr_size;
 
@@ -22230,7 +22212,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)
     {
@@ -22290,7 +22272,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);
 
@@ -22375,7 +22357,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;
 }
@@ -22431,7 +22413,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);
 
@@ -22554,7 +22536,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);
 
@@ -22604,7 +22586,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;
@@ -22778,11 +22760,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.
@@ -22796,7 +22778,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);
 
@@ -23503,14 +23485,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.  */
@@ -23534,72 +23508,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.
@@ -23801,27 +23783,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;
 }
@@ -23834,19 +23819,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 @@ struct dwarf2_per_bfd
      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 @@ struct dwarf2_per_objfile
 
   /* Map from signatured types to the corresponding struct type.  */
   std::unordered_map<signatured_type *, struct type *> m_type_map;
+
+  /* Map from the objfile-independent dwarf2_per_cu_data instances to the
+     corresponding objfile-dependent dwarf2_cu instances.  */
+  std::unordered_map<dwarf2_per_cu_data *, dwarf2_cu *> 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.26.2


  parent reply	other threads:[~2020-05-12 21:19 UTC|newest]

Thread overview: 92+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-12 21:08 [PATCH v2 00/42] Share DWARF partial symtabs between objfiles Simon Marchi
2020-05-12 21:08 ` [PATCH v2 01/42] Introduce dwarf2_per_objfile::obstack Simon Marchi
2020-05-12 21:08 ` [PATCH v2 02/42] Add "objfile" parameter to two partial_symtab methods Simon Marchi
2020-05-12 21:08 ` [PATCH v2 03/42] Add dwarf2_per_cu_data::index Simon Marchi
2020-05-12 21:08 ` [PATCH v2 04/42] Add dwarf2_per_objfile member to DWARF batons Simon Marchi
2020-05-12 21:08 ` [PATCH v2 05/42] Split dwarf2_per_objfile into dwarf2_per_objfile and dwarf2_per_bfd Simon Marchi
2020-05-12 21:08 ` [PATCH v2 06/42] Remove symtab links from dwarf2_psymtab and dwarf2_per_cu_quick_data Simon Marchi
2020-05-12 21:08 ` [PATCH v2 07/42] Move die_type_hash to dwarf2_per_objfile Simon Marchi
2020-05-12 21:08 ` [PATCH v2 08/42] Add dwarf2_per_objfile field to dwarf2_cu Simon Marchi
2020-05-12 21:08 ` [PATCH v2 09/42] Remove reference to dwarf2_per_cu_data::dwarf2_per_objfile in dw2_do_instantiate_symtab Simon Marchi
2020-05-12 21:11 ` [PATCH v2 10/42] Remove dwarf2_cu->per_cu->dwarf2_per_objfile references Simon Marchi
2020-05-12 21:11 ` [PATCH v2 11/42] Add dwarf2_per_bfd field to dwarf2_per_cu_data Simon Marchi
2020-05-12 21:11 ` [PATCH v2 12/42] Make dwarf2_get_dwz_file take a dwarf2_per_bfd Simon Marchi
2020-05-12 21:11 ` [PATCH v2 13/42] Use bfd_get_filename instead of objfile_name in lookup_dwo_unit Simon Marchi
2020-05-12 21:11 ` [PATCH v2 14/42] Add dwarf2_per_objfile parameter to cutu_reader's constructors Simon Marchi
2020-05-12 21:11 ` [PATCH v2 15/42] Make queue_and_load_dwo_tu receive a dwarf2_cu Simon Marchi
2020-05-22 20:45   ` Tom Tromey
2020-05-25 19:10     ` Simon Marchi
2020-05-12 21:11 ` [PATCH v2 16/42] Remove dwarf2_per_cu_data::dwarf2_per_objfile reference in cutu_reader::keep Simon Marchi
2020-05-12 21:11 ` [PATCH v2 17/42] Add dwarf2_per_objfile parameter to create_partial_symtab Simon Marchi
2020-05-12 21:11 ` [PATCH v2 18/42] Add dwarf2_per_objfile parameter to recursively_compute_inclusions Simon Marchi
2020-05-12 21:11 ` [PATCH v2 19/42] Add dwarf2_per_objfile parameter to process_full_{comp, type}_unit Simon Marchi
2020-05-12 21:12 ` [PATCH v2 20/42] Pass dwarf2_cu objects to dwo-related functions, instead of dwarf2_per_cu_data Simon Marchi
2020-05-12 21:12 ` [PATCH v2 21/42] Remove reference to dwarf2_per_cu_data::dwarf2_per_objfile in queue_and_load_all_dwo_tus Simon Marchi
2020-05-12 21:12 ` [PATCH v2 22/42] Move int type methods out of dwarf2_per_cu_data Simon Marchi
2020-05-12 21:12 ` [PATCH v2 23/42] Add dwarf2_per_objfile to dwarf_expr_context and dwarf2_frame_cache Simon Marchi
2020-05-22 21:04   ` Tom Tromey
2020-05-25 19:50     ` Simon Marchi
2020-05-28  1:44       ` Simon Marchi
2020-05-12 21:12 ` [PATCH v2 24/42] Remove dwarf2_per_cu_data::text_offset Simon Marchi
2020-05-12 21:12 ` [PATCH v2 25/42] Add dwarf2_per_objfile parameter to dwarf2_read_addr_index Simon Marchi
2020-05-12 21:12 ` [PATCH v2 26/42] Add dwarf2_per_objfile parameter to allocate_piece_closure Simon Marchi
2020-05-12 21:12 ` [PATCH v2 27/42] Add dwarf2_per_objfile parameters to dwarf2_fetch_* functions Simon Marchi
2020-05-12 21:12 ` [PATCH v2 28/42] Remove dwarf2_per_cu_data::objfile () Simon Marchi
2020-05-27 16:27   ` Tom de Vries
2020-05-27 16:52     ` Tom de Vries
2020-05-27 20:03     ` Simon Marchi
2020-05-27 21:08       ` Tom de Vries
2020-05-27 21:55         ` Simon Marchi
2020-05-27 22:16           ` Simon Marchi
2020-05-28  2:00             ` Simon Marchi
2020-05-28 13:05               ` Tom de Vries
2020-05-28 15:33                 ` Simon Marchi
2020-05-28 16:24                   ` Christian Biesinger
2020-05-28 16:52                     ` Simon Marchi
2020-05-28 19:49                       ` Simon Marchi
2020-05-12 21:12 ` [PATCH v2 29/42] Add dwarf2_per_objfile parameter to free_one_cached_comp_unit Simon Marchi
2020-05-12 21:17 ` [PATCH v2 30/42] Add dwarf2_per_objfile parameter to get_die_type_at_offset Simon Marchi
2020-05-12 21:17 ` [PATCH v2 31/42] Remove leftover references to dwarf2_per_cu_data::dwarf2_per_objfile Simon Marchi
2020-05-12 21:17 ` [PATCH v2 32/42] Remove dwarf2_per_cu_data::dwarf2_per_objfile Simon Marchi
2020-05-12 21:17 ` [PATCH v2 33/42] Split type_unit_group Simon Marchi
2020-05-13  9:54   ` Tom de Vries
2020-05-13 15:06     ` Simon Marchi
2020-05-12 21:17 ` [PATCH v2 34/42] Move signatured_type::type to unshareable object Simon Marchi
2020-05-12 21:17 ` [PATCH v2 35/42] Pass dwarf2_per_bfd instead of dwarf2_per_objfile to some index-related functions Simon Marchi
2020-05-12 21:17 ` [PATCH v2 36/42] Pass dwarf2_cu to process_full_{comp,type}_unit Simon Marchi
2020-05-12 21:17 ` [PATCH v2 37/42] Make load_cu return the loaded dwarf2_cu Simon Marchi
2020-05-12 21:17 ` [PATCH v2 38/42] Add comp_unit_head to dwarf2_per_cu_data Simon Marchi
2020-05-12 21:17 ` [PATCH v2 39/42] Pass existing_cu object to cutu_reader Simon Marchi
2020-05-22 20:57   ` Tom Tromey
2020-05-25 19:10     ` Simon Marchi
2020-05-12 21:18 ` Simon Marchi [this message]
2020-05-12 21:18 ` [PATCH v2 41/42] Make mapped_debug_names independent of objfile Simon Marchi
2020-05-22 21:01   ` Tom Tromey
2020-05-25 19:53     ` Simon Marchi
2020-05-12 21:18 ` [PATCH v2 42/42] Share DWARF partial symtabs Simon Marchi
2020-05-13 10:17 ` [PATCH v2 00/42] Share DWARF partial symtabs between objfiles Tom de Vries
2020-05-13 15:46   ` Simon Marchi
2020-05-22 21:02     ` Tom Tromey
2020-05-25 19:53       ` Simon Marchi
2020-05-13 14:52 ` Simon Marchi
2020-05-22 21:07 ` Tom Tromey
2020-05-23 12:24   ` Pedro Alves
2020-05-25 19:56     ` Simon Marchi
2020-05-26 11:17       ` Pedro Alves
2020-05-26 15:35         ` Simon Marchi
2020-05-26 21:34           ` Simon Marchi
2020-05-27  5:08             ` Simon Marchi
2020-05-27 14:53               ` Simon Marchi
2020-05-27 15:51                 ` Simon Marchi
2020-05-29 10:23                   ` Tom de Vries
2020-05-29 12:55                     ` Tom de Vries
2020-05-31  4:16                     ` Simon Marchi
2020-05-31 14:22                       ` Tom de Vries
2020-06-02 21:27                         ` Simon Marchi
2020-06-04 17:55                           ` Tom de Vries
2020-06-04 18:04                             ` Simon Marchi
2020-06-10  3:43                               ` Simon Marchi
2020-06-12  3:25                                 ` Tom Tromey
2020-05-27 14:50 ` [PATCH v2 41.5/42] Move line_header_hash to dwarf2_per_objfile Simon Marchi
2020-05-27 15:07   ` Tom Tromey
2020-05-27 15:10     ` Simon Marchi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200512211824.6834-41-simon.marchi@efficios.com \
    --to=simon.marchi@efficios.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).