jankratochvil updated this revision to Diff 159192.

Repository:
  rLLDB 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 &regex,
               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,34 @@
 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::deque<const DWARFUnit *> todo({&cu});
+  std::unordered_set<dw_offset_t> found;
+  while (!todo.empty()) {
+    const DWARFUnit *work = todo.front();
+    todo.pop_front();
+    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;
+      todo.push_back(new_work);
+    }
+  }
+  m_set.globals.FindAllEntriesForCompileUnit(found, offsets);
 }
 
 void ManualDWARFIndex::GetObjCMethods(ConstString class_name,
@@ -546,3 +574,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
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to