abbrev_table_cache () = default;
DISABLE_COPY_AND_ASSIGN (abbrev_table_cache);
+ abbrev_table_cache (abbrev_table_cache &&) = default;
+ abbrev_table_cache &operator= (abbrev_table_cache &&) = default;
+
/* Find an abbrev table coming from the abbrev section SECTION at
offset OFFSET. Return the table, or nullptr if it has not yet
been registered. */
/* See cooked-index-worker.h. */
+void
+cooked_index_worker_result::emit_complaints_and_exceptions
+ (gdb::unordered_set<gdb_exception> &seen_exceptions)
+{
+ gdb_assert (is_main_thread ());
+
+ re_emit_complaints (m_complaints);
+
+ /* Only show a given exception a single time. */
+ for (auto &one_exc : m_exceptions)
+ if (seen_exceptions.insert (one_exc).second)
+ exception_print (gdb_stderr, one_exc);
+}
+
+/* See cooked-index-worker.h. */
+
void
cooked_index_worker::start ()
{
/* Only show a given exception a single time. */
gdb::unordered_set<gdb_exception> seen_exceptions;
for (auto &one_result : m_results)
- {
- re_emit_complaints (std::get<1> (one_result));
- for (auto &one_exc : std::get<2> (one_result))
- if (seen_exceptions.insert (one_exc).second)
- exception_print (gdb_stderr, one_exc);
- }
+ one_result.emit_complaints_and_exceptions (seen_exceptions);
print_stats ();
cooked_index_worker_result ();
DISABLE_COPY_AND_ASSIGN (cooked_index_worker_result);
+ cooked_index_worker_result (cooked_index_worker_result &&) = default;
+ cooked_index_worker_result &operator= (cooked_index_worker_result &&)
+ = default;
+
/* Return the current abbrev table_cache. */
const abbrev_table_cache &get_abbrev_table_cache () const
{ return m_abbrev_table_cache; }
name, parent_entry, per_cu);
}
+ /* Overload that allows the language to be specified. */
+ cooked_index_entry *add (sect_offset die_offset, enum dwarf_tag tag,
+ cooked_index_flag flags, enum language lang,
+ const char *name,
+ cooked_index_entry_ref parent_entry,
+ dwarf2_per_cu *per_cu)
+ {
+ return m_shard->add (die_offset, tag, flags, lang,
+ name, parent_entry, per_cu);
+ }
+
/* Install the current addrmap into the shard being constructed,
then transfer ownership of the index to the caller. */
- cooked_index_shard_up release ()
+ cooked_index_shard_up release_shard ()
{
m_shard->install_addrmap (&m_addrmap);
+ /* This isn't needed any more. */
+ m_addrmap.clear ();
return std::move (m_shard);
}
return &m_parent_map;
}
- /* Return the parent_map that is currently being created. Ownership
- is passed to the caller. */
- parent_map release_parent_map ()
+ /* Add an exception to the list of exceptions caught while reading.
+ These are passed forward and printed by the main thread. */
+ void note_error (gdb_exception &&except)
{
- return std::move (m_parent_map);
+ m_exceptions.push_back (std::move (except));
}
+ /* Called when the thread using this object is done with its work.
+ This stores any complaints for later emission, and it clears some
+ data that won't be needed again. */
+ void done_reading (complaint_collection &&complaints)
+ {
+ /* Hang on to the complaints. */
+ m_complaints = std::move (complaints);
+ /* Discard things that are no longer needed. */
+ m_reader_hash.clear ();
+ }
+
+ /* Called to emit any stored complaints or exceptions. This can
+ only be called on the main thread. */
+ void emit_complaints_and_exceptions
+ (gdb::unordered_set<gdb_exception> &seen_exceptions);
+
private:
/* The abbrev table cache used by this indexer. */
abbrev_table_cache m_abbrev_table_cache;
/* A writeable addrmap being constructed by this scanner. */
addrmap_mutable m_addrmap;
+
+ /* The issued complaints. Only set after done_reading is
+ called. */
+ complaint_collection m_complaints;
+
+ /* Exceptions that we're storing to emit later. */
+ std::vector<gdb_exception> m_exceptions;
};
/* The possible states of the index. See the explanatory comment
virtual void print_stats ()
{ }
- /* Each thread returns a tuple holding a cooked index, any collected
- complaints, a vector of errors that should be printed, and a
- parent map.
-
- The errors are retained because GDB's I/O system is not
- thread-safe. run_on_main_thread could be used, but that would
- mean the messages are printed after the prompt, which looks
- weird. */
- using result_type = std::tuple<cooked_index_shard_up,
- complaint_collection,
- std::vector<gdb_exception>,
- parent_map>;
-
/* The per-objfile object. */
dwarf2_per_objfile *m_per_objfile;
/* Result of each worker task. */
- std::vector<result_type> m_results;
- /* Any warnings emitted. This is not in 'result_type' because (for
- the time being at least), it's only needed in do_reading, not in
- every worker. Note that deferred_warnings uses gdb_stderr in its
- constructor, and this should only be done from the main thread.
- This is enforced in the cooked_index_worker constructor. */
+ std::vector<cooked_index_worker_result> m_results;
+ /* Any warnings emitted. For the time being at least, this only
+ needed in do_reading, not in every worker. Note that
+ deferred_warnings uses gdb_stderr in its constructor, and this
+ should only be done from the main thread. This is enforced in
+ the cooked_index_worker constructor. */
deferred_warnings m_warnings;
/* A map of all parent maps. Used during finalization to fix up
gdb::unordered_map<ULONGEST, index_val> abbrev_map;
- /* Even though the scanning of .debug_names and creation of the cooked index
- entries is done serially, we create multiple shards so that the
- finalization step can be parallelized. The shards are filled in a round
- robin fashion. */
- std::vector<cooked_index_shard_up> shards;
+ /* Even though the scanning of .debug_names and creation of the
+ cooked index entries is done serially, we create multiple shards
+ so that the finalization step can be parallelized. The shards
+ are filled in a round robin fashion. It's convenient to use a
+ result object rather than an actual shard. */
+ std::vector<cooked_index_worker_result> indices;
/* Next shard to insert an entry in. */
int next_shard = 0;
if (per_cu != nullptr)
{
*result
- = shards[next_shard]->add (die_offset, (dwarf_tag) indexval.dwarf_tag,
+ = indices[next_shard].add (die_offset, (dwarf_tag) indexval.dwarf_tag,
flags, lang, name, nullptr, per_cu);
++next_shard;
- if (next_shard == shards.size ())
+ if (next_shard == indices.size ())
next_shard = 0;
entry_pool_offsets_to_entries.emplace (offset_in_entry_pool, *result);
cooked_index_worker_debug_names::do_reading ()
{
complaint_interceptor complaint_handler;
- std::vector<gdb_exception> exceptions;
+
try
{
m_map.scan_all_names ();
}
- catch (const gdb_exception &exc)
+ catch (gdb_exception &exc)
{
- exceptions.push_back (std::move (exc));
+ /* Arbitrarily put all exceptions into the first result. */
+ m_map.indices[0].note_error (std::move (exc));
}
- m_results.emplace_back (nullptr,
- complaint_handler.release (),
- std::move (exceptions),
- parent_map ());
+ std::vector<cooked_index_shard_up> shards;
+ bool first = true;
+ for (auto &iter : m_map.indices)
+ {
+ if (first)
+ {
+ iter.done_reading (complaint_handler.release ());
+ first = false;
+ }
+ else
+ iter.done_reading ({});
+ shards.push_back (iter.release_shard ());
+ m_all_parents_map.add_map (*iter.get_parent_map ());
+ }
+
+ m_results = std::move (m_map.indices);
dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd;
cooked_index *table
/* Note that this code never uses IS_PARENT_DEFERRED, so it is safe
to pass nullptr here. */
- table->set_contents (std::move (m_map.shards), &m_warnings, nullptr);
+ table->set_contents (std::move (shards), &m_warnings, nullptr);
bfd_thread_cleanup ();
}
}
per_bfd->debug_aranges.read (per_objfile->objfile);
- addrmap_mutable addrmap;
+
+ /* There is a single address map for the whole index (coming from
+ .debug_aranges). We only need to install it into a single shard
+ for it to get searched by cooked_index. So, we make the first
+ result object here, so we can store the addrmap, then move it
+ into place later. */
+ cooked_index_worker_result first;
deferred_warnings warnings;
read_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges,
- &addrmap, &warnings);
+ first.get_addrmap (), &warnings);
warnings.emit ();
const auto n_workers
= std::max<std::size_t> (gdb::thread_pool::g_thread_pool->thread_count (),
1);
- /* Create as many index shard as there are worker threads. */
- for (int i = 0; i < n_workers; ++i)
- map.shards.emplace_back (std::make_unique<cooked_index_shard> ());
-
- /* There is a single address map for the whole index (coming from
- .debug_aranges). We only need to install it into a single shard for it to
- get searched by cooked_index. */
- map.shards[0]->install_addrmap (&addrmap);
+ /* Create as many index shard as there are worker threads,
+ preserving the first one. */
+ map.indices.push_back (std::move (first));
+ map.indices.resize (n_workers);
auto cidn = (std::make_unique<cooked_index_worker_debug_names>
(per_objfile, std::move (map)));
};
void
-cooked_index_worker_debug_info::process_cus (size_t task_number, unit_iterator first,
- unit_iterator end)
+cooked_index_worker_debug_info::process_cus (size_t task_number,
+ unit_iterator first,
+ unit_iterator end)
{
SCOPE_EXIT { bfd_thread_cleanup (); };
}
catch (gdb_exception &except)
{
- errors.push_back (std::move (except));
+ thread_storage.note_error (std::move (except));
}
}
- m_results[task_number] = result_type (thread_storage.release (),
- complaint_handler.release (),
- std::move (errors),
- thread_storage.release_parent_map ());
+ thread_storage.done_reading (complaint_handler.release ());
+ m_results[task_number] = std::move (thread_storage);
}
void
for (auto &one_result : m_results)
{
- shards.push_back (std::move (std::get<0> (one_result)));
- m_all_parents_map.add_map (std::get<3> (one_result));
+ shards.push_back (one_result.release_shard ());
+ m_all_parents_map.add_map (*one_result.get_parent_map ());
}
/* This has to wait until we read the CUs, we need the list of DWOs. */
process_skeletonless_type_units (m_per_objfile, &m_index_storage);
- shards.push_back (m_index_storage.release ());
+ shards.push_back (m_index_storage.release_shard ());
shards.shrink_to_fit ();
- m_all_parents_map.add_map (m_index_storage.release_parent_map ());
+ m_all_parents_map.add_map (*m_index_storage.get_parent_map ());
dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd;
cooked_index *table