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.

llvm-svn: 70094
This commit is contained in:
Douglas Gregor 2009-04-25 23:30:02 +00:00
parent c06ce0f710
commit 99734e7669
6 changed files with 77 additions and 13 deletions

View File

@ -234,7 +234,20 @@ public:
/// 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

View File

@ -64,7 +64,10 @@ class SwitchCase;
/// 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 @@ public:
return DecodeIdentifierInfo(Record[Idx++]);
}
virtual IdentifierInfo *GetIdentifier(unsigned ID) {
return DecodeIdentifierInfo(ID);
}
Selector DecodeSelector(unsigned Idx);
Selector GetSelector(const RecordData &Record, unsigned &Idx) {

View File

@ -19,6 +19,8 @@
#include <vector>
namespace clang {
class ExternalIdentifierLookup;
class FileEntry;
class FileManager;
class IdentifierInfo;
@ -42,10 +44,27 @@ struct HeaderFileInfo {
/// 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 @@ class HeaderSearch {
/// 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 @@ public:
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

View File

@ -42,6 +42,8 @@ IdentifierInfo::IdentifierInfo() {
IdentifierInfoLookup::~IdentifierInfoLookup() {}
ExternalIdentifierLookup::~ExternalIdentifierLookup() {}
IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
IdentifierInfoLookup* externalLookup)
: HashTable(8192), // Start with space for 8K identifiers.

View File

@ -1717,7 +1717,7 @@ bool PCHReader::ReadPreprocessorBlock() {
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 @@ PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset) {
}
IdentifierOffsets = (const uint32_t *)BlobStart;
IdentifiersLoaded.resize(Record[0]);
PP.getHeaderSearchInfo().SetExternalLookup(this);
break;
case pch::EXTERNAL_DEFINITIONS:

View File

@ -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 @@ bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){
// 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;