[modules] Stop walking all modules when looking for lexical decls for a

DeclContext. These only ever come from the owning module file for the Decl.

llvm-svn: 244285
This commit is contained in:
Richard Smith 2015-08-06 22:07:25 +00:00
parent c2b70bf999
commit 82f8fcda9f
5 changed files with 73 additions and 82 deletions

View File

@ -61,9 +61,6 @@ namespace clang {
/// used for the translation unit declaration.
typedef uint32_t DeclID;
/// \brief a Decl::Kind/DeclID pair.
typedef std::pair<uint32_t, DeclID> KindDeclIDPair;
// FIXME: Turn these into classes so we can have some type safety when
// we go from local ID to global and vice-versa.
typedef DeclID LocalDeclID;

View File

@ -494,6 +494,16 @@ private:
/// \brief Map from a FileID to the file-level declarations that it contains.
llvm::DenseMap<FileID, FileDeclsInfo> FileDeclIDs;
/// \brief An array of lexical contents of a declaration context, as a sequence of
/// Decl::Kind, DeclID pairs.
typedef ArrayRef<llvm::support::unaligned_uint32_t> LexicalContents;
/// \brief Map from a DeclContext to its lexical contents.
llvm::DenseMap<const DeclContext*, LexicalContents> LexicalDecls;
/// \brief Map from the TU to its lexical contents from each module file.
std::vector<std::pair<ModuleFile*, LexicalContents>> TULexicalDecls;
// Updates for visible decls can occur for other contexts than just the
// TU, and when we read those update records, the actual context may not
// be available yet, so have this pending map using the ID as a key. It

View File

@ -52,12 +52,10 @@ enum ModuleKind {
/// \brief Information about the contents of a DeclContext.
struct DeclContextInfo {
DeclContextInfo()
: NameLookupTableData(), LexicalDecls() {}
DeclContextInfo() : NameLookupTableData() {}
llvm::OnDiskIterableChainedHashTable<reader::ASTDeclContextNameLookupTrait>
*NameLookupTableData; // an ASTDeclContextNameLookupTable.
ArrayRef<KindDeclIDPair> LexicalDecls;
};
/// \brief The input file that has been loaded from this AST file, along with

View File

@ -973,9 +973,13 @@ bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M,
return true;
}
M.DeclContextInfos[DC].LexicalDecls = llvm::makeArrayRef(
reinterpret_cast<const KindDeclIDPair *>(Blob.data()),
Blob.size() / sizeof(KindDeclIDPair));
assert(!isa<TranslationUnitDecl>(DC) &&
"expected a TU_UPDATE_LEXICAL record for TU");
// FIXME: Once we remove RewriteDecl, assert that we didn't already have
// lexical decls for this context.
LexicalDecls[DC] = llvm::makeArrayRef(
reinterpret_cast<const llvm::support::unaligned_uint32_t *>(Blob.data()),
Blob.size() / 4);
DC->setHasExternalLexicalStorage(true);
return false;
}
@ -2498,10 +2502,11 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case TU_UPDATE_LEXICAL: {
DeclContext *TU = Context.getTranslationUnitDecl();
DeclContextInfo &Info = F.DeclContextInfos[TU];
Info.LexicalDecls = llvm::makeArrayRef(
reinterpret_cast<const KindDeclIDPair *>(Blob.data()),
static_cast<unsigned int>(Blob.size() / sizeof(KindDeclIDPair)));
LexicalContents Contents(
reinterpret_cast<const llvm::support::unaligned_uint32_t *>(
Blob.data()),
static_cast<unsigned int>(Blob.size() / 4));
TULexicalDecls.push_back(std::make_pair(&F, Contents));
TU->setHasExternalLexicalStorage(true);
break;
}
@ -6175,69 +6180,45 @@ Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) {
return ReadStmtFromStream(*Loc.F);
}
namespace {
class FindExternalLexicalDeclsVisitor {
ASTReader &Reader;
const DeclContext *DC;
llvm::function_ref<bool(Decl::Kind)> IsKindWeWant;
SmallVectorImpl<Decl*> &Decls;
bool PredefsVisited[NUM_PREDEF_DECL_IDS];
public:
FindExternalLexicalDeclsVisitor(
ASTReader &Reader, const DeclContext *DC,
llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
SmallVectorImpl<Decl *> &Decls)
: Reader(Reader), DC(DC), IsKindWeWant(IsKindWeWant), Decls(Decls) {
for (unsigned I = 0; I != NUM_PREDEF_DECL_IDS; ++I)
PredefsVisited[I] = false;
}
static bool visitPostorder(ModuleFile &M, void *UserData) {
return (*static_cast<FindExternalLexicalDeclsVisitor*>(UserData))(M);
}
bool operator()(ModuleFile &M) {
ModuleFile::DeclContextInfosMap::iterator Info =
M.DeclContextInfos.find(DC);
if (Info == M.DeclContextInfos.end() || Info->second.LexicalDecls.empty())
return false;
// Load all of the declaration IDs
for (const KindDeclIDPair &P : Info->second.LexicalDecls) {
if (!IsKindWeWant((Decl::Kind)P.first))
continue;
// Don't add predefined declarations to the lexical context more
// than once.
if (P.second < NUM_PREDEF_DECL_IDS) {
if (PredefsVisited[P.second])
continue;
PredefsVisited[P.second] = true;
}
if (Decl *D = Reader.GetLocalDecl(M, P.second)) {
if (!DC->isDeclInLexicalTraversal(D))
Decls.push_back(D);
}
}
return false;
}
};
}
void ASTReader::FindExternalLexicalDecls(
const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
SmallVectorImpl<Decl *> &Decls) {
// There might be lexical decls in multiple modules, for the TU at
// least. FIXME: Only look in multiple module files in the very rare
// cases where this can actually happen.
FindExternalLexicalDeclsVisitor Visitor(*this, DC, IsKindWeWant, Decls);
ModuleMgr.visitDepthFirst(
nullptr, &FindExternalLexicalDeclsVisitor::visitPostorder, &Visitor);
bool PredefsVisited[NUM_PREDEF_DECL_IDS] = {};
auto Visit = [&] (ModuleFile *M, const LexicalContents &LexicalDecls) {
assert(LexicalDecls.size() % 2 == 0 && "expected an even number of entries");
for (int I = 0, N = LexicalDecls.size(); I != N; I += 2) {
auto K = (Decl::Kind)+LexicalDecls[I];
if (!IsKindWeWant(K))
continue;
auto ID = (serialization::DeclID)+LexicalDecls[I + 1];
// Don't add predefined declarations to the lexical context more
// than once.
if (ID < NUM_PREDEF_DECL_IDS) {
if (PredefsVisited[ID])
continue;
PredefsVisited[ID] = true;
}
if (Decl *D = GetLocalDecl(*M, ID)) {
if (!DC->isDeclInLexicalTraversal(D))
Decls.push_back(D);
}
}
};
if (isa<TranslationUnitDecl>(DC)) {
for (auto Lexical : TULexicalDecls)
Visit(Lexical.first, Lexical.second);
} else {
auto I = LexicalDecls.find(DC);
if (I != LexicalDecls.end())
Visit(getOwningModuleFile(cast<Decl>(DC)), I->second);
}
++NumLexicalDeclContextsRead;
}

View File

@ -2738,12 +2738,15 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
uint64_t Offset = Stream.GetCurrentBitNo();
RecordData Record;
Record.push_back(DECL_CONTEXT_LEXICAL);
SmallVector<KindDeclIDPair, 64> Decls;
for (const auto *D : DC->decls())
Decls.push_back(std::make_pair(D->getKind(), GetDeclRef(D)));
SmallVector<uint32_t, 128> KindDeclPairs;
for (const auto *D : DC->decls()) {
KindDeclPairs.push_back(D->getKind());
KindDeclPairs.push_back(GetDeclRef(D));
}
++NumLexicalDeclContexts;
Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, bytes(Decls));
Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record,
bytes(KindDeclPairs));
return Offset;
}
@ -4288,10 +4291,12 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
// Create a lexical update block containing all of the declarations in the
// translation unit that do not come from other AST files.
const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
SmallVector<KindDeclIDPair, 64> NewGlobalDecls;
for (const auto *I : TU->noload_decls()) {
if (!I->isFromASTFile())
NewGlobalDecls.push_back(std::make_pair(I->getKind(), GetDeclRef(I)));
SmallVector<uint32_t, 128> NewGlobalKindDeclPairs;
for (const auto *D : TU->noload_decls()) {
if (!D->isFromASTFile()) {
NewGlobalKindDeclPairs.push_back(D->getKind());
NewGlobalKindDeclPairs.push_back(GetDeclRef(D));
}
}
llvm::BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev();
@ -4301,7 +4306,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
Record.clear();
Record.push_back(TU_UPDATE_LEXICAL);
Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
bytes(NewGlobalDecls));
bytes(NewGlobalKindDeclPairs));
// And a visible updates block for the translation unit.
Abv = new llvm::BitCodeAbbrev();