On Oct 19, 2009, at 6:02 PM, Daniel Dunbar <[email protected]> wrote:
> 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? The only known issue remaining is that unreferenced macros in the PCH file won't be emitted to the AST. Well, that, and I haven't crammed much code through the PCH -> AST path. - Doug > - 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-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
