From: Ted Kremenek Date: Thu, 8 Jan 2009 04:30:32 +0000 (+0000) Subject: PTH: Hook up getSpelling() caching in PTHLexer. This results in a nice X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=32a8ad526f9bc00539f000a2dd1ac3e167db61c1;p=clang PTH: Hook up getSpelling() caching in PTHLexer. This results in a nice performance gain. Here's what we see for -Eonly on Cocoa.h (using PTH): - wall time decreases by 21% (26% speedup overall) - system time decreases by 35% - user time decreases by 6% These reductions are due to not paging source files just to get spellings for literals. The solution in place doesn't appear to be 100% yet, as we still see some of the pages for source files getting mapped in. Using -print-stats, we see that SourceManager maps in 7179K less bytes of source text (reduction of 75%). Will investigate why the remaining 25% are getting paged in. With these changes, here's how PTH compares to non-PTH on Cocoa.h: -Eonly: PTH takes 64% of the time as non-PTH (54% speedup) -fsyntax-only: PTH takes 89% of the time as non-PTH (11% speedup) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61913 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h index 8e23924abc..8928ad4aa8 100644 --- a/include/clang/Lex/PTHLexer.h +++ b/include/clang/Lex/PTHLexer.h @@ -41,6 +41,13 @@ class PTHLexer : public PreprocessorLexer { /// 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; PTHLexer(const PTHLexer&); // DO NOT IMPLEMENT void operator=(const PTHLexer&); // DO NOT IMPLEMENT @@ -57,7 +64,8 @@ public: /// Create a PTHLexer for the specified token stream. PTHLexer(Preprocessor& pp, SourceLocation fileloc, const char* D, - const char* ppcond, PTHManager& PM); + const char* ppcond, const char* spellingTable, unsigned numSpellings, + PTHManager& PM); ~PTHLexer() {} diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h index 1d023e096c..fc814d0063 100644 --- a/include/clang/Lex/PTHManager.h +++ b/include/clang/Lex/PTHManager.h @@ -69,6 +69,10 @@ class PTHManager { /// GetIdentifierInfo - Used by PTHManager to reconstruct IdentifierInfo /// 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); public: diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp index ef7cfb18d6..cfd5c6492a 100644 --- a/lib/Lex/PTHLexer.cpp +++ b/lib/Lex/PTHLexer.cpp @@ -49,9 +49,13 @@ static inline uint32_t Read32(const char*& data) { //===----------------------------------------------------------------------===// PTHLexer::PTHLexer(Preprocessor& pp, SourceLocation fileloc, const char* D, - const char* ppcond, PTHManager& PM) + const char* ppcond, + const char* spellingTable, unsigned NumSpellings, + PTHManager& PM) : PreprocessorLexer(&pp, fileloc), TokBuf(D), CurPtr(D), LastHashTokPtr(0), - PPCond(ppcond), CurPPCondPtr(ppcond), PTHMgr(PM) {} + PPCond(ppcond), CurPPCondPtr(ppcond), + SpellingTable(spellingTable), SpellingsLeft(NumSpellings), + PTHMgr(PM) {} void PTHLexer::Lex(Token& Tok) { LexNextToken: @@ -285,8 +289,55 @@ SourceLocation PTHLexer::getSourceLocation() { return SourceLocation::getFileLoc(FileID, offset); } +unsigned PTHManager::GetSpelling(unsigned PTHOffset, const char *& Buffer) { + const char* p = Buf->getBufferStart() + PTHOffset; + assert(p < Buf->getBufferEnd()); + + // The string is prefixed by 16 bits for its length, followed by the string + // itself. + unsigned len = ((unsigned) ((uint8_t) p[0])) + | (((unsigned) ((uint8_t) p[1])) << 8); + + Buffer = p + 2; + return len; +} + unsigned PTHLexer::getSpelling(SourceLocation sloc, const char *&Buffer) { - return 0; + const char* p = SpellingTable; + SourceManager& SM = PP->getSourceManager(); + unsigned fpos = SM.getFullFilePos(SM.getPhysicalLoc(sloc)); + unsigned len = 0; + + while (SpellingsLeft) { + 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) + break; + + --SpellingsLeft; + + // Did we find a matching token offset for this spelling? + if (TokOffset == fpos) { + 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); + + len = PTHMgr.GetSpelling(SpellingPTHOffset, Buffer); + break; + } + + // No match. Keep on looking. + p += sizeof(uint32_t)*2; + } + + SpellingTable = p; + return len; } //===----------------------------------------------------------------------===// @@ -478,8 +529,15 @@ PTHLexer* PTHManager::CreateLexer(unsigned FileID, const FileEntry* FE) { const char* ppcond = Buf->getBufferStart() + FileData.getPPCondOffset(); uint32_t len = Read32(ppcond); if (len == 0) ppcond = 0; + + // Get the location of the spelling table. + const char* spellingTable = Buf->getBufferStart() + + FileData.getSpellingOffset(); + + len = Read32(spellingTable); + if (len == 0) spellingTable = 0; assert(data < Buf->getBufferEnd()); return new PTHLexer(PP, SourceLocation::getFileLoc(FileID, 0), data, ppcond, - *this); + spellingTable, len, *this); }