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)

llvm-svn: 61913
This commit is contained in:
Ted Kremenek 2009-01-08 04:30:32 +00:00
parent 145a7cfa85
commit d5e6e16d0d
3 changed files with 75 additions and 5 deletions

View File

@ -41,6 +41,13 @@ class PTHLexer : public PreprocessorLexer {
/// CurPPCondPtr - Pointer inside PPCond that refers to the next entry /// CurPPCondPtr - Pointer inside PPCond that refers to the next entry
/// to process when doing quick skipping of preprocessor blocks. /// to process when doing quick skipping of preprocessor blocks.
const char* CurPPCondPtr; 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 PTHLexer(const PTHLexer&); // DO NOT IMPLEMENT
void operator=(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. /// Create a PTHLexer for the specified token stream.
PTHLexer(Preprocessor& pp, SourceLocation fileloc, const char* D, PTHLexer(Preprocessor& pp, SourceLocation fileloc, const char* D,
const char* ppcond, PTHManager& PM); const char* ppcond, const char* spellingTable, unsigned numSpellings,
PTHManager& PM);
~PTHLexer() {} ~PTHLexer() {}

View File

@ -69,6 +69,10 @@ class PTHManager {
/// GetIdentifierInfo - Used by PTHManager to reconstruct IdentifierInfo /// GetIdentifierInfo - Used by PTHManager to reconstruct IdentifierInfo
/// objects from the PTH file. /// objects from the PTH file.
IdentifierInfo* GetIdentifierInfo(unsigned); IdentifierInfo* GetIdentifierInfo(unsigned);
/// GetSpelling - Used by PTHLexer classes to get the cached spelling
/// for a token.
unsigned GetSpelling(unsigned PTHOffset, const char*& Buffer);
public: public:

View File

@ -49,9 +49,13 @@ static inline uint32_t Read32(const char*& data) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
PTHLexer::PTHLexer(Preprocessor& pp, SourceLocation fileloc, const char* D, 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), : 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) { void PTHLexer::Lex(Token& Tok) {
LexNextToken: LexNextToken:
@ -285,8 +289,55 @@ SourceLocation PTHLexer::getSourceLocation() {
return SourceLocation::getFileLoc(FileID, offset); 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) { 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(); const char* ppcond = Buf->getBufferStart() + FileData.getPPCondOffset();
uint32_t len = Read32(ppcond); uint32_t len = Read32(ppcond);
if (len == 0) ppcond = 0; 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()); assert(data < Buf->getBufferEnd());
return new PTHLexer(PP, SourceLocation::getFileLoc(FileID, 0), data, ppcond, return new PTHLexer(PP, SourceLocation::getFileLoc(FileID, 0), data, ppcond,
*this); spellingTable, len, *this);
} }