r176976 - [Modules] Don't eagerly load and associate all the module header files.
Argyrios Kyrtzidis
akyrtzi at gmail.com
Wed Mar 13 14:13:51 PDT 2013
Author: akirtzidis
Date: Wed Mar 13 16:13:51 2013
New Revision: 176976
URL: http://llvm.org/viewvc/llvm-project?rev=176976&view=rev
Log:
[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
Modified:
cfe/trunk/include/clang/Lex/HeaderSearch.h
cfe/trunk/include/clang/Lex/ModuleMap.h
cfe/trunk/include/clang/Serialization/ASTWriter.h
cfe/trunk/lib/Lex/HeaderSearch.cpp
cfe/trunk/lib/Lex/ModuleMap.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
Modified: cfe/trunk/include/clang/Lex/HeaderSearch.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/HeaderSearch.h?rev=176976&r1=176975&r2=176976&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/HeaderSearch.h (original)
+++ cfe/trunk/include/clang/Lex/HeaderSearch.h Wed Mar 13 16:13:51 2013
@@ -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.
///
Modified: cfe/trunk/include/clang/Lex/ModuleMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=176976&r1=176975&r2=176976&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ModuleMap.h (original)
+++ cfe/trunk/include/clang/Lex/ModuleMap.h Wed Mar 13 16:13:51 2013
@@ -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.
///
Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=176976&r1=176975&r2=176976&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Wed Mar 13 16:13:51 2013
@@ -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);
Modified: cfe/trunk/lib/Lex/HeaderSearch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/HeaderSearch.cpp?rev=176976&r1=176975&r2=176976&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/HeaderSearch.cpp (original)
+++ cfe/trunk/lib/Lex/HeaderSearch.cpp Wed Mar 13 16:13:51 2013
@@ -47,7 +47,7 @@ HeaderSearch::HeaderSearch(IntrusiveRefC
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(HeaderFi
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::isFileMultipleInclude
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(StringRe
} 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;
Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=176976&r1=176975&r2=176976&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Wed Mar 13 16:13:51 2013
@@ -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 *M
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);
}
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=176976&r1=176975&r2=176976&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Wed Mar 13 16:13:51 2013
@@ -1337,7 +1337,7 @@ HeaderFileInfoTrait::ReadKey(const unsig
}
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_k
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(Modul
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(Modul
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;
}
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=176976&r1=176975&r2=176976&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed Mar 13 16:13:51 2013
@@ -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
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(Modul
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) {
More information about the cfe-commits
mailing list