diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-03-13 21:13:51 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-03-13 21:13:51 +0000 |
commit | 55ea75bf61a5d76f6453513d937944ce68181c6a (patch) | |
tree | 20a9ea8eb7950bd1e711a9f326e66d2d3ec6c4bc | |
parent | c1d22393628a145e54396c0ac66e9625d13a7658 (diff) |
[Modules] Don't eagerly load and associate all the module header files.
In a module-enabled Cocoa PCH file, we spend a lot of time stat'ing the headers
in order to associate the FileEntries with their modules and support implicit
module import.
Use a more lazy scheme by enhancing HeaderInfoTable to store extra info about
the module that a header belongs to, and associate it with its module only when
there is a request for loading the header info for a particular file.
Part of rdar://13391765
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176976 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Lex/HeaderSearch.h | 13 | ||||
-rw-r--r-- | include/clang/Lex/ModuleMap.h | 5 | ||||
-rw-r--r-- | include/clang/Serialization/ASTWriter.h | 4 | ||||
-rw-r--r-- | lib/Lex/HeaderSearch.cpp | 18 | ||||
-rw-r--r-- | lib/Lex/ModuleMap.cpp | 13 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 37 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 30 |
7 files changed, 90 insertions, 30 deletions
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 1729e240cc..a0ce139993 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -50,6 +50,9 @@ struct HeaderFileInfo { /// \brief Whether this header file info was supplied by an external source. unsigned External : 1; + + /// \brief Whether this header is part of a module. + unsigned isModuleHeader : 1; /// \brief Whether this structure is considered to already have been /// "resolved", meaning that it was loaded from the external source. @@ -90,7 +93,8 @@ struct HeaderFileInfo { HeaderFileInfo() : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User), - External(false), Resolved(false), IndexHeaderMapHeader(false), + External(false), isModuleHeader(false), Resolved(false), + IndexHeaderMapHeader(false), NumIncludes(0), ControllingMacroID(0), ControllingMacro(0) {} /// \brief Retrieve the controlling macro for this header file, if @@ -189,7 +193,7 @@ class HeaderSearch { std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps; /// \brief The mapping between modules and headers. - ModuleMap ModMap; + mutable ModuleMap ModMap; /// \brief Describes whether a given directory has a module map in it. llvm::DenseMap<const DirectoryEntry *, bool> DirectoryHasModuleMap; @@ -400,6 +404,9 @@ public: getFileInfo(File).DirInfo = SrcMgr::C_System; } + /// \brief Mark the specified file as part of a module. + void MarkFileModuleHeader(const FileEntry *File); + /// \brief Increment the count for the number of times the specified /// FileEntry has been entered. void IncrementIncludeCount(const FileEntry *File) { @@ -469,7 +476,7 @@ public: /// \brief Retrieve the module that corresponds to the given file, if any. /// /// \param File The header that we wish to map to a module. - Module *findModuleForHeader(const FileEntry *File); + Module *findModuleForHeader(const FileEntry *File) const; /// \brief Read the contents of the given module map file. /// diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index bb53ff21a0..cffa5b7b66 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -33,6 +33,7 @@ class FileEntry; class FileManager; class DiagnosticConsumer; class DiagnosticsEngine; +class HeaderSearch; class ModuleMapParser; class ModuleMap { @@ -40,6 +41,7 @@ class ModuleMap { IntrusiveRefCntPtr<DiagnosticsEngine> Diags; const LangOptions &LangOpts; const TargetInfo *Target; + HeaderSearch &HeaderInfo; /// \brief The directory used for Clang-supplied, builtin include headers, /// such as "stdint.h". @@ -147,7 +149,8 @@ public: /// /// \param Target The target for this translation unit. ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC, - const LangOptions &LangOpts, const TargetInfo *Target); + const LangOptions &LangOpts, const TargetInfo *Target, + HeaderSearch &HeaderInfo); /// \brief Destroy the module map. /// diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index b966ae1228..1bbf74061f 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -641,6 +641,10 @@ public: /// source location. serialization::SubmoduleID inferSubmoduleIDFromLocation(SourceLocation Loc); + /// \brief Retrieve a submodule ID for this module. + /// Returns 0 If no ID has been associated with the module. + unsigned getExistingSubmoduleID(Module *Mod) const; + /// \brief Note that the identifier II occurs at the given offset /// within the identifier table. void SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset); diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index d4d14e8745..9e4b68232a 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -47,7 +47,7 @@ HeaderSearch::HeaderSearch(IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts, const LangOptions &LangOpts, const TargetInfo *Target) : HSOpts(HSOpts), FileMgr(FM), FrameworkMap(64), - ModMap(FileMgr, *Diags.getClient(), LangOpts, Target) + ModMap(FileMgr, *Diags.getClient(), LangOpts, Target, *this) { AngledDirIdx = 0; SystemDirIdx = 0; @@ -806,6 +806,7 @@ static void mergeHeaderFileInfo(HeaderFileInfo &HFI, const HeaderFileInfo &OtherHFI) { HFI.isImport |= OtherHFI.isImport; HFI.isPragmaOnce |= OtherHFI.isPragmaOnce; + HFI.isModuleHeader |= OtherHFI.isModuleHeader; HFI.NumIncludes += OtherHFI.NumIncludes; if (!HFI.ControllingMacro && !HFI.ControllingMacroID) { @@ -851,6 +852,14 @@ bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) { HFI.ControllingMacro || HFI.ControllingMacroID; } +void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE) { + if (FE->getUID() >= FileInfo.size()) + FileInfo.resize(FE->getUID()+1); + + HeaderFileInfo &HFI = FileInfo[FE->getUID()]; + HFI.isModuleHeader = true; +} + void HeaderSearch::setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID) { if (UID >= FileInfo.size()) FileInfo.resize(UID+1); @@ -948,7 +957,12 @@ bool HeaderSearch::hasModuleMap(StringRef FileName, } while (true); } -Module *HeaderSearch::findModuleForHeader(const FileEntry *File) { +Module *HeaderSearch::findModuleForHeader(const FileEntry *File) const { + if (ExternalSource) { + // Make sure the external source has handled header info about this file, + // which includes whether the file is part of a module. + (void)getFileInfo(File); + } if (Module *Mod = ModMap.findModuleForHeader(File)) return Mod; diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index f9b4e2c947..71a98e2152 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -18,6 +18,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" +#include "clang/Lex/HeaderSearch.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/LiteralSupport.h" @@ -76,8 +77,10 @@ ModuleMap::resolveExport(Module *Mod, } ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC, - const LangOptions &LangOpts, const TargetInfo *Target) - : LangOpts(LangOpts), Target(Target), BuiltinIncludeDir(0) + const LangOptions &LangOpts, const TargetInfo *Target, + HeaderSearch &HeaderInfo) + : LangOpts(LangOpts), Target(Target), HeaderInfo(HeaderInfo), + BuiltinIncludeDir(0) { IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); Diags = IntrusiveRefCntPtr<DiagnosticsEngine>( @@ -553,10 +556,12 @@ void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) { void ModuleMap::addHeader(Module *Mod, const FileEntry *Header, bool Excluded) { - if (Excluded) + if (Excluded) { Mod->ExcludedHeaders.push_back(Header); - else + } else { Mod->Headers.push_back(Header); + HeaderInfo.MarkFileModuleHeader(Header); + } Headers[Header] = KnownHeader(Mod, Excluded); } diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 54fe424ddf..cc9b5d506a 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -1337,7 +1337,7 @@ HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) { } HeaderFileInfoTrait::data_type -HeaderFileInfoTrait::ReadData(internal_key_ref, const unsigned char *d, +HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, unsigned DataLen) { const unsigned char *End = d + DataLen; using namespace clang::io; @@ -1358,6 +1358,21 @@ HeaderFileInfoTrait::ReadData(internal_key_ref, const unsigned char *d, HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + if (d != End) { + uint32_t LocalSMID = ReadUnalignedLE32(d); + if (LocalSMID) { + // This header is part of a module. Associate it with the module to enable + // implicit module import. + SubmoduleID GlobalSMID = Reader.getGlobalSubmoduleID(M, LocalSMID); + Module *Mod = Reader.getSubmodule(GlobalSMID); + HFI.isModuleHeader = true; + FileManager &FileMgr = Reader.getFileManager(); + ModuleMap &ModMap = + Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap(); + ModMap.addHeader(Mod, FileMgr.getFile(key.Filename), /*Excluded=*/false); + } + } + assert(End == d && "Wrong data length in HeaderFileInfo deserialization"); (void)End; @@ -3508,13 +3523,9 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { if (!CurrentModule) break; - // FIXME: Be more lazy about this! - if (const FileEntry *File = PP.getFileManager().getFile(Blob)) { - if (std::find(CurrentModule->Headers.begin(), - CurrentModule->Headers.end(), - File) == CurrentModule->Headers.end()) - ModMap.addHeader(CurrentModule, File, false); - } + // We lazily associate headers with their modules via the HeaderInfoTable. + // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead + // of complete filenames or remove it entirely. break; } @@ -3527,13 +3538,9 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { if (!CurrentModule) break; - // FIXME: Be more lazy about this! - if (const FileEntry *File = PP.getFileManager().getFile(Blob)) { - if (std::find(CurrentModule->Headers.begin(), - CurrentModule->Headers.end(), - File) == CurrentModule->Headers.end()) - ModMap.addHeader(CurrentModule, File, true); - } + // We lazily associate headers with their modules via the HeaderInfoTable. + // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead + // of complete filenames or remove it entirely. break; } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 8f48d5870a..088e7a3f2c 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1384,14 +1384,15 @@ namespace { // Trait used for the on-disk hash table of header search information. class HeaderFileInfoTrait { ASTWriter &Writer; + const HeaderSearch &HS; // Keep track of the framework names we've used during serialization. SmallVector<char, 128> FrameworkStringData; llvm::StringMap<unsigned> FrameworkNameOffset; public: - HeaderFileInfoTrait(ASTWriter &Writer) - : Writer(Writer) { } + HeaderFileInfoTrait(ASTWriter &Writer, const HeaderSearch &HS) + : Writer(Writer), HS(HS) { } struct key_type { const FileEntry *FE; @@ -1415,6 +1416,8 @@ namespace { unsigned KeyLen = strlen(key.Filename) + 1 + 8 + 8; clang::io::Emit16(Out, KeyLen); unsigned DataLen = 1 + 2 + 4 + 4; + if (Data.isModuleHeader) + DataLen += 4; clang::io::Emit8(Out, DataLen); return std::make_pair(KeyLen, DataLen); } @@ -1427,7 +1430,7 @@ namespace { Out.write(key.Filename, KeyLen); } - void EmitData(raw_ostream &Out, key_type_ref, + void EmitData(raw_ostream &Out, key_type_ref key, data_type_ref Data, unsigned DataLen) { using namespace clang::io; uint64_t Start = Out.tell(); (void)Start; @@ -1461,7 +1464,12 @@ namespace { Offset = Pos->second; } Emit32(Out, Offset); - + + if (Data.isModuleHeader) { + Module *Mod = HS.findModuleForHeader(key.FE); + Emit32(Out, Writer.getExistingSubmoduleID(Mod)); + } + assert(Out.tell() - Start == DataLen && "Wrong data length"); } @@ -1480,7 +1488,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { if (FilesByUID.size() > HS.header_file_size()) FilesByUID.resize(HS.header_file_size()); - HeaderFileInfoTrait GeneratorTrait(*this); + HeaderFileInfoTrait GeneratorTrait(*this, HS); OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator; SmallVector<const char *, 4> SavedStrings; unsigned NumHeaderSearchEntries = 0; @@ -2020,6 +2028,18 @@ unsigned ASTWriter::getSubmoduleID(Module *Mod) { return SubmoduleIDs[Mod] = NextSubmoduleID++; } +unsigned ASTWriter::getExistingSubmoduleID(Module *Mod) const { + if (!Mod) + return 0; + + llvm::DenseMap<Module *, unsigned>::const_iterator + Known = SubmoduleIDs.find(Mod); + if (Known != SubmoduleIDs.end()) + return Known->second; + + return 0; +} + /// \brief Compute the number of modules within the given tree (including the /// given module). static unsigned getNumberOfModules(Module *Mod) { |