Skip to content

Commit cb04d33

Browse files
jeffreytan81jeffreytan81
and
jeffreytan81
authored
Improve namespace lookup using .debug_names parent chain (#110062)
## Summary This PR is a continuation of #108907 by using `.debug_names` parent chain faster lookup for namespaces. ## Implementation Similar to #108907. This PR adds a new API: `GetNamespacesWithParents` in `DWARFIndex` base class. The API performs the same function as `GetNamespaces()` with additional filtering using parents `CompilerDeclContext`. A default implementation is given in `DWARFIndex` class which parses debug info and performs the matching. In the `DebugNameDWARFIndex` override, parents `CompilerDeclContext` is cross checked with parent chain in `.debug_names` for much faster filtering before fallback to base implementation for final filtering. ## Performance Results For the same benchmark used in #108907, this PR improves: 48s => 28s --------- Co-authored-by: jeffreytan81 <jeffreytan@fb.com>
1 parent 0d94c7b commit cb04d33

File tree

5 files changed

+85
-12
lines changed

5 files changed

+85
-12
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,19 @@ bool DWARFIndex::ProcessTypeDIEMatchQuery(
151151
return true;
152152
return callback(die);
153153
}
154+
155+
void DWARFIndex::GetNamespacesWithParents(
156+
ConstString name, const CompilerDeclContext &parent_decl_ctx,
157+
llvm::function_ref<bool(DWARFDIE die)> callback) {
158+
GetNamespaces(name, [&](DWARFDIE die) {
159+
return ProcessNamespaceDieMatchParents(parent_decl_ctx, die, callback);
160+
});
161+
}
162+
163+
bool DWARFIndex::ProcessNamespaceDieMatchParents(
164+
const CompilerDeclContext &parent_decl_ctx, DWARFDIE die,
165+
llvm::function_ref<bool(DWARFDIE die)> callback) {
166+
if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die))
167+
return true;
168+
return callback(die);
169+
}

lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h

+11
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ class DWARFIndex {
7171
virtual void
7272
GetTypesWithQuery(TypeQuery &query,
7373
llvm::function_ref<bool(DWARFDIE die)> callback);
74+
/// Get namespace DIEs whose base name match \param name with \param
75+
/// parent_decl_ctx in its decl parent chain. A base implementation
76+
/// is provided. Specializations should override this if they are able to
77+
/// provide a faster implementation.
78+
virtual void
79+
GetNamespacesWithParents(ConstString name,
80+
const CompilerDeclContext &parent_decl_ctx,
81+
llvm::function_ref<bool(DWARFDIE die)> callback);
7482
virtual void
7583
GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
7684
const CompilerDeclContext &parent_decl_ctx,
@@ -127,6 +135,9 @@ class DWARFIndex {
127135
bool
128136
ProcessTypeDIEMatchQuery(TypeQuery &query, DWARFDIE die,
129137
llvm::function_ref<bool(DWARFDIE die)> callback);
138+
bool ProcessNamespaceDieMatchParents(
139+
const CompilerDeclContext &parent_decl_ctx, DWARFDIE die,
140+
llvm::function_ref<bool(DWARFDIE die)> callback);
130141
};
131142
} // namespace dwarf
132143
} // namespace lldb_private::plugin

lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp

+54-10
Original file line numberDiff line numberDiff line change
@@ -368,9 +368,10 @@ void DebugNamesDWARFIndex::GetFullyQualifiedType(
368368
continue;
369369
}
370370

371-
if (SameParentChain(parent_names, *parent_chain) &&
372-
!ProcessEntry(entry, callback))
373-
return;
371+
if (SameParentChain(parent_names, *parent_chain)) {
372+
if (!ProcessEntry(entry, callback))
373+
return;
374+
}
374375
}
375376
m_fallback.GetFullyQualifiedType(context, callback);
376377
}
@@ -554,17 +555,60 @@ void DebugNamesDWARFIndex::GetTypesWithQuery(
554555
continue;
555556
}
556557

557-
if (WithinParentChain(parent_contexts, *parent_chain) &&
558-
!ProcessEntry(entry, [&](DWARFDIE die) {
559-
// After .debug_names filtering still sending to base class for
560-
// further filtering before calling the callback.
561-
return ProcessTypeDIEMatchQuery(query, die, callback);
562-
}))
563-
return;
558+
if (WithinParentChain(parent_contexts, *parent_chain)) {
559+
if (!ProcessEntry(entry, [&](DWARFDIE die) {
560+
// After .debug_names filtering still sending to base class for
561+
// further filtering before calling the callback.
562+
return ProcessTypeDIEMatchQuery(query, die, callback);
563+
}))
564+
// If the callback returns false, we're done.
565+
return;
566+
}
564567
}
565568
m_fallback.GetTypesWithQuery(query, callback);
566569
}
567570

571+
void DebugNamesDWARFIndex::GetNamespacesWithParents(
572+
ConstString name, const CompilerDeclContext &parent_decl_ctx,
573+
llvm::function_ref<bool(DWARFDIE die)> callback) {
574+
std::vector<lldb_private::CompilerContext> parent_contexts =
575+
parent_decl_ctx.GetCompilerContext();
576+
llvm::SmallVector<CompilerContext> parent_named_contexts;
577+
std::copy_if(parent_contexts.rbegin(), parent_contexts.rend(),
578+
std::back_inserter(parent_named_contexts),
579+
[](const CompilerContext &ctx) { return !ctx.name.IsEmpty(); });
580+
for (const DebugNames::Entry &entry :
581+
m_debug_names_up->equal_range(name.GetStringRef())) {
582+
lldb_private::dwarf::Tag entry_tag = entry.tag();
583+
if (entry_tag == DW_TAG_namespace ||
584+
entry_tag == DW_TAG_imported_declaration) {
585+
std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
586+
getParentChain(entry);
587+
if (!parent_chain) {
588+
// Fallback: use the base class implementation.
589+
if (!ProcessEntry(entry, [&](DWARFDIE die) {
590+
return ProcessNamespaceDieMatchParents(parent_decl_ctx, die,
591+
callback);
592+
}))
593+
return;
594+
continue;
595+
}
596+
597+
if (WithinParentChain(parent_named_contexts, *parent_chain)) {
598+
if (!ProcessEntry(entry, [&](DWARFDIE die) {
599+
// After .debug_names filtering still sending to base class for
600+
// further filtering before calling the callback.
601+
return ProcessNamespaceDieMatchParents(parent_decl_ctx, die,
602+
callback);
603+
}))
604+
// If the callback returns false, we're done.
605+
return;
606+
}
607+
}
608+
}
609+
m_fallback.GetNamespacesWithParents(name, parent_decl_ctx, callback);
610+
}
611+
568612
void DebugNamesDWARFIndex::GetFunctions(
569613
const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
570614
const CompilerDeclContext &parent_decl_ctx,

lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ class DebugNamesDWARFIndex : public DWARFIndex {
5555
void
5656
GetTypesWithQuery(TypeQuery &query,
5757
llvm::function_ref<bool(DWARFDIE die)> callback) override;
58-
58+
void GetNamespacesWithParents(
59+
ConstString name, const CompilerDeclContext &parent_decl_ctx,
60+
llvm::function_ref<bool(DWARFDIE die)> callback) override;
5961
void GetFunctions(const Module::LookupInfo &lookup_info,
6062
SymbolFileDWARF &dwarf,
6163
const CompilerDeclContext &parent_decl_ctx,

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2900,7 +2900,7 @@ SymbolFileDWARF::FindNamespace(ConstString name,
29002900
if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
29012901
return namespace_decl_ctx;
29022902

2903-
m_index->GetNamespaces(name, [&](DWARFDIE die) {
2903+
m_index->GetNamespacesWithParents(name, parent_decl_ctx, [&](DWARFDIE die) {
29042904
if (!DIEInDeclContext(parent_decl_ctx, die, only_root_namespaces))
29052905
return true; // The containing decl contexts don't match
29062906

0 commit comments

Comments
 (0)