[cfe-commits] r62009 - in /cfe/trunk: include/clang/Lex/PTHLexer.h include/clang/Lex/PTHManager.h lib/Lex/PTHLexer.cpp

Ted Kremenek kremenek at apple.com
Fri Jan 9 14:05:31 PST 2009


Author: kremenek
Date: Fri Jan  9 16:05:30 2009
New Revision: 62009

URL: http://llvm.org/viewvc/llvm-project?rev=62009&view=rev
Log:
Enhance PTH 'getSpelling' caching:
- Refactor caching logic into a helper class PTHSpellingSearch
- Allow "random accesses" in the spelling cache, thus catching the remaining
  cases where 'getSpelling' wasn't hitting the PTH cache
  
For -Eonly, PTH, Cocoa.h:
- This reduces wall time by 3% (user time unchanged, sys time reduced)
- This reduces the amount of paged source by 1112K.
  The remaining 1112K still being paged in is from somewhere else
  (investigating).

Modified:
    cfe/trunk/include/clang/Lex/PTHLexer.h
    cfe/trunk/include/clang/Lex/PTHManager.h
    cfe/trunk/lib/Lex/PTHLexer.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Lex/PTHLexer.h (original)
+++ cfe/trunk/include/clang/Lex/PTHLexer.h Fri Jan  9 16:05:30 2009
@@ -20,8 +20,13 @@
 namespace clang {
   
 class PTHManager;
+class PTHSpellingSearch;
   
 class PTHLexer : public PreprocessorLexer {
+private:
+  /// FileID - The SourceManager FileID for the original source file.
+  unsigned FileID;
+  
   /// TokBuf - Buffer from PTH file containing raw token data.
   const char* TokBuf;
   
@@ -41,13 +46,10 @@
   /// CurPPCondPtr - Pointer inside PPCond that refers to the next entry
   ///  to process when doing quick skipping of preprocessor blocks.
   const char* CurPPCondPtr;
-  
-  /// Pointer to a side table containing offsets in the PTH file
-  ///  for token spellings.
-  const char* SpellingTable;
-  
-  /// Number of cached spellings left in the cached source file.
-  unsigned SpellingsLeft;
+
+  /// MySpellingMgr - Reference to the spelling manager used to get spellings
+  ///  for the source file indicated by \c FileID.
+  PTHSpellingSearch& MySpellingSrch;  
 
   PTHLexer(const PTHLexer&);  // DO NOT IMPLEMENT
   void operator=(const PTHLexer&); // DO NOT IMPLEMENT
@@ -59,14 +61,17 @@
   PTHManager& PTHMgr;
   
   Token EofToken;
-  
-public:  
+
+protected:
+  friend class PTHManager;
 
   /// Create a PTHLexer for the specified token stream.
   PTHLexer(Preprocessor& pp, SourceLocation fileloc, const char* D, 
-           const char* ppcond, const char* spellingTable, unsigned numSpellings,
+           const char* ppcond,
+           PTHSpellingSearch& mySpellingSrch,
            PTHManager& PM);
-  
+public:  
+
   ~PTHLexer() {}
     
   /// Lex - Return the next token.

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

==============================================================================
--- cfe/trunk/include/clang/Lex/PTHManager.h (original)
+++ cfe/trunk/include/clang/Lex/PTHManager.h Fri Jan  9 16:05:30 2009
@@ -16,6 +16,7 @@
 
 #include "clang/Lex/PTHLexer.h"
 #include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/DenseMap.h"
 #include <string>
 
 namespace llvm {
@@ -28,14 +29,41 @@
 class IdentifierInfo;
 class IdentifierTable;
 class PTHLexer;
+class PTHManager;
+
+class PTHSpellingSearch {
+  PTHManager& PTHMgr;
   
-class PTHManager {
+  const char* TableBeg;
+  const char* TableEnd;
+  
+  unsigned SpellingsLeft;
+  const char* LinearItr;
+  
+public:
+  enum { SpellingEntrySize = 4*2 };
   
+  unsigned getSpellingBinarySearch(unsigned fpos, const char *&Buffer);
+  unsigned getSpellingLinearSearch(unsigned fpos, const char *&Buffer);
+  
+  PTHSpellingSearch(PTHManager& pm, unsigned numSpellings, const char* tableBeg)
+    : PTHMgr(pm),
+      TableBeg(tableBeg),
+      TableEnd(tableBeg + numSpellings*SpellingEntrySize),
+      SpellingsLeft(numSpellings),
+      LinearItr(tableBeg) {}
+};  
+  
+class PTHManager {
   friend class PTHLexer;
+  friend class PTHSpellingSearch;
   
   /// The memory mapped PTH file.
   const llvm::MemoryBuffer* Buf;
   
+  /// A map from FileIDs to SpellingSearch objects.
+  llvm::DenseMap<unsigned,PTHSpellingSearch*> SpellingMap;
+  
   /// IdMap - A lazily generated cache mapping from persistent identifiers to
   ///  IdentifierInfo*.
   IdentifierInfo** PerIDCache;
@@ -70,10 +98,12 @@
   ///  objects from the PTH file.
   IdentifierInfo* GetIdentifierInfo(unsigned);
   
-  /// GetSpelling - Used by PTHLexer classes to get the cached spelling
-  ///  for a token.
-  unsigned GetSpelling(unsigned PTHOffset, const char*& Buffer);
+  /// getSpellingAtPTHOffset - Used by PTHLexer classes to get the cached 
+  ///  spelling for a token.
+  unsigned getSpellingAtPTHOffset(unsigned PTHOffset, const char*& Buffer);
 
+  unsigned getSpelling(unsigned FileID, unsigned fpos, const char *& Buffer);
+  
 public:
   
   ~PTHManager();

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

==============================================================================
--- cfe/trunk/lib/Lex/PTHLexer.cpp (original)
+++ cfe/trunk/lib/Lex/PTHLexer.cpp Fri Jan  9 16:05:30 2009
@@ -23,6 +23,7 @@
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/Streams.h"
 
 using namespace clang;
 
@@ -50,12 +51,14 @@
 
 PTHLexer::PTHLexer(Preprocessor& pp, SourceLocation fileloc, const char* D,
                    const char* ppcond,
-                   const char* spellingTable, unsigned NumSpellings,
+                   PTHSpellingSearch& mySpellingSrch,
                    PTHManager& PM)
   : PreprocessorLexer(&pp, fileloc), TokBuf(D), CurPtr(D), LastHashTokPtr(0),
-    PPCond(ppcond), CurPPCondPtr(ppcond), 
-    SpellingTable(spellingTable), SpellingsLeft(NumSpellings),
-    PTHMgr(PM) {}
+    PPCond(ppcond), CurPPCondPtr(ppcond), MySpellingSrch(mySpellingSrch),
+    PTHMgr(PM)
+{      
+  FileID = fileloc.getFileID();
+}
 
 void PTHLexer::Lex(Token& Tok) {
 LexNextToken:
@@ -100,6 +103,13 @@
   //===--------------------------------------==//
   // Process the token.
   //===--------------------------------------==//
+#if 0  
+  SourceManager& SM = PP->getSourceManager();
+  llvm::cerr << SM.getFileEntryForID(FileID)->getName()
+    << ':' << SM.getLogicalLineNumber(Tok.getLocation())
+    << ':' << SM.getLogicalColumnNumber(Tok.getLocation())
+    << '\n';
+#endif  
 
   if (k == tok::identifier) {
     MIOpt.ReadToken();
@@ -289,7 +299,25 @@
   return SourceLocation::getFileLoc(FileID, offset);
 }
 
-unsigned PTHManager::GetSpelling(unsigned PTHOffset, const char *& Buffer) {
+//===----------------------------------------------------------------------===//
+// getSpelling() - Use cached data in PTH files for getSpelling().
+//===----------------------------------------------------------------------===//
+
+unsigned PTHManager::getSpelling(unsigned FileID, unsigned fpos,
+                                 const char *& Buffer) {
+  
+  llvm::DenseMap<unsigned,PTHSpellingSearch*>::iterator I =
+    SpellingMap.find(FileID);
+
+  if (I == SpellingMap.end())
+      return 0;
+    
+  return I->second->getSpellingBinarySearch(fpos, Buffer);  
+}
+
+unsigned PTHManager::getSpellingAtPTHOffset(unsigned PTHOffset,
+                                            const char *& Buffer) {
+
   const char* p = Buf->getBufferStart() + PTHOffset;
   assert(p < Buf->getBufferEnd());
   
@@ -302,13 +330,15 @@
   return len;
 }
 
-unsigned PTHLexer::getSpelling(SourceLocation sloc, const char *&Buffer) {
-  const char* p = SpellingTable;
-  SourceManager& SM = PP->getSourceManager();
-  unsigned fpos = SM.getFullFilePos(SM.getPhysicalLoc(sloc));
+unsigned PTHSpellingSearch::getSpellingLinearSearch(unsigned fpos,
+                                                    const char *&Buffer) {
+  const char* p = LinearItr;
   unsigned len = 0;
-
-  while (SpellingsLeft) {
+  
+  if (!SpellingsLeft)
+    return getSpellingBinarySearch(fpos, Buffer);
+  
+  do {
     uint32_t TokOffset = 
       ((uint32_t) ((uint8_t) p[0]))
       | (((uint32_t) ((uint8_t) p[1])) << 8)
@@ -316,7 +346,7 @@
       | (((uint32_t) ((uint8_t) p[3])) << 24);
     
     if (TokOffset > fpos)
-      break;
+      return getSpellingBinarySearch(fpos, Buffer);
     
     --SpellingsLeft;
     
@@ -328,18 +358,72 @@
         | (((uint32_t) ((uint8_t) p[6])) << 16)
         | (((uint32_t) ((uint8_t) p[7])) << 24);
       
-      len = PTHMgr.GetSpelling(SpellingPTHOffset, Buffer);
+      len = PTHMgr.getSpellingAtPTHOffset(SpellingPTHOffset, Buffer);
       break;
     }
 
     // No match.  Keep on looking.
     p += sizeof(uint32_t)*2;
   }
+  while (SpellingsLeft);
 
-  SpellingTable = p;
+  LinearItr = p;
   return len;
 }
 
+unsigned PTHSpellingSearch::getSpellingBinarySearch(unsigned fpos,
+                                                    const char *& Buffer) {
+  
+  assert ((TableEnd - TableBeg) % SpellingEntrySize == 0);
+  
+  unsigned min = 0;
+  const char* tb = TableBeg;
+  unsigned max = (TableEnd - tb) / SpellingEntrySize;
+
+  while (min != max) {
+    unsigned i = (max - min) / 2 + min;
+    const char* p = tb + (i * SpellingEntrySize);
+    
+    uint32_t TokOffset = 
+      ((uint32_t) ((uint8_t) p[0]))
+      | (((uint32_t) ((uint8_t) p[1])) << 8)
+      | (((uint32_t) ((uint8_t) p[2])) << 16)
+      | (((uint32_t) ((uint8_t) p[3])) << 24);
+    
+    if (TokOffset > fpos) {
+      max = i;
+      continue;
+    }
+    
+    if (TokOffset < fpos) {
+      min = i;
+      continue;
+    }
+    
+    uint32_t SpellingPTHOffset = 
+        ((uint32_t) ((uint8_t) p[4]))
+        | (((uint32_t) ((uint8_t) p[5])) << 8)
+        | (((uint32_t) ((uint8_t) p[6])) << 16)
+        | (((uint32_t) ((uint8_t) p[7])) << 24);
+    
+    return PTHMgr.getSpellingAtPTHOffset(SpellingPTHOffset, Buffer);
+  }
+  
+  return 0;
+}
+
+unsigned PTHLexer::getSpelling(SourceLocation sloc, const char *&Buffer) {
+  SourceManager& SM = PP->getSourceManager();
+  sloc = SM.getPhysicalLoc(sloc);
+  unsigned fid = SM.getCanonicalFileID(sloc);
+  unsigned fpos = SM.getFullFilePos(sloc);
+  
+  if (fid == FileID)
+    return MySpellingSrch.getSpellingLinearSearch(fpos, Buffer);
+
+  return PTHMgr.getSpelling(fid, fpos, Buffer);
+}
+
 //===----------------------------------------------------------------------===//
 // Internal Data Structures for PTH file lookup and resolving identifiers.
 //===----------------------------------------------------------------------===//
@@ -538,6 +622,11 @@
   if (len == 0) spellingTable = 0;
 
   assert(data < Buf->getBufferEnd());
+  
+  // Create the SpellingSearch object for this FileID.
+  PTHSpellingSearch* ss = new PTHSpellingSearch(*this, len, spellingTable);
+  SpellingMap[FileID] = ss;
+  
   return new PTHLexer(PP, SourceLocation::getFileLoc(FileID, 0), data, ppcond,
-                      spellingTable, len, *this); 
+                      *ss, *this); 
 }





More information about the cfe-commits mailing list