From d11d422a37f64d7192e8c72abfe749cb11bfc9fa Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 6 Aug 2015 22:07:25 +0000 Subject: [PATCH] [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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@244285 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Serialization/ASTBitCodes.h | 3 - include/clang/Serialization/ASTReader.h | 10 +++ include/clang/Serialization/Module.h | 4 +- lib/Serialization/ASTReader.cpp | 101 +++++++++------------- lib/Serialization/ASTWriter.cpp | 23 +++-- 5 files changed, 66 insertions(+), 75 deletions(-) diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 3d46225e7c..ea3a9c203b 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -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 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; diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 227ac50d8f..b01070edb4 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -494,6 +494,16 @@ private: /// \brief Map from a FileID to the file-level declarations that it contains. llvm::DenseMap FileDeclIDs; + /// \brief An array of lexical contents of a declaration context, as a sequence of + /// Decl::Kind, DeclID pairs. + typedef ArrayRef LexicalContents; + + /// \brief Map from a DeclContext to its lexical contents. + llvm::DenseMap LexicalDecls; + + /// \brief Map from the TU to its lexical contents from each module file. + std::vector> 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 diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h index 1d9fb0bfe8..0740cd025e 100644 --- a/include/clang/Serialization/Module.h +++ b/include/clang/Serialization/Module.h @@ -52,12 +52,10 @@ enum ModuleKind { /// \brief Information about the contents of a DeclContext. struct DeclContextInfo { - DeclContextInfo() - : NameLookupTableData(), LexicalDecls() {} + DeclContextInfo() : NameLookupTableData() {} llvm::OnDiskIterableChainedHashTable *NameLookupTableData; // an ASTDeclContextNameLookupTable. - ArrayRef LexicalDecls; }; /// \brief The input file that has been loaded from this AST file, along with diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index c12894d773..acb19a2cc7 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -973,9 +973,13 @@ bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M, return true; } - M.DeclContextInfos[DC].LexicalDecls = llvm::makeArrayRef( - reinterpret_cast(Blob.data()), - Blob.size() / sizeof(KindDeclIDPair)); + assert(!isa(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(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(Blob.data()), - static_cast(Blob.size() / sizeof(KindDeclIDPair))); + LexicalContents Contents( + reinterpret_cast( + Blob.data()), + static_cast(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 IsKindWeWant; - - SmallVectorImpl &Decls; - bool PredefsVisited[NUM_PREDEF_DECL_IDS]; - - public: - FindExternalLexicalDeclsVisitor( - ASTReader &Reader, const DeclContext *DC, - llvm::function_ref IsKindWeWant, - SmallVectorImpl &Decls) - : Reader(Reader), DC(DC), IsKindWeWant(IsKindWeWant), Decls(Decls) { - for (unsigned I = 0; I != NUM_PREDEF_DECL_IDS; ++I) - PredefsVisited[I] = false; - } +void ASTReader::FindExternalLexicalDecls( + const DeclContext *DC, llvm::function_ref IsKindWeWant, + SmallVectorImpl &Decls) { + bool PredefsVisited[NUM_PREDEF_DECL_IDS] = {}; - static bool visitPostorder(ModuleFile &M, void *UserData) { - return (*static_cast(UserData))(M); - } + 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; - bool operator()(ModuleFile &M) { - ModuleFile::DeclContextInfosMap::iterator Info = - M.DeclContextInfos.find(DC); - if (Info == M.DeclContextInfos.end() || Info->second.LexicalDecls.empty()) - return false; + auto ID = (serialization::DeclID)+LexicalDecls[I + 1]; - // Load all of the declaration IDs - for (const KindDeclIDPair &P : Info->second.LexicalDecls) { - if (!IsKindWeWant((Decl::Kind)P.first)) + // Don't add predefined declarations to the lexical context more + // than once. + if (ID < NUM_PREDEF_DECL_IDS) { + if (PredefsVisited[ID]) 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); - } + PredefsVisited[ID] = true; } - return false; + if (Decl *D = GetLocalDecl(*M, ID)) { + if (!DC->isDeclInLexicalTraversal(D)) + Decls.push_back(D); + } } }; -} -void ASTReader::FindExternalLexicalDecls( - const DeclContext *DC, llvm::function_ref IsKindWeWant, - SmallVectorImpl &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); + if (isa(DC)) { + for (auto Lexical : TULexicalDecls) + Visit(Lexical.first, Lexical.second); + } else { + auto I = LexicalDecls.find(DC); + if (I != LexicalDecls.end()) + Visit(getOwningModuleFile(cast(DC)), I->second); + } + ++NumLexicalDeclContextsRead; } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 1199803a9c..366d4b39fc 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -2738,12 +2738,15 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, uint64_t Offset = Stream.GetCurrentBitNo(); RecordData Record; Record.push_back(DECL_CONTEXT_LEXICAL); - SmallVector Decls; - for (const auto *D : DC->decls()) - Decls.push_back(std::make_pair(D->getKind(), GetDeclRef(D))); + SmallVector 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 NewGlobalDecls; - for (const auto *I : TU->noload_decls()) { - if (!I->isFromASTFile()) - NewGlobalDecls.push_back(std::make_pair(I->getKind(), GetDeclRef(I))); + SmallVector 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(); -- 2.50.1