forked from OSchip/llvm-project
Optimize unqualified/global name lookup in modules by introducing a
generational scheme for identifiers that avoids searching the hash tables of a given module more than once for a given identifier. Previously, loading any new module invalidated all of the previous lookup results for all identifiers, causing us to perform the lookups repeatedly. llvm-svn: 148412
This commit is contained in:
parent
c3cc110bb4
commit
4fc9f3e819
|
@ -579,6 +579,10 @@ private:
|
|||
/// \brief Whether to disable the use of stat caches in AST files.
|
||||
bool DisableStatCache;
|
||||
|
||||
/// \brief The current "generation" of the module file import stack, which
|
||||
/// indicates how many separate module file load operations have occurred.
|
||||
unsigned CurrentGeneration;
|
||||
|
||||
/// \brief Mapping from switch-case IDs in the chain to switch-case statements
|
||||
///
|
||||
/// Statements usually don't have IDs, but switch cases need them, so that the
|
||||
|
@ -652,6 +656,9 @@ private:
|
|||
/// loaded once the recursive loading has completed.
|
||||
std::deque<PendingIdentifierInfo> PendingIdentifierInfos;
|
||||
|
||||
/// \brief The generation number of
|
||||
llvm::DenseMap<IdentifierInfo *, unsigned> IdentifierGeneration;
|
||||
|
||||
/// \brief Contains declarations and definitions that will be
|
||||
/// "interesting" to the ASTConsumer, when we get that AST consumer.
|
||||
///
|
||||
|
@ -1432,6 +1439,9 @@ public:
|
|||
/// \brief Update an out-of-date identifier.
|
||||
virtual void updateOutOfDateIdentifier(IdentifierInfo &II);
|
||||
|
||||
/// \brief Note that this identifier is up-to-date.
|
||||
void markIdentifierUpToDate(IdentifierInfo *II);
|
||||
|
||||
/// \brief Read the macro definition corresponding to this iterator
|
||||
/// into the unread macro record offsets table.
|
||||
void LoadMacroDefinition(
|
||||
|
|
|
@ -57,7 +57,7 @@ struct DeclContextInfo {
|
|||
/// other modules.
|
||||
class ModuleFile {
|
||||
public:
|
||||
ModuleFile(ModuleKind Kind);
|
||||
ModuleFile(ModuleKind Kind, unsigned Generation);
|
||||
~ModuleFile();
|
||||
|
||||
// === General information ===
|
||||
|
@ -72,6 +72,9 @@ public:
|
|||
/// user.
|
||||
bool DirectlyImported;
|
||||
|
||||
/// \brief The generation of which this module file is a part.
|
||||
unsigned Generation;
|
||||
|
||||
/// \brief The memory buffer that stores the data associated with
|
||||
/// this AST file.
|
||||
llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
|
||||
|
|
|
@ -95,6 +95,8 @@ public:
|
|||
/// \param ImportedBy The module that is importing this module, or NULL if
|
||||
/// this module is imported directly by the user.
|
||||
///
|
||||
/// \param Generation The generation in which this module was loaded.
|
||||
///
|
||||
/// \param ErrorStr Will be set to a non-empty string if any errors occurred
|
||||
/// while trying to load the module.
|
||||
///
|
||||
|
@ -102,7 +104,7 @@ public:
|
|||
/// and a boolean indicating whether the module was newly added.
|
||||
std::pair<ModuleFile *, bool>
|
||||
addModule(StringRef FileName, ModuleKind Type, ModuleFile *ImportedBy,
|
||||
std::string &ErrorStr);
|
||||
unsigned Generation, std::string &ErrorStr);
|
||||
|
||||
/// \brief Add an in-memory buffer the list of known buffers
|
||||
void addInMemoryBuffer(StringRef FileName, llvm::MemoryBuffer *Buffer);
|
||||
|
|
|
@ -514,7 +514,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
|
|||
II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));
|
||||
Reader.SetIdentifierInfo(ID, II);
|
||||
II->setIsFromAST();
|
||||
II->setOutOfDate(false);
|
||||
Reader.markIdentifierUpToDate(II);
|
||||
return II;
|
||||
}
|
||||
|
||||
|
@ -540,7 +540,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
|
|||
IdentifierInfo *II = KnownII;
|
||||
if (!II)
|
||||
II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));
|
||||
II->setOutOfDate(false);
|
||||
Reader.markIdentifierUpToDate(II);
|
||||
II->setIsFromAST();
|
||||
|
||||
// Set or check the various bits in the IdentifierInfo structure.
|
||||
|
@ -1560,14 +1560,20 @@ namespace {
|
|||
/// \brief Visitor class used to look up identifirs in an AST file.
|
||||
class IdentifierLookupVisitor {
|
||||
StringRef Name;
|
||||
unsigned PriorGeneration;
|
||||
IdentifierInfo *Found;
|
||||
public:
|
||||
explicit IdentifierLookupVisitor(StringRef Name) : Name(Name), Found() { }
|
||||
IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration)
|
||||
: Name(Name), PriorGeneration(PriorGeneration), Found() { }
|
||||
|
||||
static bool visit(ModuleFile &M, void *UserData) {
|
||||
IdentifierLookupVisitor *This
|
||||
= static_cast<IdentifierLookupVisitor *>(UserData);
|
||||
|
||||
// If we've already searched this module file, skip it now.
|
||||
if (M.Generation <= This->PriorGeneration)
|
||||
return true;
|
||||
|
||||
ASTIdentifierLookupTable *IdTable
|
||||
= (ASTIdentifierLookupTable *)M.IdentifierLookupTable;
|
||||
if (!IdTable)
|
||||
|
@ -1593,7 +1599,24 @@ namespace {
|
|||
}
|
||||
|
||||
void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) {
|
||||
get(II.getName());
|
||||
unsigned PriorGeneration = 0;
|
||||
if (getContext().getLangOptions().Modules)
|
||||
PriorGeneration = IdentifierGeneration[&II];
|
||||
|
||||
IdentifierLookupVisitor Visitor(II.getName(), PriorGeneration);
|
||||
ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);
|
||||
markIdentifierUpToDate(&II);
|
||||
}
|
||||
|
||||
void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) {
|
||||
if (!II)
|
||||
return;
|
||||
|
||||
II->setOutOfDate(false);
|
||||
|
||||
// Update the generation for this identifier.
|
||||
if (getContext().getLangOptions().Modules)
|
||||
IdentifierGeneration[II] = CurrentGeneration;
|
||||
}
|
||||
|
||||
const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) {
|
||||
|
@ -2612,6 +2635,9 @@ void ASTReader::makeModuleVisible(Module *Mod,
|
|||
|
||||
ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
|
||||
ModuleKind Type) {
|
||||
// Bump the generation number.
|
||||
++CurrentGeneration;
|
||||
|
||||
switch(ReadASTCore(FileName, Type, /*ImportedBy=*/0)) {
|
||||
case Failure: return Failure;
|
||||
case IgnorePCH: return IgnorePCH;
|
||||
|
@ -2619,7 +2645,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
|
|||
}
|
||||
|
||||
// Here comes stuff that we only do once the entire chain is loaded.
|
||||
|
||||
|
||||
// Check the predefines buffers.
|
||||
if (!DisableValidation && Type == MK_PCH &&
|
||||
// FIXME: CheckPredefinesBuffers also sets the SuggestedPredefines;
|
||||
|
@ -2635,7 +2661,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
|
|||
IdEnd = PP.getIdentifierTable().end();
|
||||
Id != IdEnd; ++Id)
|
||||
Id->second->setOutOfDate(true);
|
||||
|
||||
|
||||
// Resolve any unresolved module exports.
|
||||
for (unsigned I = 0, N = UnresolvedModuleImportExports.size(); I != N; ++I) {
|
||||
UnresolvedModuleImportExport &Unresolved = UnresolvedModuleImportExports[I];
|
||||
|
@ -2683,7 +2709,7 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName,
|
|||
bool NewModule;
|
||||
std::string ErrorStr;
|
||||
llvm::tie(M, NewModule) = ModuleMgr.addModule(FileName, Type, ImportedBy,
|
||||
ErrorStr);
|
||||
CurrentGeneration, ErrorStr);
|
||||
|
||||
if (!M) {
|
||||
// We couldn't load the module.
|
||||
|
@ -5109,11 +5135,11 @@ void ASTReader::InitializeSema(Sema &S) {
|
|||
}
|
||||
|
||||
IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
|
||||
IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart));
|
||||
IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart),
|
||||
/*PriorGeneration=*/0);
|
||||
ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);
|
||||
IdentifierInfo *II = Visitor.getIdentifierInfo();
|
||||
if (II)
|
||||
II->setOutOfDate(false);
|
||||
markIdentifierUpToDate(II);
|
||||
return II;
|
||||
}
|
||||
|
||||
|
@ -6236,7 +6262,8 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
|
|||
Consumer(0), ModuleMgr(FileMgr.getFileSystemOptions()),
|
||||
RelocatablePCH(false), isysroot(isysroot),
|
||||
DisableValidation(DisableValidation),
|
||||
DisableStatCache(DisableStatCache), NumStatHits(0), NumStatMisses(0),
|
||||
DisableStatCache(DisableStatCache),
|
||||
CurrentGeneration(0), NumStatHits(0), NumStatMisses(0),
|
||||
NumSLocEntriesRead(0), TotalNumSLocEntries(0),
|
||||
NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0),
|
||||
TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0),
|
||||
|
|
|
@ -20,8 +20,8 @@ using namespace clang;
|
|||
using namespace serialization;
|
||||
using namespace reader;
|
||||
|
||||
ModuleFile::ModuleFile(ModuleKind Kind)
|
||||
: Kind(Kind), DirectlyImported(false), SizeInBits(0),
|
||||
ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation)
|
||||
: Kind(Kind), DirectlyImported(false), Generation(Generation), SizeInBits(0),
|
||||
LocalNumSLocEntries(0), SLocEntryBaseID(0),
|
||||
SLocEntryBaseOffset(0), SLocEntryOffsets(0),
|
||||
SLocFileOffsets(0), LocalNumIdentifiers(0),
|
||||
|
|
|
@ -35,7 +35,8 @@ llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) {
|
|||
|
||||
std::pair<ModuleFile *, bool>
|
||||
ModuleManager::addModule(StringRef FileName, ModuleKind Type,
|
||||
ModuleFile *ImportedBy, std::string &ErrorStr) {
|
||||
ModuleFile *ImportedBy, unsigned Generation,
|
||||
std::string &ErrorStr) {
|
||||
const FileEntry *Entry = FileMgr.getFile(FileName);
|
||||
if (!Entry && FileName != "-") {
|
||||
ErrorStr = "file not found";
|
||||
|
@ -47,7 +48,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
|
|||
bool NewModule = false;
|
||||
if (!ModuleEntry) {
|
||||
// Allocate a new module.
|
||||
ModuleFile *New = new ModuleFile(Type);
|
||||
ModuleFile *New = new ModuleFile(Type, Generation);
|
||||
New->FileName = FileName.str();
|
||||
Chain.push_back(New);
|
||||
NewModule = true;
|
||||
|
|
Loading…
Reference in New Issue