[PATCH 11/14] Split type_unit_group

Tom Tromey
2020-02-15T16:55:01Z

type_unit_group has links to the compunit_symtab and other symtabs.
However, once this object is shared across objfiles, this will no
longer be ok.

This patch introduces a new type_unit_unshareable and arranges to
store a map from type unit groups to type_unit_unshareable objects on
the DWARF unshareable object.

2020-02-15 Tom Tromey <tom@tromey.com>

* dwarf2/read.h (struct type_unit_unshareable): New.
(struct dwarf2_unshareable) <type_units>: New member.
* dwarf2/read.c (struct type_unit_group) <compunit_symtab,
num_symtabs, symtabs>: Remove; move to type_unit_unshareable.
(get_type_unit_group_unshareable): New function.
(process_full_type_unit, dwarf2_cu::setup_type_unit_groups)
(dwarf2_cu::setup_type_unit_groups): Use type_unit_unshareable.
---
gdb/ChangeLog | 10 ++++++++
gdb/dwarf2/read.c | 65 +++++++++++++++++++++++++----------------------
gdb/dwarf2/read.h | 30 ++++++++++++++++++++++
3 files changed, 74 insertions(+), 31 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index f86034f2273..d1c5bee1109 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -580,27 +580,8 @@ struct type_unit_group
and is deleted afterwards and not used again. */
std::vector<signatured_type *> *tus;

- /* The compunit symtab.
- Type units in a group needn't all be defined in the same source file,
- so we create an essentially anonymous symtab as the compunit symtab. */
- struct compunit_symtab *compunit_symtab;
-
/* The data used to construct the hash key. */
struct stmt_list_hash hash;
-
- /* The number of symtabs from the line header.
- The value here must match line_header.num_file_names. */
- unsigned int num_symtabs;
-
- /* The symbol tables for this TU (obtained from the files listed in
- DW_AT_stmt_list).
- WARNING: The order of entries here must match the order of entries
- in the line header. After the first TU using this type_unit_group, the
- line header for the subsequent TUs is recreated from this. This is done
- because we need to use the same symtabs for each TU using the same
- DW_AT_stmt_list value. Also note that symtabs may be repeated here,
- there's no guarantee the line header doesn't have duplicate entries. */
- struct symtab **symtabs;
};

/* These sections are what may appear in a (real or virtual) DWO file. */
@@ -9507,6 +9488,22 @@ rust_union_quirks (struct dwarf2_cu *cu)
cu->rust_unions.clear ();
}

+/* Get the type_unit_unshareable corresponding to TU_GROUP. If one
+ does not exist, create it. */
+
+static type_unit_unshareable *
+get_type_unit_group_unshareable (dwarf2_per_objfile *dwarf2_per_objfile,
+ type_unit_group *tu_group)
+{
+ auto iter = dwarf2_per_objfile->unshareable->type_units.find (tu_group);
+ if (iter != dwarf2_per_objfile->unshareable->type_units.end ())
+ return iter->second.get ();
+ std::unique_ptr<type_unit_unshareable> uniq (new type_unit_unshareable);
+ type_unit_unshareable *result = uniq.get ();
+ dwarf2_per_objfile->unshareable->type_units[tu_group] = std::move (uniq);
+ return result;
+}
+
/* Return the symtab for PER_CU. This works properly regardless of
whether we're using the index or psymtabs. */

@@ -9776,11 +9773,14 @@ process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
If this is the first TU to use this symtab, complete the construction
of it with end_expandable_symtab. Otherwise, complete the addition of
this TU's symbols to the existing symtab. */
- if (sig_type->type_unit_group->compunit_symtab == NULL)
+ type_unit_unshareable *tu_unshare
+ = get_type_unit_group_unshareable (dwarf2_per_objfile,
+ sig_type->type_unit_group);
+ if (tu_unshare->compunit_symtab == NULL)
{
buildsym_compunit *builder = cu->get_builder ();
cust = builder->end_expandable_symtab (0, SECT_OFF_TEXT (objfile));
- sig_type->type_unit_group->compunit_symtab = cust;
+ tu_unshare->compunit_symtab = cust;

if (cust != NULL)
{
@@ -9796,7 +9796,7 @@ process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
else
{
cu->get_builder ()->augment_type_symtab ();
- cust = sig_type->type_unit_group->compunit_symtab;
+ cust = tu_unshare->compunit_symtab;
}

gdb::optional<compunit_symtab *> &symtab
@@ -10930,7 +10930,10 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
do it again, we could fake it and just recreate the part we need
(file name,index -> symtab mapping). If data shows this optimization
is useful we can do it then. */
- first_time = tu_group->compunit_symtab == NULL;
+ struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile;
+ type_unit_unshareable *tu_unshare
+ = get_type_unit_group_unshareable (dwarf2_per_objfile, tu_group);
+ first_time = tu_unshare->compunit_symtab == NULL;

/* We have to handle the case of both a missing DW_AT_stmt_list or bad
debug info. */
@@ -10946,9 +10949,9 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
start_symtab ("", NULL, 0);
else
{
- gdb_assert (tu_group->symtabs == NULL);
+ gdb_assert (tu_unshare->symtabs == NULL);
gdb_assert (m_builder == nullptr);
- struct compunit_symtab *cust = tu_group->compunit_symtab;
+ struct compunit_symtab *cust = tu_unshare->compunit_symtab;
m_builder.reset (new struct buildsym_compunit
(COMPUNIT_OBJFILE (cust), "",
COMPUNIT_DIRNAME (cust),
@@ -10970,9 +10973,9 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
process_full_type_unit still needs to know if this is the first
time. */

- tu_group->num_symtabs = line_header->file_names_size ();
- tu_group->symtabs = XNEWVEC (struct symtab *,
- line_header->file_names_size ());
+ tu_unshare->num_symtabs = line_header->file_names_size ();
+ tu_unshare->symtabs = XNEWVEC (struct symtab *,
+ line_header->file_names_size ());

auto &file_names = line_header->file_names ();
for (i = 0; i < file_names.size (); ++i)
@@ -10993,13 +10996,13 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
}

fe.symtab = b->get_current_subfile ()->symtab;
- tu_group->symtabs[i] = fe.symtab;
+ tu_unshare->symtabs[i] = fe.symtab;
}
}
else
{
gdb_assert (m_builder == nullptr);
- struct compunit_symtab *cust = tu_group->compunit_symtab;
+ struct compunit_symtab *cust = tu_unshare->compunit_symtab;
m_builder.reset (new struct buildsym_compunit
(COMPUNIT_OBJFILE (cust), "",
COMPUNIT_DIRNAME (cust),
@@ -11010,7 +11013,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
for (i = 0; i < file_names.size (); ++i)
{
file_entry &fe = file_names[i];
- fe.symtab = tu_group->symtabs[i];
+ fe.symtab = tu_unshare->symtabs[i];
}
}

diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index bef37e969d3..8b2e8703aa0 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -47,6 +47,7 @@ struct dwarf2_per_cu_data;
struct mapped_index;
struct mapped_debug_names;
struct signatured_type;
+struct type_unit_group;

/* One item on the queue of compilation units to read in full symbols
for. */
@@ -66,6 +67,30 @@ struct dwarf2_queue_item
enum language pretend_language;
};

+/* This is the per-objfile data associated with a type_unit_group. */
+
+struct type_unit_unshareable
+{
+ /* The compunit symtab.
+ Type units in a group needn't all be defined in the same source file,
+ so we create an essentially anonymous symtab as the compunit symtab. */
+ struct compunit_symtab *compunit_symtab = nullptr;
+
+ /* The number of symtabs from the line header.
+ The value here must match line_header.num_file_names. */
+ unsigned int num_symtabs = 0;
+
+ /* The symbol tables for this TU (obtained from the files listed in
+ DW_AT_stmt_list).
+ WARNING: The order of entries here must match the order of entries
+ in the line header. After the first TU using this type_unit_group, the
+ line header for the subsequent TUs is recreated from this. This is done
+ because we need to use the same symtabs for each TU using the same
+ DW_AT_stmt_list value. Also note that symtabs may be repeated here,
+ there's no guarantee the line header doesn't have duplicate entries. */
+ struct symtab **symtabs = nullptr;
+};
+
/* Some DWARF data cannot (currently) be shared across objfiles. Such
data is stored in this object.

@@ -86,6 +111,11 @@ struct dwarf2_unshareable
/* Hold the corresponding compunit_symtab for each CU or TU. This
is indexed by dwarf2_per_cu_data::index. */
std::vector<gdb::optional<compunit_symtab *>> symtabs;
+
+ /* Map from a type unit group to the corresponding unshared
+ structure. */
+ std::unordered_map<type_unit_group *, std::unique_ptr<type_unit_unshareable>>
+ type_units;
};

/* Collection of data recorded per objfile.
--
2.17.2