OnDiskHashTable: Make the iterable version separate.

Currently the on disk hash table's key_iterator and data_iterator make
the assumption that the table data starts exactly four bytes after the
base of the table. This happens to be true for all of the tables we
currently iterate over, but not for all of the OnDiskHashTables we
currently use. For example, key_ and data_iterator would iterate over
meaningless data if they were used on the hash tables in PTHLexer.

We make the API safer by breaking this into two types. One doesn't
have the iterators, and the other must be told where the payload
starts.

llvm-svn: 206189
This commit is contained in:
Justin Bogner 2014-04-14 16:34:29 +00:00
parent 8c1f0818c0
commit da4e650e5c
6 changed files with 70 additions and 32 deletions

View File

@ -266,6 +266,41 @@ public:
iterator end() const { return iterator(); }
Info &getInfoObj() { return InfoObj; }
static OnDiskChainedHashTable* Create(const unsigned char* Buckets,
const unsigned char* const Base,
const Info &InfoObj = Info()) {
using namespace llvm::support;
assert(Buckets > Base);
assert((reinterpret_cast<uintptr_t>(Buckets) & 0x3) == 0 &&
"buckets should be 4-byte aligned.");
unsigned NumBuckets = endian::readNext<uint32_t, little, aligned>(Buckets);
unsigned NumEntries = endian::readNext<uint32_t, little, aligned>(Buckets);
return new OnDiskChainedHashTable<Info>(NumBuckets, NumEntries, Buckets,
Base, InfoObj);
}
};
template<typename Info>
class OnDiskIterableChainedHashTable : public OnDiskChainedHashTable<Info> {
const unsigned char *Payload;
public:
typedef OnDiskChainedHashTable<Info> base_type;
typedef typename base_type::internal_key_type internal_key_type;
typedef typename base_type::external_key_type external_key_type;
typedef typename base_type::data_type data_type;
OnDiskIterableChainedHashTable(unsigned NumBuckets, unsigned NumEntries,
const unsigned char *Buckets,
const unsigned char *Payload,
const unsigned char *Base,
const Info &InfoObj = Info())
: base_type(NumBuckets, NumEntries, Buckets, Base, InfoObj),
Payload(Payload) {}
/// \brief Iterates over all of the keys in the table.
class key_iterator {
const unsigned char *Ptr;
@ -329,7 +364,7 @@ public:
};
key_iterator key_begin() {
return key_iterator(Base + 4, getNumEntries(), &InfoObj);
return key_iterator(Payload, this->getNumEntries(), &this->getInfoObj());
}
key_iterator key_end() { return key_iterator(); }
@ -396,15 +431,13 @@ public:
};
data_iterator data_begin() {
return data_iterator(Base + 4, getNumEntries(), &InfoObj);
return data_iterator(Payload, this->getNumEntries(), &this->getInfoObj());
}
data_iterator data_end() { return data_iterator(); }
Info &getInfoObj() { return InfoObj; }
static OnDiskChainedHashTable *Create(const unsigned char *Buckets,
const unsigned char *const Base,
const Info &InfoObj = Info()) {
static OnDiskIterableChainedHashTable *
Create(const unsigned char *Buckets, const unsigned char *const Payload,
const unsigned char *const Base, const Info &InfoObj = Info()) {
using namespace llvm::support;
assert(Buckets > Base);
assert((reinterpret_cast<uintptr_t>(Buckets) & 0x3) == 0 &&
@ -412,8 +445,8 @@ public:
unsigned NumBuckets = endian::readNext<uint32_t, little, aligned>(Buckets);
unsigned NumEntries = endian::readNext<uint32_t, little, aligned>(Buckets);
return new OnDiskChainedHashTable<Info>(NumBuckets, NumEntries, Buckets,
Base, InfoObj);
return new OnDiskIterableChainedHashTable<Info>(
NumBuckets, NumEntries, Buckets, Payload, Base, InfoObj);
}
};

View File

@ -254,7 +254,7 @@ class ReadMethodPoolVisitor;
namespace reader {
class ASTIdentifierLookupTrait;
/// \brief The on-disk hash table used for the DeclContext's Name lookup table.
typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait>
typedef OnDiskIterableChainedHashTable<ASTDeclContextNameLookupTrait>
ASTDeclContextNameLookupTable;
}

View File

@ -29,6 +29,7 @@ class FileEntry;
class DeclContext;
class Module;
template<typename Info> class OnDiskChainedHashTable;
template<typename Info> class OnDiskIterableChainedHashTable;
namespace serialization {
@ -49,7 +50,7 @@ struct DeclContextInfo {
DeclContextInfo()
: NameLookupTableData(), LexicalDecls(), NumLexicalDecls() {}
OnDiskChainedHashTable<reader::ASTDeclContextNameLookupTrait>
OnDiskIterableChainedHashTable<reader::ASTDeclContextNameLookupTrait>
*NameLookupTableData; // an ASTDeclContextNameLookupTable.
const KindDeclIDPair *LexicalDecls;
unsigned NumLexicalDecls;

View File

@ -851,11 +851,11 @@ bool ASTReader::ReadDeclContextStorage(ModuleFile &M,
Error("Expected visible lookup table block");
return true;
}
Info.NameLookupTableData
= ASTDeclContextNameLookupTable::Create(
(const unsigned char *)Blob.data() + Record[0],
(const unsigned char *)Blob.data(),
ASTDeclContextNameLookupTrait(*this, M));
Info.NameLookupTableData = ASTDeclContextNameLookupTable::Create(
(const unsigned char *)Blob.data() + Record[0],
(const unsigned char *)Blob.data() + sizeof(uint32_t),
(const unsigned char *)Blob.data(),
ASTDeclContextNameLookupTrait(*this, M));
}
return false;
@ -2509,10 +2509,11 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
unsigned Idx = 0;
serialization::DeclID ID = ReadDeclID(F, Record, Idx);
ASTDeclContextNameLookupTable *Table =
ASTDeclContextNameLookupTable::Create(
(const unsigned char *)Blob.data() + Record[Idx++],
(const unsigned char *)Blob.data(),
ASTDeclContextNameLookupTrait(*this, F));
ASTDeclContextNameLookupTable::Create(
(const unsigned char *)Blob.data() + Record[Idx++],
(const unsigned char *)Blob.data() + sizeof(uint32_t),
(const unsigned char *)Blob.data(),
ASTDeclContextNameLookupTrait(*this, F));
if (ID == PREDEF_DECL_TRANSLATION_UNIT_ID) { // Is it the TU?
DeclContext *TU = Context.getTranslationUnitDecl();
F.DeclContextInfos[TU].NameLookupTableData = Table;
@ -2531,11 +2532,11 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case IDENTIFIER_TABLE:
F.IdentifierTableData = Blob.data();
if (Record[0]) {
F.IdentifierLookupTable
= ASTIdentifierLookupTable::Create(
(const unsigned char *)F.IdentifierTableData + Record[0],
(const unsigned char *)F.IdentifierTableData,
ASTIdentifierLookupTrait(*this, F));
F.IdentifierLookupTable = ASTIdentifierLookupTable::Create(
(const unsigned char *)F.IdentifierTableData + Record[0],
(const unsigned char *)F.IdentifierTableData + sizeof(uint32_t),
(const unsigned char *)F.IdentifierTableData,
ASTIdentifierLookupTrait(*this, F));
PP.getIdentifierTable().setExternalIdentifierLookup(this);
}

View File

@ -140,7 +140,7 @@ public:
/// \brief The on-disk hash table used to contain information about
/// all of the identifiers in the program.
typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait>
typedef OnDiskIterableChainedHashTable<ASTIdentifierLookupTrait>
ASTIdentifierLookupTable;
/// \brief Class that performs lookup for a selector's entries in the global

View File

@ -114,7 +114,8 @@ public:
}
};
typedef OnDiskChainedHashTable<IdentifierIndexReaderTrait> IdentifierIndexTable;
typedef OnDiskIterableChainedHashTable<IdentifierIndexReaderTrait>
IdentifierIndexTable;
}
@ -210,9 +211,9 @@ GlobalModuleIndex::GlobalModuleIndex(llvm::MemoryBuffer *Buffer,
// Wire up the identifier index.
if (Record[0]) {
IdentifierIndex = IdentifierIndexTable::Create(
(const unsigned char *)Blob.data() + Record[0],
(const unsigned char *)Blob.data(),
IdentifierIndexReaderTrait());
(const unsigned char *)Blob.data() + Record[0],
(const unsigned char *)Blob.data() + sizeof(uint32_t),
(const unsigned char *)Blob.data(), IdentifierIndexReaderTrait());
}
break;
}
@ -591,11 +592,13 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
// Handle the identifier table
if (State == ASTBlock && Code == IDENTIFIER_TABLE && Record[0] > 0) {
typedef OnDiskChainedHashTable<InterestingASTIdentifierLookupTrait>
InterestingIdentifierTable;
typedef
OnDiskIterableChainedHashTable<InterestingASTIdentifierLookupTrait>
InterestingIdentifierTable;
std::unique_ptr<InterestingIdentifierTable> Table(
InterestingIdentifierTable::Create(
(const unsigned char *)Blob.data() + Record[0],
(const unsigned char *)Blob.data() + sizeof(uint32_t),
(const unsigned char *)Blob.data()));
for (InterestingIdentifierTable::data_iterator D = Table->data_begin(),
DEnd = Table->data_end();