[cfe-commits] r70094 - in /cfe/trunk: include/clang/Basic/IdentifierTable.h include/clang/Frontend/PCHReader.h include/clang/Lex/HeaderSearch.h lib/Basic/IdentifierTable.cpp lib/Frontend/PCHReader.cpp lib/Lex/HeaderSearch.cpp

Douglas Gregor dgregor at apple.com
Sat Apr 25 16:30:02 PDT 2009


Author: dgregor
Date: Sat Apr 25 18:30:02 2009
New Revision: 70094

URL: http://llvm.org/viewvc/llvm-project?rev=70094&view=rev
Log:
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.


Modified:
    cfe/trunk/include/clang/Basic/IdentifierTable.h
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/include/clang/Lex/HeaderSearch.h
    cfe/trunk/lib/Basic/IdentifierTable.cpp
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Lex/HeaderSearch.cpp

Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/IdentifierTable.h?rev=70094&r1=70093&r2=70094&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/IdentifierTable.h (original)
+++ cfe/trunk/include/clang/Basic/IdentifierTable.h Sat Apr 25 18:30:02 2009
@@ -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

Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=70094&r1=70093&r2=70094&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Sat Apr 25 18:30:02 2009
@@ -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) {

Modified: cfe/trunk/include/clang/Lex/HeaderSearch.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/HeaderSearch.h?rev=70094&r1=70093&r2=70094&view=diff

==============================================================================
--- cfe/trunk/include/clang/Lex/HeaderSearch.h (original)
+++ cfe/trunk/include/clang/Lex/HeaderSearch.h Sat Apr 25 18:30:02 2009
@@ -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

Modified: cfe/trunk/lib/Basic/IdentifierTable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/IdentifierTable.cpp?rev=70094&r1=70093&r2=70094&view=diff

==============================================================================
--- cfe/trunk/lib/Basic/IdentifierTable.cpp (original)
+++ cfe/trunk/lib/Basic/IdentifierTable.cpp Sat Apr 25 18:30:02 2009
@@ -42,6 +42,8 @@
 
 IdentifierInfoLookup::~IdentifierInfoLookup() {}
 
+ExternalIdentifierLookup::~ExternalIdentifierLookup() {}
+
 IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
                                  IdentifierInfoLookup* externalLookup)
   : HashTable(8192), // Start with space for 8K identifiers.

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=70094&r1=70093&r2=70094&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Sat Apr 25 18:30:02 2009
@@ -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:

Modified: cfe/trunk/lib/Lex/HeaderSearch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/HeaderSearch.cpp?rev=70094&r1=70093&r2=70094&view=diff

==============================================================================
--- cfe/trunk/lib/Lex/HeaderSearch.cpp (original)
+++ cfe/trunk/lib/Lex/HeaderSearch.cpp Sat Apr 25 18:30:02 2009
@@ -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;





More information about the cfe-commits mailing list