On Fri, Oct 16, 2009 at 11:18 AM, Douglas Gregor <[email protected]> wrote: > Author: dgregor > Date: Fri Oct 16 13:18:30 2009 > New Revision: 84263 > > URL: http://llvm.org/viewvc/llvm-project?rev=84263&view=rev > Log: > Add support for a chain of stat caches in the FileManager, rather than > only supporting a single stat cache. The immediate benefit of this > change is that we can now generate a PCH/AST file when including > another PCH file; in the future, the chain of stat caches will likely > be useful with multiple levels of PCH files.
Nice! What is the status of PCH/AST generation when including a PCH file, are all known issues resolved? - Daniel > Added: > cfe/trunk/test/Index/c-index-pch.c > cfe/trunk/test/Index/c-index-pch.h > Modified: > cfe/trunk/include/clang/Basic/FileManager.h > cfe/trunk/include/clang/Frontend/PCHReader.h > cfe/trunk/lib/Basic/FileManager.cpp > cfe/trunk/lib/Frontend/CacheTokens.cpp > cfe/trunk/lib/Frontend/GeneratePCH.cpp > cfe/trunk/lib/Frontend/PCHReader.cpp > cfe/trunk/lib/Lex/PTHLexer.cpp > cfe/trunk/lib/Lex/Preprocessor.cpp > cfe/trunk/test/CMakeLists.txt > > Modified: cfe/trunk/include/clang/Basic/FileManager.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/FileManager.h?rev=84263&r1=84262&r2=84263&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Basic/FileManager.h (original) > +++ cfe/trunk/include/clang/Basic/FileManager.h Fri Oct 16 13:18:30 2009 > @@ -71,16 +71,38 @@ > } > }; > > -// FIXME: This is a lightweight shim that is used by FileManager to cache > -// 'stat' system calls. We will use it with PTH to identify if caching > -// stat calls in PTH files is a performance win. > +/// \brief Abstract interface for introducing a FileManager cache for 'stat' > +/// system calls, which is used by precompiled and pretokenized headers to > +/// improve performance. > class StatSysCallCache { > +protected: > + llvm::OwningPtr<StatSysCallCache> NextStatCache; > + > public: > virtual ~StatSysCallCache() {} > - virtual int stat(const char *path, struct stat *buf) = 0; > + virtual int stat(const char *path, struct stat *buf) { > + if (getNextStatCache()) > + return getNextStatCache()->stat(path, buf); > + > + return ::stat(path, buf); > + } > + > + /// \brief Sets the next stat call cache in the chain of stat caches. > + /// Takes ownership of the given stat cache. > + void setNextStatCache(StatSysCallCache *Cache) { > + NextStatCache.reset(Cache); > + } > + > + /// \brief Retrieve the next stat call cache in the chain. > + StatSysCallCache *getNextStatCache() { return NextStatCache.get(); } > + > + /// \brief Retrieve the next stat call cache in the chain, transferring > + /// ownership of this cache (and, transitively, all of the remaining > caches) > + /// to the caller. > + StatSysCallCache *takeNextStatCache() { return NextStatCache.take(); } > }; > > -/// \brief A stat listener that can be used by FileManager to keep > +/// \brief A stat "cache" that can be used by FileManager to keep > /// track of the results of stat() calls that occur throughout the > /// execution of the front end. > class MemorizeStatCalls : public StatSysCallCache { > @@ -144,13 +166,22 @@ > FileManager(); > ~FileManager(); > > - /// setStatCache - Installs the provided StatSysCallCache object within > - /// the FileManager. Ownership of this object is transferred to the > - /// FileManager. > - void setStatCache(StatSysCallCache *statCache) { > - StatCache.reset(statCache); > - } > - > + /// \brief Installs the provided StatSysCallCache object within > + /// the FileManager. > + /// > + /// Ownership of this object is transferred to the FileManager. > + /// > + /// \param statCache the new stat cache to install. Ownership of this > + /// object is transferred to the FileManager. > + /// > + /// \param AtBeginning whether this new stat cache must be installed at the > + /// beginning of the chain of stat caches. Otherwise, it will be added to > + /// the end of the chain. > + void addStatCache(StatSysCallCache *statCache, bool AtBeginning = false); > + > + /// \brief Removes the provided StatSysCallCache object from the file > manager. > + void removeStatCache(StatSysCallCache *statCache); > + > /// getDirectory - Lookup, cache, and verify the specified directory. This > /// returns null if the directory doesn't exist. > /// > > Modified: cfe/trunk/include/clang/Frontend/PCHReader.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=84263&r1=84262&r2=84263&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Frontend/PCHReader.h (original) > +++ cfe/trunk/include/clang/Frontend/PCHReader.h Fri Oct 16 13:18:30 2009 > @@ -169,6 +169,11 @@ > /// \brief The AST context into which we'll read the PCH file. > ASTContext *Context; > > + /// \brief The PCH stat cache installed by this PCHReader, if any. > + /// > + /// The dynamic type of this stat cache is always PCHStatCache > + void *StatCache; > + > /// \brief The AST consumer. > ASTConsumer *Consumer; > > @@ -492,8 +497,8 @@ > /// \param isysroot If non-NULL, the system include path specified by the > /// user. This is only used with relocatable PCH files. If non-NULL, > /// a relocatable PCH file will use the default path "/". > - PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, > - Diagnostic &Diags, const char *isysroot = 0); > + PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, > + Diagnostic &Diags, const char *isysroot = 0); > ~PCHReader(); > > /// \brief Load the precompiled header designated by the given file > > Modified: cfe/trunk/lib/Basic/FileManager.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/FileManager.cpp?rev=84263&r1=84262&r2=84263&view=diff > > ============================================================================== > --- cfe/trunk/lib/Basic/FileManager.cpp (original) > +++ cfe/trunk/lib/Basic/FileManager.cpp Fri Oct 16 13:18:30 2009 > @@ -149,6 +149,41 @@ > delete &UniqueFiles; > } > > +void FileManager::addStatCache(StatSysCallCache *statCache, bool > AtBeginning) { > + assert(statCache && "No stat cache provided?"); > + if (AtBeginning || StatCache.get() == 0) { > + statCache->setNextStatCache(StatCache.take()); > + StatCache.reset(statCache); > + return; > + } > + > + StatSysCallCache *LastCache = StatCache.get(); > + while (LastCache->getNextStatCache()) > + LastCache = LastCache->getNextStatCache(); > + > + LastCache->setNextStatCache(statCache); > +} > + > +void FileManager::removeStatCache(StatSysCallCache *statCache) { > + if (!statCache) > + return; > + > + if (StatCache.get() == statCache) { > + // This is the first stat cache. > + StatCache.reset(StatCache->takeNextStatCache()); > + return; > + } > + > + // Find the stat cache in the list. > + StatSysCallCache *PrevCache = StatCache.get(); > + while (PrevCache && PrevCache->getNextStatCache() != statCache) > + PrevCache = PrevCache->getNextStatCache(); > + if (PrevCache) > + PrevCache->setNextStatCache(statCache->getNextStatCache()); > + else > + assert(false && "Stat cache not found for removal"); > +} > + > /// getDirectory - Lookup, cache, and verify the specified directory. This > /// returns null if the directory doesn't exist. > /// > @@ -290,8 +325,8 @@ > } > > int MemorizeStatCalls::stat(const char *path, struct stat *buf) { > - int result = ::stat(path, buf); > - > + int result = StatSysCallCache::stat(path, buf); > + > if (result != 0) { > // Cache failed 'stat' results. > struct stat empty; > > Modified: cfe/trunk/lib/Frontend/CacheTokens.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CacheTokens.cpp?rev=84263&r1=84262&r2=84263&view=diff > > ============================================================================== > --- cfe/trunk/lib/Frontend/CacheTokens.cpp (original) > +++ cfe/trunk/lib/Frontend/CacheTokens.cpp Fri Oct 16 13:18:30 2009 > @@ -516,7 +516,7 @@ > ~StatListener() {} > > int stat(const char *path, struct stat *buf) { > - int result = ::stat(path, buf); > + int result = StatSysCallCache::stat(path, buf); > > if (result != 0) // Failed 'stat'. > PM.insert(path, PTHEntry()); > @@ -553,7 +553,8 @@ > PTHWriter PW(*OS, PP); > > // Install the 'stat' system call listener in the FileManager. > - PP.getFileManager().setStatCache(new StatListener(PW.getPM())); > + StatListener *StatCache = new StatListener(PW.getPM()); > + PP.getFileManager().addStatCache(StatCache, /*AtBeginning=*/true); > > // Lex through the entire file. This will populate SourceManager with > // all of the header information. > @@ -562,7 +563,7 @@ > do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); > > // Generate the PTH file. > - PP.getFileManager().setStatCache(0); > + PP.getFileManager().removeStatCache(StatCache); > PW.GeneratePTH(&MainFileName); > } > > > Modified: cfe/trunk/lib/Frontend/GeneratePCH.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/GeneratePCH.cpp?rev=84263&r1=84262&r2=84263&view=diff > > ============================================================================== > --- cfe/trunk/lib/Frontend/GeneratePCH.cpp (original) > +++ cfe/trunk/lib/Frontend/GeneratePCH.cpp Fri Oct 16 13:18:30 2009 > @@ -53,7 +53,7 @@ > // Install a stat() listener to keep track of all of the stat() > // calls. > StatCalls = new MemorizeStatCalls; > - PP.getFileManager().setStatCache(StatCalls); > + PP.getFileManager().addStatCache(StatCalls, /*AtBeginning=*/true); > } > > void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { > > Modified: cfe/trunk/lib/Frontend/PCHReader.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=84263&r1=84262&r2=84263&view=diff > > ============================================================================== > --- cfe/trunk/lib/Frontend/PCHReader.cpp (original) > +++ cfe/trunk/lib/Frontend/PCHReader.cpp Fri Oct 16 13:18:30 2009 > @@ -335,8 +335,6 @@ > PP.setCounterValue(Value); > } > > - > - > //===----------------------------------------------------------------------===// > // PCH reader implementation > //===----------------------------------------------------------------------===// > @@ -345,7 +343,7 @@ > const char *isysroot) > : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()), > FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()), > - SemaObj(0), PP(&PP), Context(Context), Consumer(0), > + SemaObj(0), PP(&PP), Context(Context), StatCache(0), Consumer(0), > IdentifierTableData(0), IdentifierLookupTable(0), > IdentifierOffsets(0), > MethodPoolLookupTable(0), MethodPoolLookupTableData(0), > @@ -362,7 +360,7 @@ > PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, > Diagnostic &Diags, const char *isysroot) > : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags), > - SemaObj(0), PP(0), Context(0), Consumer(0), > + SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0), > IdentifierTableData(0), IdentifierLookupTable(0), > IdentifierOffsets(0), > MethodPoolLookupTable(0), MethodPoolLookupTableData(0), > @@ -794,7 +792,7 @@ > // If we don't get a hit in the PCH file just forward to 'stat'. > if (I == Cache->end()) { > ++NumStatMisses; > - return ::stat(path, buf); > + return StatSysCallCache::stat(path, buf); > } > > ++NumStatHits; > @@ -1352,13 +1350,16 @@ > } > break; > > - case pch::STAT_CACHE: > - FileMgr.setStatCache( > - new PCHStatCache((const unsigned char *)BlobStart + > Record[0], > - (const unsigned char *)BlobStart, > - NumStatHits, NumStatMisses)); > + case pch::STAT_CACHE: { > + PCHStatCache *MyStatCache = > + new PCHStatCache((const unsigned char *)BlobStart + Record[0], > + (const unsigned char *)BlobStart, > + NumStatHits, NumStatMisses); > + FileMgr.addStatCache(MyStatCache); > + StatCache = MyStatCache; > break; > - > + } > + > case pch::EXT_VECTOR_DECLS: > if (!ExtVectorDecls.empty()) { > Error("duplicate EXT_VECTOR_DECLS record in PCH file"); > @@ -1466,7 +1467,8 @@ > SourceMgr.ClearPreallocatedSLocEntries(); > > // Remove the stat cache. > - FileMgr.setStatCache(0); > + if (StatCache) > + FileMgr.removeStatCache((PCHStatCache*)StatCache); > > return IgnorePCH; > } > > Modified: cfe/trunk/lib/Lex/PTHLexer.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PTHLexer.cpp?rev=84263&r1=84262&r2=84263&view=diff > > ============================================================================== > --- cfe/trunk/lib/Lex/PTHLexer.cpp (original) > +++ cfe/trunk/lib/Lex/PTHLexer.cpp Fri Oct 16 13:18:30 2009 > @@ -679,7 +679,8 @@ > CacheTy::iterator I = Cache.find(path); > > // If we don't get a hit in the PTH file just forward to 'stat'. > - if (I == Cache.end()) return ::stat(path, buf); > + if (I == Cache.end()) > + return StatSysCallCache::stat(path, buf); > > const PTHStatData& Data = *I; > > > Modified: cfe/trunk/lib/Lex/Preprocessor.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Preprocessor.cpp?rev=84263&r1=84262&r2=84263&view=diff > > ============================================================================== > --- cfe/trunk/lib/Lex/Preprocessor.cpp (original) > +++ cfe/trunk/lib/Lex/Preprocessor.cpp Fri Oct 16 13:18:30 2009 > @@ -122,7 +122,7 @@ > > void Preprocessor::setPTHManager(PTHManager* pm) { > PTH.reset(pm); > - FileMgr.setStatCache(PTH->createStatCache()); > + FileMgr.addStatCache(PTH->createStatCache()); > } > > void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const { > > Modified: cfe/trunk/test/CMakeLists.txt > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CMakeLists.txt?rev=84263&r1=84262&r2=84263&view=diff > > ============================================================================== > --- cfe/trunk/test/CMakeLists.txt (original) > +++ cfe/trunk/test/CMakeLists.txt Fri Oct 16 13:18:30 2009 > @@ -45,7 +45,7 @@ > ${LLVM_SOURCE_DIR}/utils/lit/lit.py > -sv ${CLANG_TEST_EXTRA_ARGS} > ${CMAKE_CURRENT_BINARY_DIR}/${testdir} > - DEPENDS clang clang-cc index-test > + DEPENDS clang clang-cc index-test c-index-test > COMMENT "Running Clang regression tests in ${testdir}") > endforeach() > > @@ -62,7 +62,7 @@ > ${LLVM_SOURCE_DIR}/utils/lit/lit.py > -sv ${CLANG_TEST_EXTRA_ARGS} > ${CMAKE_CURRENT_BINARY_DIR} > - DEPENDS clang clang-cc index-test > + DEPENDS clang clang-cc index-test c-index-test > COMMENT "Running Clang regression tests") > > add_custom_target(clang-c++tests > @@ -78,6 +78,6 @@ > ${LLVM_SOURCE_DIR}/utils/lit/lit.py > -sv ${CLANG_TEST_EXTRA_ARGS} > ${CMAKE_CURRENT_SOURCE_DIR}/../utils/C++Tests > - DEPENDS clang clang-cc index-test > + DEPENDS clang clang-cc index-test c-index-test > COMMENT "Running Clang regression tests") > endif() > > Added: cfe/trunk/test/Index/c-index-pch.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/c-index-pch.c?rev=84263&view=auto > > ============================================================================== > --- cfe/trunk/test/Index/c-index-pch.c (added) > +++ cfe/trunk/test/Index/c-index-pch.c Fri Oct 16 13:18:30 2009 > @@ -0,0 +1,7 @@ > +// RUN: clang-cc -emit-pch -x c -o %t.pch %S/c-index-pch.h && > +// RUN: clang-cc -include-pch %t.pch -x c -emit-pch -o %t.ast %s && > +// RUN: c-index-test %t.ast all | FileCheck -check-prefix=ALL %s > +// CHECK-ALL: FunctionDecl=foo > +// CHECK-ALL: VarDecl=bar > +// CHECK-ALL: FunctionDecl=wibble > +void wibble(int i); > > Added: cfe/trunk/test/Index/c-index-pch.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/c-index-pch.h?rev=84263&view=auto > > ============================================================================== > --- cfe/trunk/test/Index/c-index-pch.h (added) > +++ cfe/trunk/test/Index/c-index-pch.h Fri Oct 16 13:18:30 2009 > @@ -0,0 +1,7 @@ > +#ifndef C_INDEX_PCH_H > +#define C_INDEX_PCH_H > + > +void foo(int i, float f); > +extern int bar; > + > +#endif // C_INDEX_PCH_H > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
