Lazily load the controlling macros for all of the headers known in the
PCH file. In the Cocoa-prefixed "Hello, World" benchmark, this takes
us from reading 503 identifiers down to 37 and from 470 macros down to
4. It also results in an 8% performance improvement.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70094 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index 235c190..083196a 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -234,7 +234,20 @@
/// be found.
virtual IdentifierInfo* get(const char *NameStart, const char *NameEnd) = 0;
};
-
+
+/// \brief An abstract class used to resolve numerical identifier
+/// references (meaningful only to some external source) into
+/// IdentifierInfo pointers.
+class ExternalIdentifierLookup {
+public:
+ virtual ~ExternalIdentifierLookup();
+
+ /// \brief Return the identifier associated with the given ID number.
+ ///
+ /// The ID 0 is associated with the NULL identifier.
+ virtual IdentifierInfo *GetIdentifier(unsigned ID) = 0;
+};
+
/// IdentifierTable - This table implements an efficient mapping from strings to
/// IdentifierInfo nodes. It has no other purpose, but this is an
/// extremely performance-critical piece of the code, as each occurrance of
diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h
index 0c8520c..98e32fc 100644
--- a/include/clang/Frontend/PCHReader.h
+++ b/include/clang/Frontend/PCHReader.h
@@ -64,7 +64,10 @@
/// The PCH reader provides lazy de-serialization of declarations, as
/// required when traversing the AST. Only those AST nodes that are
/// actually required will be de-serialized.
-class PCHReader : public ExternalSemaSource, public IdentifierInfoLookup {
+class PCHReader
+ : public ExternalSemaSource,
+ public IdentifierInfoLookup,
+ public ExternalIdentifierLookup {
public:
enum PCHReadResult { Success, Failure, IgnorePCH };
@@ -371,6 +374,10 @@
return DecodeIdentifierInfo(Record[Idx++]);
}
+ virtual IdentifierInfo *GetIdentifier(unsigned ID) {
+ return DecodeIdentifierInfo(ID);
+ }
+
Selector DecodeSelector(unsigned Idx);
Selector GetSelector(const RecordData &Record, unsigned &Idx) {
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index fe7e7ae..f21aab1 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -19,6 +19,8 @@
#include <vector>
namespace clang {
+
+class ExternalIdentifierLookup;
class FileEntry;
class FileManager;
class IdentifierInfo;
@@ -42,10 +44,27 @@
/// ControllingMacro - If this file has a #ifndef XXX (or equivalent) guard
/// that protects the entire contents of the file, this is the identifier
/// for the macro that controls whether or not it has any effect.
+ ///
+ /// Note: Most clients should use getControllingMacro() to access
+ /// the controlling macro of this header, since
+ /// getControllingMacro() is able to load a controlling macro from
+ /// external storage.
const IdentifierInfo *ControllingMacro;
-
- HeaderFileInfo() : isImport(false), DirInfo(SrcMgr::C_User),
- NumIncludes(0), ControllingMacro(0) {}
+
+ /// \brief The ID number of the controlling macro.
+ ///
+ /// This ID number will be non-zero when there is a controlling
+ /// macro whose IdentifierInfo may not yet have been loaded from
+ /// external storage.
+ unsigned ControllingMacroID;
+
+ HeaderFileInfo()
+ : isImport(false), DirInfo(SrcMgr::C_User),
+ NumIncludes(0), ControllingMacro(0), ControllingMacroID(0) {}
+
+ /// \brief Retrieve the controlling macro for this header file, if
+ /// any.
+ const IdentifierInfo *getControllingMacro(ExternalIdentifierLookup *External);
};
/// HeaderSearch - This class encapsulates the information needed to find the
@@ -84,7 +103,11 @@
/// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing
/// headermaps. This vector owns the headermap.
std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps;
-
+
+ /// \brief Entity used to resolve the identifier IDs of controlling
+ /// macros into IdentifierInfo pointers, as needed.
+ ExternalIdentifierLookup *ExternalLookup;
+
// Various statistics we track for performance analysis.
unsigned NumIncluded;
unsigned NumMultiIncludeFileOptzn;
@@ -115,6 +138,10 @@
FileInfo.clear();
}
+ void SetExternalLookup(ExternalIdentifierLookup *EIL) {
+ ExternalLookup = EIL;
+ }
+
/// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
/// return null on failure. isAngled indicates whether the file reference is
/// a <> reference. If successful, this returns 'UsedDir', the
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 344c4eb..8b74b20 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -42,6 +42,8 @@
IdentifierInfoLookup::~IdentifierInfoLookup() {}
+ExternalIdentifierLookup::~ExternalIdentifierLookup() {}
+
IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
IdentifierInfoLookup* externalLookup)
: HashTable(8192), // Start with space for 8K identifiers.
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 40e5c0d..c351a24 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -1717,7 +1717,7 @@
HFI.isImport = Record[0];
HFI.DirInfo = Record[1];
HFI.NumIncludes = Record[2];
- HFI.ControllingMacro = DecodeIdentifierInfo(Record[3]);
+ HFI.ControllingMacroID = Record[3];
PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
break;
}
@@ -1854,6 +1854,7 @@
}
IdentifierOffsets = (const uint32_t *)BlobStart;
IdentifiersLoaded.resize(Record[0]);
+ PP.getHeaderSearchInfo().SetExternalLookup(this);
break;
case pch::EXTERNAL_DEFINITIONS:
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index ddea8e5..129fa1a 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -20,10 +20,23 @@
#include <cstdio>
using namespace clang;
+const IdentifierInfo *
+HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) {
+ if (ControllingMacro)
+ return ControllingMacro;
+
+ if (!ControllingMacroID || !External)
+ return 0;
+
+ ControllingMacro = External->GetIdentifier(ControllingMacroID);
+ return ControllingMacro;
+}
+
HeaderSearch::HeaderSearch(FileManager &FM) : FileMgr(FM), FrameworkMap(64) {
SystemDirIdx = 0;
NoCurDirSearch = false;
-
+
+ ExternalLookup = 0;
NumIncluded = 0;
NumMultiIncludeFileOptzn = 0;
NumFrameworkLookups = NumSubFrameworkLookups = 0;
@@ -417,11 +430,12 @@
// Next, check to see if the file is wrapped with #ifndef guards. If so, and
// if the macro that guards it is defined, we know the #include has no effect.
- if (FileInfo.ControllingMacro &&
- FileInfo.ControllingMacro->hasMacroDefinition()) {
- ++NumMultiIncludeFileOptzn;
- return false;
- }
+ if (const IdentifierInfo *ControllingMacro
+ = FileInfo.getControllingMacro(ExternalLookup))
+ if (ControllingMacro->hasMacroDefinition()) {
+ ++NumMultiIncludeFileOptzn;
+ return false;
+ }
// Increment the number of times this file has been included.
++FileInfo.NumIncludes;