Performance: Add a set of visited SymbolFiles to the other FindFiles variant.

This is basically the same bug as in r260434.

SymbolFileDWARF::FindTypes has exponential worst-case when digging
through dependency DAG of .pcm files because each object file and .pcm
file may depend on an already-visited .pcm file, which may again have
dependencies. Fixed here by carrying a set of already visited
SymbolFiles around.

rdar://problem/56993424

Differential Revision: https://reviews.llvm.org/D70106
This commit is contained in:
Adrian Prantl 2019-11-12 09:25:59 -08:00
parent 54a9b4c02f
commit 3b73dcdc96
14 changed files with 49 additions and 24 deletions

View File

@ -429,7 +429,11 @@ public:
/// This behaves like the other FindTypes method but allows to
/// specify a DeclContext and a language for the type being searched
/// for.
///
/// \param searched_symbol_files
/// Prevents one file from being visited multiple times.
void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types);
lldb::TypeSP FindFirstType(const SymbolContext &sc,

View File

@ -193,9 +193,14 @@ public:
TypeMap &types);
/// Find types specified by a CompilerContextPattern.
/// \param languages Only return results in these languages.
virtual void FindTypes(llvm::ArrayRef<CompilerContext> pattern,
LanguageSet languages, TypeMap &types);
/// \param languages
/// Only return results in these languages.
/// \param searched_symbol_files
/// Prevents one file from being visited multiple times.
virtual void
FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types);
virtual void
GetMangledNamesForFunction(const std::string &scope_qualified_name,

View File

@ -1006,12 +1006,14 @@ void Module::FindTypes(
}
}
void Module::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
LanguageSet languages, TypeMap &types) {
void Module::FindTypes(
llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
if (SymbolFile *symbols = GetSymbolFile())
symbols->FindTypes(pattern, languages, types);
symbols->FindTypes(pattern, languages, searched_symbol_files, types);
}
SymbolFile *Module::GetSymbolFile(bool can_create, Stream *feedback_strm) {

View File

@ -307,8 +307,9 @@ void SymbolFileBreakpad::FindTypes(
uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeMap &types) {}
void SymbolFileBreakpad::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
LanguageSet languages, TypeMap &types) {}
void SymbolFileBreakpad::FindTypes(
llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {}
void SymbolFileBreakpad::AddSymbols(Symtab &symtab) {
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);

View File

@ -112,6 +112,7 @@ public:
TypeMap &types) override;
void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeMap &types) override;
llvm::Expected<TypeSystem &>

View File

@ -150,7 +150,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) {
// The type in the Clang module must have the same language as the current CU.
LanguageSet languages;
languages.Insert(die.GetCU()->GetLanguageType());
dwo_module_sp->GetSymbolFile()->FindTypes(decl_context, languages, dwo_types);
llvm::DenseSet<SymbolFile *> searched_symbol_files;
dwo_module_sp->GetSymbolFile()->FindTypes(decl_context, languages,
searched_symbol_files, dwo_types);
if (dwo_types.Empty()) {
if (!IsClangModuleFwdDecl(die))
return TypeSP();
@ -161,8 +163,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) {
for (const auto &name_module : sym_file.getExternalTypeModules()) {
if (!name_module.second)
continue;
name_module.second->GetSymbolFile()->FindTypes(decl_context,
languages, dwo_types);
name_module.second->GetSymbolFile()->FindTypes(
decl_context, languages, searched_symbol_files, dwo_types);
if (dwo_types.GetSize())
break;
}

View File

@ -2366,12 +2366,10 @@ void SymbolFileDWARF::FindTypes(
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
// Make sure we haven't already searched this SymbolFile before...
if (searched_symbol_files.count(this))
// Make sure we haven't already searched this SymbolFile before.
if (!searched_symbol_files.insert(this).second)
return;
searched_symbol_files.insert(this);
DWARFDebugInfo *info = DebugInfo();
if (!info)
return;
@ -2453,8 +2451,13 @@ void SymbolFileDWARF::FindTypes(
}
}
void SymbolFileDWARF::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
LanguageSet languages, TypeMap &types) {
void SymbolFileDWARF::FindTypes(
llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {
// Make sure we haven't already searched this SymbolFile before.
if (!searched_symbol_files.insert(this).second)
return;
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
if (pattern.empty())
return;

View File

@ -190,6 +190,7 @@ public:
void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern,
lldb_private::LanguageSet languages,
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types) override;
void GetTypes(lldb_private::SymbolContextScope *sc_scope,

View File

@ -1259,8 +1259,9 @@ void SymbolFileNativePDB::FindTypes(
FindTypesByName(name.GetStringRef(), max_matches, types);
}
void SymbolFileNativePDB::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
LanguageSet languages, TypeMap &types) {}
void SymbolFileNativePDB::FindTypes(
llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {}
void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name,
uint32_t max_matches,

View File

@ -131,6 +131,7 @@ public:
TypeMap &types) override;
void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeMap &types) override;
llvm::Expected<TypeSystem &>

View File

@ -1562,9 +1562,10 @@ void SymbolFilePDB::FindTypesByName(
}
}
void SymbolFilePDB::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
LanguageSet languages,
lldb_private::TypeMap &types) {}
void SymbolFilePDB::FindTypes(
llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types) {}
void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol,
uint32_t type_mask,

View File

@ -134,6 +134,7 @@ public:
void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern,
lldb_private::LanguageSet languages,
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types) override;
void FindTypesByRegex(const lldb_private::RegularExpression &regex,

View File

@ -134,7 +134,9 @@ void SymbolFile::FindTypes(
TypeMap &types) {}
void SymbolFile::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
LanguageSet languages, TypeMap &types) {}
LanguageSet languages,
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeMap &types) {}
void SymbolFile::AssertModuleLock() {
// The code below is too expensive to leave enabled in release builds. It's

View File

@ -529,7 +529,7 @@ Error opts::symbols::findTypes(lldb_private::Module &Module) {
Symfile.FindTypes(ConstString(Name), ContextPtr, UINT32_MAX, SearchedFiles,
Map);
else
Module.FindTypes(parseCompilerContext(), languages, Map);
Module.FindTypes(parseCompilerContext(), languages, SearchedFiles, Map);
outs() << formatv("Found {0} types:\n", Map.GetSize());
StreamString Stream;