[cfe-commits] r64490 - in /cfe/trunk: Driver/CacheTokens.cpp lib/Lex/PTHLexer.cpp

Ted Kremenek kremenek at apple.com
Fri Feb 13 14:07:44 PST 2009


Author: kremenek
Date: Fri Feb 13 16:07:44 2009
New Revision: 64490

URL: http://llvm.org/viewvc/llvm-project?rev=64490&view=rev
Log:
PTH: Cache directory and negative 'stat' calls.  This gives us a 1% performance improvement on Cocoa.h (fsyntax-only+PTH).

Modified:
    cfe/trunk/Driver/CacheTokens.cpp
    cfe/trunk/lib/Lex/PTHLexer.cpp

Modified: cfe/trunk/Driver/CacheTokens.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/CacheTokens.cpp?rev=64490&r1=64489&r2=64490&view=diff

==============================================================================
--- cfe/trunk/Driver/CacheTokens.cpp (original)
+++ cfe/trunk/Driver/CacheTokens.cpp Fri Feb 13 16:07:44 2009
@@ -207,25 +207,23 @@
   
   
 class VISIBILITY_HIDDEN PTHEntryKeyVariant {
-  union { const FileEntry* FE; const DirectoryEntry* DE; const char* Path; };
+  union { const FileEntry* FE; const char* Path; };
   enum { IsFE = 0x1, IsDE = 0x2, IsNoExist = 0x0 } Kind;
+  struct stat *StatBuf;
 public:
-  PTHEntryKeyVariant(const FileEntry *fe) : FE(fe), Kind(IsFE) {}
-  PTHEntryKeyVariant(const DirectoryEntry *de) : DE(de), Kind(IsDE) {}
-  PTHEntryKeyVariant(const char* path) : Path(path), Kind(IsNoExist) {}
-  
-  const FileEntry *getFile() const { return Kind == IsFE ? FE : 0; }
-  const DirectoryEntry *getDir() const { return Kind == IsDE ? DE : 0; }
-  const char* getNameOfNonExistantFile() const {
-    return Kind == IsNoExist ? Path : 0;
-  }
+  PTHEntryKeyVariant(const FileEntry *fe)
+    : FE(fe), Kind(IsFE), StatBuf(0) {}
+
+  PTHEntryKeyVariant(struct stat* statbuf, const char* path)
+    : Path(path), Kind(IsDE), StatBuf(new struct stat(*statbuf)) {}
+
+  PTHEntryKeyVariant(const char* path)
+    : Path(path), Kind(IsNoExist), StatBuf(0) {}
+  
+  bool isFile() const { return Kind == IsFE; }
   
   const char* getCString() const {
-    switch (Kind) {
-      case IsFE: return FE->getName();
-      case IsDE: return DE->getName();
-      default: return Path;
-    }
+    return Kind == IsFE ? FE->getName() : Path;
   }
   
   unsigned getKind() const { return (unsigned) Kind; }
@@ -241,18 +239,21 @@
         ::Emit64(Out, FE->getSize());
         break;
       case IsDE:
-        // FIXME
-      default: break;
-        // Emit nothing.        
+        // Emit stat information.
+        ::Emit32(Out, (uint32_t) StatBuf->st_ino);
+        ::Emit32(Out, (uint32_t) StatBuf->st_dev);
+        ::Emit16(Out, (uint16_t) StatBuf->st_mode);
+        ::Emit64(Out, (uint64_t) StatBuf->st_mtime);
+        ::Emit64(Out, (uint64_t) StatBuf->st_size);
+        delete StatBuf;
+        break;
+      default:
+        break;
     }
   }
   
   unsigned getRepresentationLength() const {
-    switch (Kind) {
-      case IsFE: return 4 + 4 + 2 + 8 + 8;
-      case IsDE: // FIXME
-      default: return 0;
-    }
+    return Kind == IsNoExist ? 0 : 4 + 4 + 2 + 8 + 8;
   }
 };
   
@@ -275,7 +276,7 @@
     unsigned n = strlen(V.getCString()) + 1 + 1;
     ::Emit16(Out, n);
     
-    unsigned m = V.getRepresentationLength() + (V.getFile() ? 4 + 4 : 0);
+    unsigned m = V.getRepresentationLength() + (V.isFile() ? 4 + 4 : 0);
     ::Emit8(Out, m);
 
     return std::make_pair(n, m);
@@ -294,7 +295,7 @@
 
     // For file entries emit the offsets into the PTH file for token data
     // and the preprocessor blocks table.
-    if (V.getFile()) {
+    if (V.isFile()) {
       ::Emit32(Out, E.getTokenOffset());
       ::Emit32(Out, E.getPPCondTableOffset());
     }
@@ -367,12 +368,44 @@
 
   PTHEntry LexTokens(Lexer& L);
   Offset EmitCachedSpellings();
+
+  /// StatListener - A simple "interpose" object used to monitor stat calls
+  /// invoked by FileManager while processing the original sources used
+  /// as input to PTH generation.  StatListener populates the PTHWriter's
+  /// file map with stat information for directories as well as negative stats.
+  /// Stat information for files are populated elsewhere.
+  class StatListener : public StatSysCallCache {
+    PTHMap& PM;
+  public:
+    StatListener(PTHMap& pm) : PM(pm) {}
+    ~StatListener() {}
+    
+    int stat(const char *path, struct stat *buf) {
+      int result = ::stat(path, buf);
+      
+      if (result != 0) // Failed 'stat'.
+        PM.insert(path, PTHEntry());
+      else if (S_ISDIR(buf->st_mode)) {
+        // Only cache directories with absolute paths.
+        if (!llvm::sys::Path(path).isAbsolute())
+          return result;
+
+        PM.insert(PTHEntryKeyVariant(buf, path), PTHEntry());
+      }
+        
+      return result;
+    }
+  };
   
 public:
   PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp) 
     : Out(out), PP(pp), idcount(0), CurStrOffset(0) {}
     
   void GeneratePTH();
+
+  StatSysCallCache *createStatListener() {
+    return new StatListener(PM);
+  }
 };
 } // end anonymous namespace
   
@@ -642,12 +675,6 @@
 }
 
 void clang::CacheTokens(Preprocessor& PP, const std::string& OutFile) {
-  // Lex through the entire file.  This will populate SourceManager with
-  // all of the header information.
-  Token Tok;
-  PP.EnterMainSourceFile();
-  do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));
-  
   // Open up the PTH file.
   std::string ErrMsg;
   llvm::raw_fd_ostream Out(OutFile.c_str(), true, ErrMsg);
@@ -656,9 +683,23 @@
     llvm::errs() << "PTH error: " << ErrMsg << "\n";
     return;
   }
-  
-  // Create the PTHWriter and generate the PTH file.
+
+  // Create the PTHWriter.
   PTHWriter PW(Out, PP);
+  
+  // Install the 'stat' system call listener in the FileManager.
+  PP.getFileManager().setStatCache(PW.createStatListener());
+  
+  // Lex through the entire file.  This will populate SourceManager with
+  // all of the header information.
+  Token Tok;
+  PP.EnterMainSourceFile();
+  do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));
+  
+
+  
+  // Generate the PTH file.
+  PP.getFileManager().setStatCache(0);
   PW.GeneratePTH();
 }
 
@@ -750,5 +791,3 @@
   
   return std::make_pair(IDOff, StringTableOffset);
 }
-
-

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

==============================================================================
--- cfe/trunk/lib/Lex/PTHLexer.cpp (original)
+++ cfe/trunk/lib/Lex/PTHLexer.cpp Fri Feb 13 16:07:44 2009
@@ -808,15 +808,17 @@
   
   static data_type ReadData(const internal_key_type& k, const unsigned char* d,
                             unsigned) {    
-    if (k.first == 0x1 /* File */) {
-      d += 4 * 2; // Skip the first 2 words.
+    
+    if (k.first /* File or Directory */) {
+      if (k.first == 0x1 /* File */) d += 4 * 2; // Skip the first 2 words.
       ino_t ino = (ino_t) ReadUnalignedLE32(d);
       dev_t dev = (dev_t) ReadUnalignedLE32(d);
       mode_t mode = (mode_t) ReadUnalignedLE16(d);
       time_t mtime = (time_t) ReadUnalignedLE64(d);    
       return data_type(ino, dev, mode, mtime, (off_t) ReadUnalignedLE64(d));
     }
-    
+
+    // Negative stat.  Don't read anything.
     return data_type();
   }
 };
@@ -841,6 +843,10 @@
     if (I == Cache.end()) return ::stat(path, buf);
     
     const PTHStatData& Data = *I;
+    
+    if (!Data.hasStat)
+      return 1;
+
     buf->st_ino = Data.ino;
     buf->st_dev = Data.dev;
     buf->st_mtime = Data.mtime;





More information about the cfe-commits mailing list