PTH: Embed a persistentID side-table in the PTH file that is sorted in the
lexical order of the corresponding identifier strings. This will be used for a forthcoming optimization. This slows down PTH generation time by 7%. We can revert this change if the optimization proves to not be valuable. llvm-svn: 62248
This commit is contained in:
parent
960b5bc7c1
commit
bef9fc2240
|
@ -102,7 +102,7 @@ class VISIBILITY_HIDDEN PTHWriter {
|
||||||
for ( ; I != E ; ++I) Out << *I;
|
for ( ; I != E ; ++I) Out << *I;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Offset,Offset> EmitIdentifierTable();
|
std::pair<Offset,std::pair<Offset, Offset> > EmitIdentifierTable();
|
||||||
Offset EmitFileTable();
|
Offset EmitFileTable();
|
||||||
PCHEntry LexTokens(Lexer& L);
|
PCHEntry LexTokens(Lexer& L);
|
||||||
void EmitCachedSpellings();
|
void EmitCachedSpellings();
|
||||||
|
@ -171,57 +171,66 @@ namespace {
|
||||||
struct VISIBILITY_HIDDEN IDData {
|
struct VISIBILITY_HIDDEN IDData {
|
||||||
const IdentifierInfo* II;
|
const IdentifierInfo* II;
|
||||||
uint32_t FileOffset;
|
uint32_t FileOffset;
|
||||||
const IdentifierTable::const_iterator::value_type* Str;
|
};
|
||||||
|
|
||||||
|
class VISIBILITY_HIDDEN CompareIDDataIndex {
|
||||||
|
IDData* Table;
|
||||||
|
public:
|
||||||
|
CompareIDDataIndex(IDData* table) : Table(table) {}
|
||||||
|
|
||||||
|
bool operator()(unsigned i, unsigned j) const {
|
||||||
|
// Assume that IdentifierInfo::getName() returns a '\0' terminated string.
|
||||||
|
return strcmp(Table[i].II->getName(), Table[j].II->getName()) < 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() {
|
std::pair<Offset,std::pair<Offset,Offset> >
|
||||||
|
PTHWriter::EmitIdentifierTable() {
|
||||||
const IdentifierTable& T = PP.getIdentifierTable();
|
llvm::BumpPtrAllocator Alloc;
|
||||||
|
|
||||||
// Build an inverse map from persistent IDs -> IdentifierInfo*.
|
// Build an inverse map from persistent IDs -> IdentifierInfo*.
|
||||||
typedef std::vector<IDData> InverseIDMap;
|
IDData* IIDMap = Alloc.Allocate<IDData>(idcount);
|
||||||
InverseIDMap IIDMap;
|
|
||||||
IIDMap.resize(idcount);
|
|
||||||
|
|
||||||
// Generate mapping from persistent IDs -> IdentifierInfo*.
|
// Generate mapping from persistent IDs -> IdentifierInfo*.
|
||||||
for (IDMap::iterator I=IM.begin(), E=IM.end(); I!=E; ++I) {
|
for (IDMap::iterator I=IM.begin(), E=IM.end(); I!=E; ++I) {
|
||||||
// Decrement by 1 because we are using a vector for the lookup and
|
// Decrement by 1 because we are using a vector for the lookup and
|
||||||
// 0 is reserved for NULL.
|
// 0 is reserved for NULL.
|
||||||
assert(I->second > 0);
|
assert(I->second > 0);
|
||||||
assert(I->second-1 < IIDMap.size());
|
assert(I->second-1 < idcount);
|
||||||
IIDMap[I->second-1].II = I->first;
|
unsigned idx = I->second-1;
|
||||||
}
|
IIDMap[idx].II = I->first;
|
||||||
|
}
|
||||||
// Get the string data associated with the IdentifierInfo.
|
|
||||||
for (IdentifierTable::const_iterator I=T.begin(), E=T.end(); I!=E; ++I) {
|
|
||||||
IDMap::iterator IDI = IM.find(&(I->getValue()));
|
|
||||||
if (IDI == IM.end()) continue;
|
|
||||||
IIDMap[IDI->second-1].Str = &(*I);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// We want to write out the strings in lexical order to support binary
|
||||||
|
// search of strings to identifiers. Create such a table.
|
||||||
|
unsigned *LexicalOrder = Alloc.Allocate<unsigned>(idcount);
|
||||||
|
for (unsigned i = 0; i < idcount ; ++i ) LexicalOrder[i] = i;
|
||||||
|
std::sort(LexicalOrder, LexicalOrder+idcount, CompareIDDataIndex(IIDMap));
|
||||||
|
|
||||||
|
// Write out the lexically-sorted table of persistent ids.
|
||||||
|
Offset LexicalOff = Out.tell();
|
||||||
|
for (unsigned i = 0; i < idcount ; ++i) Emit32(LexicalOrder[i]);
|
||||||
|
|
||||||
|
// Write out the string data itself.
|
||||||
Offset DataOff = Out.tell();
|
Offset DataOff = Out.tell();
|
||||||
|
|
||||||
for (InverseIDMap::iterator I=IIDMap.begin(), E=IIDMap.end(); I!=E; ++I) {
|
for (unsigned i = 0; i < idcount; ++i) {
|
||||||
// Record the location for this data.
|
IDData& d = IIDMap[i];
|
||||||
I->FileOffset = Out.tell();
|
d.FileOffset = Out.tell(); // Record the location for this data.
|
||||||
// Write out the keyword.
|
unsigned len = d.II->getLength(); // Write out the string length.
|
||||||
unsigned len = I->Str->getKeyLength();
|
|
||||||
Emit32(len);
|
Emit32(len);
|
||||||
const char* buf = I->Str->getKeyData();
|
const char* buf = d.II->getName(); // Write out the string data.
|
||||||
EmitBuf(buf, buf+len);
|
EmitBuf(buf, buf+len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now emit the table mapping from persistent IDs to PTH file offsets.
|
// Now emit the table mapping from persistent IDs to PTH file offsets.
|
||||||
Offset IDOff = Out.tell();
|
Offset IDOff = Out.tell();
|
||||||
|
Emit32(idcount); // Emit the number of identifiers.
|
||||||
// Emit the number of identifiers.
|
for (unsigned i = 0 ; i < idcount; ++i) Emit32(IIDMap[i].FileOffset);
|
||||||
Emit32(idcount);
|
|
||||||
|
|
||||||
for (InverseIDMap::iterator I=IIDMap.begin(), E=IIDMap.end(); I!=E; ++I)
|
|
||||||
Emit32(I->FileOffset);
|
|
||||||
|
|
||||||
return std::make_pair(DataOff, IDOff);
|
return std::make_pair(DataOff, std::make_pair(IDOff, LexicalOff));
|
||||||
}
|
}
|
||||||
|
|
||||||
Offset PTHWriter::EmitFileTable() {
|
Offset PTHWriter::EmitFileTable() {
|
||||||
|
@ -473,7 +482,8 @@ void PTHWriter::GeneratePTH() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write out the identifier table.
|
// Write out the identifier table.
|
||||||
std::pair<Offset,Offset> IdTableOff = EmitIdentifierTable();
|
const std::pair<Offset, std::pair<Offset,Offset> >& IdTableOff
|
||||||
|
= EmitIdentifierTable();
|
||||||
|
|
||||||
// Write out the cached strings table.
|
// Write out the cached strings table.
|
||||||
EmitCachedSpellings();
|
EmitCachedSpellings();
|
||||||
|
@ -483,7 +493,8 @@ void PTHWriter::GeneratePTH() {
|
||||||
|
|
||||||
// Finally, write out the offset table at the end.
|
// Finally, write out the offset table at the end.
|
||||||
Emit32(IdTableOff.first);
|
Emit32(IdTableOff.first);
|
||||||
Emit32(IdTableOff.second);
|
Emit32(IdTableOff.second.first);
|
||||||
|
Emit32(IdTableOff.second.second);
|
||||||
Emit32(FileTableOff);
|
Emit32(FileTableOff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -538,11 +538,12 @@ PTHManager* PTHManager::Create(const std::string& file, Preprocessor& PP) {
|
||||||
// Compute the address of the index table at the end of the PTH file.
|
// Compute the address of the index table at the end of the PTH file.
|
||||||
// This table contains the offset of the file lookup table, the
|
// This table contains the offset of the file lookup table, the
|
||||||
// persistent ID -> identifer data table.
|
// persistent ID -> identifer data table.
|
||||||
const char* EndTable = BufEnd - sizeof(uint32_t)*3;
|
// FIXME: We should just embed this offset in the PTH file.
|
||||||
|
const char* EndTable = BufEnd - sizeof(uint32_t)*4;
|
||||||
|
|
||||||
// Construct the file lookup table. This will be used for mapping from
|
// Construct the file lookup table. This will be used for mapping from
|
||||||
// FileEntry*'s to cached tokens.
|
// FileEntry*'s to cached tokens.
|
||||||
const char* FileTableOffset = EndTable + sizeof(uint32_t)*2;
|
const char* FileTableOffset = EndTable + sizeof(uint32_t)*3;
|
||||||
const char* FileTable = BufBeg + Read32(FileTableOffset);
|
const char* FileTable = BufBeg + Read32(FileTableOffset);
|
||||||
|
|
||||||
if (!(FileTable > BufBeg && FileTable < BufEnd)) {
|
if (!(FileTable > BufBeg && FileTable < BufEnd)) {
|
||||||
|
|
Loading…
Reference in New Issue