forked from OSchip/llvm-project
Introduce a fast path for the ASTReader's name lookup within a
DeclContext. When the DeclContext is of a kind that can only be defined once and never updated, we limit the search to the module file that conatins the lookup table. Provides a 15% speedup in one modules-heavy source file. llvm-svn: 173050
This commit is contained in:
parent
031b69d8df
commit
9f78289055
|
@ -1311,7 +1311,7 @@ public:
|
||||||
|
|
||||||
/// \brief Retrieve the module file that owns the given declaration, or NULL
|
/// \brief Retrieve the module file that owns the given declaration, or NULL
|
||||||
/// if the declaration is not from a module file.
|
/// if the declaration is not from a module file.
|
||||||
ModuleFile *getOwningModuleFile(Decl *D);
|
ModuleFile *getOwningModuleFile(const Decl *D);
|
||||||
|
|
||||||
/// \brief Returns the source location for the decl \p ID.
|
/// \brief Returns the source location for the decl \p ID.
|
||||||
SourceLocation getSourceLocationForDeclID(serialization::GlobalDeclID ID);
|
SourceLocation getSourceLocationForDeclID(serialization::GlobalDeclID ID);
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "ASTCommon.h"
|
#include "ASTCommon.h"
|
||||||
|
#include "clang/AST/DeclObjC.h"
|
||||||
#include "clang/Basic/IdentifierTable.h"
|
#include "clang/Basic/IdentifierTable.h"
|
||||||
#include "clang/Serialization/ASTDeserializationListener.h"
|
#include "clang/Serialization/ASTDeserializationListener.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
|
@ -85,3 +86,60 @@ unsigned serialization::ComputeHash(Selector Sel) {
|
||||||
R = llvm::HashString(II->getName(), R);
|
R = llvm::HashString(II->getName(), R);
|
||||||
return R;
|
return R;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Decl *serialization::getDefinitiveDeclContext(const DeclContext *DC) {
|
||||||
|
switch (DC->getDeclKind()) {
|
||||||
|
// These entities may have multiple definitions.
|
||||||
|
case Decl::TranslationUnit:
|
||||||
|
case Decl::Namespace:
|
||||||
|
case Decl::LinkageSpec:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// C/C++ tag types can only be defined in one place.
|
||||||
|
case Decl::Enum:
|
||||||
|
case Decl::Record:
|
||||||
|
if (const TagDecl *Def = cast<TagDecl>(DC)->getDefinition())
|
||||||
|
return Def;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// FIXME: These can be defined in one place... except special member
|
||||||
|
// functions and out-of-line definitions.
|
||||||
|
case Decl::CXXRecord:
|
||||||
|
case Decl::ClassTemplateSpecialization:
|
||||||
|
case Decl::ClassTemplatePartialSpecialization:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Each function, method, and block declaration is its own DeclContext.
|
||||||
|
case Decl::Function:
|
||||||
|
case Decl::CXXMethod:
|
||||||
|
case Decl::CXXConstructor:
|
||||||
|
case Decl::CXXDestructor:
|
||||||
|
case Decl::CXXConversion:
|
||||||
|
case Decl::ObjCMethod:
|
||||||
|
case Decl::Block:
|
||||||
|
// Objective C categories, category implementations, and class
|
||||||
|
// implementations can only be defined in one place.
|
||||||
|
case Decl::ObjCCategory:
|
||||||
|
case Decl::ObjCCategoryImpl:
|
||||||
|
case Decl::ObjCImplementation:
|
||||||
|
return cast<Decl>(DC);
|
||||||
|
|
||||||
|
case Decl::ObjCProtocol:
|
||||||
|
if (const ObjCProtocolDecl *Def
|
||||||
|
= cast<ObjCProtocolDecl>(DC)->getDefinition())
|
||||||
|
return Def;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// FIXME: These are defined in one place, but properties in class extensions
|
||||||
|
// end up being back-patched into the main interface. See
|
||||||
|
// Sema::HandlePropertyInClassExtension for the offending code.
|
||||||
|
case Decl::ObjCInterface:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Unhandled DeclContext in AST reader");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -58,6 +58,18 @@ TypeID MakeTypeID(ASTContext &Context, QualType T, IdxForTypeTy IdxForType) {
|
||||||
|
|
||||||
unsigned ComputeHash(Selector Sel);
|
unsigned ComputeHash(Selector Sel);
|
||||||
|
|
||||||
|
/// \brief Retrieve the "definitive" declaration that provides all of the
|
||||||
|
/// visible entries for the given declaration context, if there is one.
|
||||||
|
///
|
||||||
|
/// The "definitive" declaration is the only place where we need to look to
|
||||||
|
/// find information about the declarations within the given declaration
|
||||||
|
/// context. For example, C++ and Objective-C classes, C structs/unions, and
|
||||||
|
/// Objective-C protocols, categories, and extensions are all defined in a
|
||||||
|
/// single place in the source code, so they have definitive declarations
|
||||||
|
/// associated with them. C++ namespaces, on the other hand, can have
|
||||||
|
/// multiple definitions.
|
||||||
|
const Decl *getDefinitiveDeclContext(const DeclContext *DC);
|
||||||
|
|
||||||
} // namespace serialization
|
} // namespace serialization
|
||||||
|
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|
|
@ -4971,7 +4971,7 @@ bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID,
|
||||||
return &M == I->second;
|
return &M == I->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleFile *ASTReader::getOwningModuleFile(Decl *D) {
|
ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) {
|
||||||
if (!D->isFromASTFile())
|
if (!D->isFromASTFile())
|
||||||
return 0;
|
return 0;
|
||||||
GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID());
|
GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID());
|
||||||
|
@ -5307,6 +5307,27 @@ namespace {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the "definitive" module file for the definition of the
|
||||||
|
/// given declaration context, if there is one.
|
||||||
|
///
|
||||||
|
/// The "definitive" module file is the only place where we need to look to
|
||||||
|
/// find information about the declarations within the given declaration
|
||||||
|
/// context. For example, C++ and Objective-C classes, C structs/unions, and
|
||||||
|
/// Objective-C protocols, categories, and extensions are all defined in a
|
||||||
|
/// single place in the source code, so they have definitive module files
|
||||||
|
/// associated with them. C++ namespaces, on the other hand, can have
|
||||||
|
/// definitions in multiple different module files.
|
||||||
|
///
|
||||||
|
/// Note: this needs to be kept in sync with ASTWriter::AddedVisibleDecl's
|
||||||
|
/// NDEBUG checking.
|
||||||
|
static ModuleFile *getDefinitiveModuleFileFor(const DeclContext *DC,
|
||||||
|
ASTReader &Reader) {
|
||||||
|
if (const Decl *D = getDefinitiveDeclContext(DC))
|
||||||
|
return Reader.getOwningModuleFile(D);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
DeclContext::lookup_result
|
DeclContext::lookup_result
|
||||||
ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
|
ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
|
||||||
DeclarationName Name) {
|
DeclarationName Name) {
|
||||||
|
@ -5335,7 +5356,16 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
|
DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
|
||||||
ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor);
|
|
||||||
|
// If we can definitively determine which module file to look into,
|
||||||
|
// only look there. Otherwise, look in all module files.
|
||||||
|
ModuleFile *Definitive;
|
||||||
|
if (Contexts.size() == 1 &&
|
||||||
|
(Definitive = getDefinitiveModuleFileFor(DC, *this))) {
|
||||||
|
DeclContextNameLookupVisitor::visit(*Definitive, &Visitor);
|
||||||
|
} else {
|
||||||
|
ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor);
|
||||||
|
}
|
||||||
++NumVisibleDeclContextsRead;
|
++NumVisibleDeclContextsRead;
|
||||||
SetExternalVisibleDeclsForName(DC, Name, Decls);
|
SetExternalVisibleDeclsForName(DC, Name, Decls);
|
||||||
return const_cast<DeclContext*>(DC)->lookup(Name);
|
return const_cast<DeclContext*>(DC)->lookup(Name);
|
||||||
|
|
|
@ -4780,6 +4780,7 @@ void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
|
||||||
if (!(!D->isFromASTFile() && cast<Decl>(DC)->isFromASTFile()))
|
if (!(!D->isFromASTFile() && cast<Decl>(DC)->isFromASTFile()))
|
||||||
return; // Not a source decl added to a DeclContext from PCH.
|
return; // Not a source decl added to a DeclContext from PCH.
|
||||||
|
|
||||||
|
assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!");
|
||||||
AddUpdatedDeclContext(DC);
|
AddUpdatedDeclContext(DC);
|
||||||
UpdatingVisibleDecls.push_back(D);
|
UpdatingVisibleDecls.push_back(D);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue