jankratochvil created this revision.
jankratochvil added reviewers: labath, clayborg.
Herald added a subscriber: JDevlieghere.
Rarely (`GlobalVariablesTestCase-test_c_global_variables`) a DIE can be only in
PU (PartialUnit), that is if a DIE is a static constant variable
(`g_file_static_int`) so that it has no location address.
Patch has been optimized for minimal code added despite the performance is
suboptimal for DWZ files. It also should not affect non-DWZ files performance.
All DWZ patches are also applied in: git clone -b dwz
git://git.jankratochvil.net/lldb
https://reviews.llvm.org/D49969
Files:
source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
source/Plugins/SymbolFile/DWARF/NameToDIE.h
Index: source/Plugins/SymbolFile/DWARF/NameToDIE.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/NameToDIE.h
+++ source/Plugins/SymbolFile/DWARF/NameToDIE.h
@@ -11,6 +11,7 @@
#define SymbolFileDWARF_NameToDIE_h_
#include <functional>
+#include <unordered_set>
#include "DIERef.h"
#include "lldb/Core/UniqueCStringMap.h"
@@ -39,9 +40,16 @@
size_t Find(const lldb_private::RegularExpression ®ex,
DIEArray &info_array) const;
+ size_t FindAllEntriesForCompileUnit(
+ std::function<bool(dw_offset_t)> compare, DIEArray &info_array) const;
+
size_t FindAllEntriesForCompileUnit(dw_offset_t cu_offset,
DIEArray &info_array) const;
+ size_t FindAllEntriesForCompileUnit(
+ const std::unordered_set<dw_offset_t> &cu_offsets,
+ DIEArray &info_array) const;
+
void
ForEach(std::function<bool(lldb_private::ConstString name,
const DIERef &die_ref)> const
Index: source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
+++ source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -39,18 +39,33 @@
return m_map.GetValues(regex, info_array);
}
-size_t NameToDIE::FindAllEntriesForCompileUnit(dw_offset_t cu_offset,
- DIEArray &info_array) const {
+size_t NameToDIE::FindAllEntriesForCompileUnit(
+ std::function<bool(dw_offset_t)> compare, DIEArray &info_array) const {
const size_t initial_size = info_array.size();
const uint32_t size = m_map.GetSize();
for (uint32_t i = 0; i < size; ++i) {
const DIERef &die_ref = m_map.GetValueAtIndexUnchecked(i);
- if (cu_offset == die_ref.cu_offset)
+ if (compare(die_ref.cu_offset))
info_array.push_back(die_ref);
}
return info_array.size() - initial_size;
}
+size_t NameToDIE::FindAllEntriesForCompileUnit(dw_offset_t cu_offset,
+ DIEArray &info_array) const {
+ return FindAllEntriesForCompileUnit([cu_offset](dw_offset_t offset) {
+ return offset == cu_offset;
+ }, info_array);
+}
+
+size_t NameToDIE::FindAllEntriesForCompileUnit(
+ const std::unordered_set<dw_offset_t> &cu_offsets,
+ DIEArray &info_array) const {
+ return FindAllEntriesForCompileUnit([&cu_offsets](dw_offset_t offset) {
+ return cu_offsets.count(offset) != 0;
+ }, info_array);
+}
+
void NameToDIE::Dump(Stream *s) {
const uint32_t size = m_map.GetSize();
for (uint32_t i = 0; i < size; ++i) {
Index: source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
+++ source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
@@ -11,8 +11,12 @@
#define LLDB_MANUALDWARFINDEX_H
#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
#include "Plugins/SymbolFile/DWARF/NameToDIE.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/Support/RWMutex.h"
+
+#include <unordered_map>
namespace lldb_private {
class ManualDWARFIndex : public DWARFIndex {
@@ -22,6 +26,8 @@
: DWARFIndex(module), m_debug_info(debug_info),
m_units_to_avoid(std::move(units_to_avoid)) {}
+ ~ManualDWARFIndex() override;
+
void Preload() override { Index(); }
void GetGlobalVariables(ConstString basename, DIEArray &offsets) override;
@@ -68,7 +74,19 @@
/// Which dwarf units should we skip while building the index.
llvm::DenseSet<dw_offset_t> m_units_to_avoid;
+ void AddExtractedPU(DWARFUnit &importer, DWARFUnit &importee);
+
IndexSet m_set;
+
+ // All DW_TAG_partial_unit's extracted for Index-ing this DW_TAG_compile_unit.
+ struct ExtractedForUnit {
+ // FIXME: The pointer is already contained in the value; but we wound need
+ // a combination of DenseSet::insert_as and DenseSet::try_emplace.
+ std::unordered_map<const DWARFUnit *, DWARFUnit::ScopedExtractDIEs> m_map;
+ llvm::sys::RWMutex m_mutex;
+ };
+ std::unordered_map<const DWARFUnit *, ExtractedForUnit> m_extracted_pu;
+ llvm::sys::RWMutex m_extracted_pu_mutex;
};
} // namespace lldb_private
Index: source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -409,6 +409,7 @@
break;
}
import_cu->SetMainCU(&main_unit);
+ AddExtractedPU(unit, *import_cu);
IndexUnit(*import_cu,set);
}
break;
@@ -433,7 +434,39 @@
void ManualDWARFIndex::GetGlobalVariables(const DWARFUnit &cu,
DIEArray &offsets) {
Index();
- m_set.globals.FindAllEntriesForCompileUnit(cu.GetOffset(), offsets);
+ if (m_extracted_pu.empty()) {
+ m_set.globals.FindAllEntriesForCompileUnit(cu.GetOffset(), offsets);
+ return;
+ }
+ // FIXME: It would be more memory and CPU effective to pack it as compact
+ // read-only data structure at the end of indexing.
+ std::unordered_set<const DWARFUnit *> todo;
+ std::unordered_set<dw_offset_t> found;
+ todo.insert(&cu);
+ while (!todo.empty()) {
+ const DWARFUnit *work = *todo.cbegin();
+ todo.erase(todo.cbegin());
+ if (!found.insert(work->GetOffset()).second) {
+ m_module.GetObjectFile()->GetModule()->ReportError(
+ "CU 0x%8.8" PRIx32 " leads to duplicate DW_TAG_imported_unit "
+ "for PU 0x%8.8" PRIx32,
+ cu.GetOffset(), work->GetOffset());
+ continue;
+ }
+ const auto it = m_extracted_pu.find(work);
+ if (it == m_extracted_pu.cend())
+ continue;
+ const ExtractedForUnit &for_unit = it->second;
+ for (const auto &pair : for_unit.m_map) {
+ const DWARFUnit *new_work = pair.first;
+ if (!todo.insert(new_work).second)
+ m_module.GetObjectFile()->GetModule()->ReportError(
+ "CU 0x%8.8" PRIx32 " leads to duplicate DW_TAG_imported_unit "
+ "from PU 0x%8.8" PRIx32 " to PU 0x%8.8" PRIx32,
+ cu.GetOffset(), work->GetOffset(), new_work->GetOffset());
+ }
+ }
+ m_set.globals.FindAllEntriesForCompileUnit(found, offsets);
}
void ManualDWARFIndex::GetObjCMethods(ConstString class_name,
@@ -546,3 +579,27 @@
s.Printf("\nNamespaces:\n");
m_set.namespaces.Dump(&s);
}
+
+void ManualDWARFIndex::AddExtractedPU(
+ DWARFUnit &importer, DWARFUnit &importee) {
+ ExtractedForUnit *for_importer;
+ {
+ llvm::sys::ScopedWriter guard_all(m_extracted_pu_mutex);
+ for_importer = &m_extracted_pu[&importer];
+ }
+ llvm::sys::ScopedWriter guard_for_unit(for_importer->m_mutex);
+ // It may be already present as we do not clear m_map for ClearDIEsRWLocked()
+ // as it is required during its later use.
+ for_importer->m_map.emplace(&importee, &importee);
+}
+
+// We could try to call ClearDIEsRWLocked() on an already destroyed DWARFUnit.
+ManualDWARFIndex::~ManualDWARFIndex() {
+ for (auto &all_pair : m_extracted_pu) {
+ ExtractedForUnit &for_unit = all_pair.second;
+ for (auto &unit_pair : for_unit.m_map) {
+ DWARFUnit::ScopedExtractDIEs &scoped = unit_pair.second;
+ scoped.Disable();
+ }
+ }
+}
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits