14 #ifndef LLVM_SUPPORT_ONDISKHASHTABLE_H
15 #define LLVM_SUPPORT_ONDISKHASHTABLE_H
19 #include "llvm/Support/DataTypes.h"
62 typename Info::key_type Key;
65 const typename Info::hash_value_type
Hash;
67 Item(
typename Info::key_type_ref Key,
typename Info::data_type_ref
Data,
69 : Key(Key),
Data(Data), Next(
nullptr),
Hash(InfoObj.ComputeHash(Key)) {}
73 offset_type NumBuckets;
74 offset_type NumEntries;
88 void insert(Bucket *Buckets,
size_t Size, Item *E) {
89 Bucket &B = Buckets[E->Hash & (Size - 1)];
96 void resize(
size_t NewSize) {
97 Bucket *NewBuckets = (Bucket *)std::calloc(NewSize,
sizeof(Bucket));
99 for (
size_t I = 0;
I < NumBuckets; ++
I)
100 for (Item *E = Buckets[
I].Head; E;) {
103 insert(NewBuckets, NewSize, E);
108 NumBuckets = NewSize;
109 Buckets = NewBuckets;
114 void insert(
typename Info::key_type_ref Key,
115 typename Info::data_type_ref
Data) {
117 insert(Key, Data, InfoObj);
123 void insert(
typename Info::key_type_ref Key,
124 typename Info::data_type_ref
Data, Info &InfoObj) {
127 if (4 * NumEntries >= 3 * NumBuckets)
128 resize(NumBuckets * 2);
129 insert(Buckets, NumBuckets,
new (BA.
Allocate()) Item(Key, Data, InfoObj));
135 return Emit(Out, InfoObj);
142 using namespace llvm::support;
146 for (offset_type
I = 0;
I < NumBuckets; ++
I) {
147 Bucket &B = Buckets[
I];
153 assert(B.Off &&
"Cannot write a bucket at offset 0. Please add padding.");
156 LE.
write<uint16_t>(B.Length);
157 assert(B.Length != 0 &&
"Bucket has a head but zero length?");
160 for (Item *
I = B.Head;
I;
I =
I->Next) {
161 LE.
write<
typename Info::hash_value_type>(
I->Hash);
162 const std::pair<offset_type, offset_type> &Len =
163 InfoObj.EmitKeyDataLength(Out,
I->Key,
I->Data);
164 InfoObj.EmitKey(Out,
I->Key, Len.first);
165 InfoObj.EmitData(Out,
I->Key,
I->Data, Len.second);
170 offset_type TableOff = Out.
tell();
174 LE.
write<uint8_t>(0);
177 LE.
write<offset_type>(NumBuckets);
178 LE.
write<offset_type>(NumEntries);
179 for (offset_type
I = 0;
I < NumBuckets; ++
I)
180 LE.
write<offset_type>(Buckets[
I].Off);
190 Buckets = (Bucket *)std::calloc(NumBuckets,
sizeof(Bucket));
237 const unsigned char *
const Buckets;
238 const unsigned char *
const Base;
249 const unsigned char *Buckets,
250 const unsigned char *Base,
251 const Info &InfoObj = Info())
252 : NumBuckets(NumBuckets), NumEntries(NumEntries), Buckets(Buckets),
253 Base(Base), InfoObj(InfoObj) {
254 assert((reinterpret_cast<uintptr_t>(Buckets) & 0x3) == 0 &&
255 "'buckets' must have a 4-byte alignment");
260 const unsigned char *
getBase()
const {
return Base; }
263 bool isEmpty()
const {
return NumEntries == 0; }
267 const unsigned char *
const Data;
275 : Key(K),
Data(D), Len(L), InfoObj(InfoObj) {}
286 return find_hashed(IKey, KeyHash, InfoPtr);
291 Info *InfoPtr =
nullptr) {
292 using namespace llvm::support;
299 const unsigned char *Bucket = Buckets +
sizeof(
offset_type) * Idx;
301 offset_type Offset = endian::readNext<offset_type, little, aligned>(Bucket);
304 const unsigned char *Items = Base + Offset;
308 unsigned Len = endian::readNext<uint16_t, little, unaligned>(Items);
310 for (
unsigned i = 0; i < Len; ++i) {
313 endian::readNext<hash_value_type, little, unaligned>(Items);
316 const std::pair<offset_type, offset_type> &L =
317 Info::ReadKeyDataLength(Items);
321 if (ItemHash != KeyHash) {
328 InfoPtr->ReadKey((
const unsigned char *
const)Items, L.first);
331 if (!InfoPtr->EqualKey(X, IKey)) {
337 return iterator(X, Items + L.first, L.second, InfoPtr);
357 const unsigned char *
const Base,
358 const Info &InfoObj = Info()) {
359 using namespace llvm::support;
360 assert(Buckets > Base);
361 assert((reinterpret_cast<uintptr_t>(Buckets) & 0x3) == 0 &&
362 "buckets should be 4-byte aligned.");
365 endian::readNext<offset_type, little, aligned>(Buckets);
367 endian::readNext<offset_type, little, aligned>(Buckets);
376 template <
typename Info>
378 const unsigned char *Payload;
389 const unsigned char *Buckets,
390 const unsigned char *Payload,
391 const unsigned char *Base,
392 const Info &InfoObj = Info())
393 :
base_type(NumBuckets, NumEntries, Buckets, Base, InfoObj),
398 const unsigned char *Ptr;
408 : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries),
411 : Ptr(nullptr), NumItemsInBucketLeft(0), NumEntriesLeft(0),
415 return X.NumEntriesLeft == Y.NumEntriesLeft;
418 return X.NumEntriesLeft != Y.NumEntriesLeft;
422 using namespace llvm::support;
423 if (!NumItemsInBucketLeft) {
426 NumItemsInBucketLeft =
427 endian::readNext<uint16_t, little, unaligned>(Ptr);
431 const std::pair<offset_type, offset_type> &L =
432 Info::ReadKeyDataLength(Ptr);
433 Ptr += L.first + L.second;
434 assert(NumItemsInBucketLeft);
435 --NumItemsInBucketLeft;
436 assert(NumEntriesLeft);
445 const unsigned char *LocalPtr = Ptr;
446 if (!NumItemsInBucketLeft)
451 const std::pair<offset_type, offset_type> &L =
452 Info::ReadKeyDataLength(LocalPtr);
456 return InfoObj->GetExternalKey(Key);
461 return key_iterator(Payload, this->getNumEntries(), &this->getInfoObj());
471 const unsigned char *Ptr;
481 : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries),
484 : Ptr(nullptr), NumItemsInBucketLeft(0), NumEntriesLeft(0),
488 return X.NumEntriesLeft == NumEntriesLeft;
491 return X.NumEntriesLeft != NumEntriesLeft;
495 using namespace llvm::support;
496 if (!NumItemsInBucketLeft) {
499 NumItemsInBucketLeft =
500 endian::readNext<uint16_t, little, unaligned>(Ptr);
504 const std::pair<offset_type, offset_type> &L =
505 Info::ReadKeyDataLength(Ptr);
506 Ptr += L.first + L.second;
507 assert(NumItemsInBucketLeft);
508 --NumItemsInBucketLeft;
509 assert(NumEntriesLeft);
518 const unsigned char *LocalPtr = Ptr;
519 if (!NumItemsInBucketLeft)
524 const std::pair<offset_type, offset_type> &L =
525 Info::ReadKeyDataLength(LocalPtr);
529 return InfoObj->ReadData(Key, LocalPtr + L.first, L.second);
534 return data_iterator(Payload, this->getNumEntries(), &this->getInfoObj());
556 Create(
const unsigned char *Buckets,
const unsigned char *
const Payload,
557 const unsigned char *
const Base,
const Info &InfoObj = Info()) {
558 using namespace llvm::support;
559 assert(Buckets > Base);
560 assert((reinterpret_cast<uintptr_t>(Buckets) & 0x3) == 0 &&
561 "buckets should be 4-byte aligned.");
564 endian::readNext<offset_type, little, aligned>(Buckets);
566 endian::readNext<offset_type, little, aligned>(Buckets);
568 NumBuckets, NumEntries, Buckets, Payload, Base, InfoObj);
OnDiskChainedHashTable(offset_type NumBuckets, offset_type NumEntries, const unsigned char *Buckets, const unsigned char *Base, const Info &InfoObj=Info())
offset_type getNumEntries() const
OnDiskChainedHashTable< Info > base_type
void write(value_type Val)
const unsigned char * getBase() const
Info::offset_type offset_type
bool operator==(const iterator &X) const
Info::external_key_type external_key_type
Iterates over all of the keys in the table.
offset_type getNumBuckets() const
bool operator!=(const data_iterator &X) const
This file defines the MallocAllocator and BumpPtrAllocator interfaces.
bool operator!=(const iterator &X) const
data_iterator & operator++()
InstrProfLookupTrait::data_type data_type
InstrProfLookupTrait::offset_type offset_type
OnDiskChainedHashTableGenerator()
uint64_t tell() const
tell - Return the current offset with the file.
data_type operator*() const
bool operator==(const data_iterator &X) const
Iterates over all the entries in the table, returning the data.
iterator(const internal_key_type K, const unsigned char *D, offset_type L, Info *InfoObj)
base_type::external_key_type external_key_type
data_iterator operator++(int)
friend bool operator==(const key_iterator &X, const key_iterator &Y)
void insert(typename Info::key_type_ref Key, typename Info::data_type_ref Data)
Insert an entry into the table.
OnDiskIterableChainedHashTable(offset_type NumBuckets, offset_type NumEntries, const unsigned char *Buckets, const unsigned char *Payload, const unsigned char *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())
Create the hash table.
base_type::offset_type offset_type
base_type::data_type data_type
data_iterator data_begin()
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
value_type operator*() const
void insert(typename Info::key_type_ref Key, typename Info::data_type_ref Data, Info &InfoObj)
Insert an entry into the table.
T * Allocate(size_t num=1)
Allocate space for an array of objects without constructing them.
key_iterator(const unsigned char *const Ptr, offset_type NumEntries, Info *InfoObj)
iterator_range< data_iterator > data()
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
offset_type Emit(raw_ostream &Out)
Emit the table to Out, which must not be at offset 0.
iterator_range< key_iterator > keys()
external_key_type value_type
Provides lookup on an on disk hash table.
friend bool operator!=(const key_iterator &X, const key_iterator &Y)
Info::hash_value_type hash_value_type
key_iterator & operator++()
A range adaptor for a pair of iterators.
Info::internal_key_type internal_key_type
key_iterator operator++(int)
base_type::internal_key_type internal_key_type
Generates an on disk hash table.
Adapter to write values to a stream in a particular byte order.
iterator find(const external_key_type &EKey, Info *InfoPtr=nullptr)
Look up the stored data for a particular key.
offset_type Emit(raw_ostream &Out, Info &InfoObj)
Emit the table to Out, which must not be at offset 0.
data_iterator(const unsigned char *const Ptr, offset_type NumEntries, Info *InfoObj)
value_type operator*() const
static OnDiskChainedHashTable * Create(const unsigned char *Buckets, const unsigned char *const Base, const Info &InfoObj=Info())
Create the hash table.
iterator find_hashed(const internal_key_type &IKey, hash_value_type KeyHash, Info *InfoPtr=nullptr)
Look up the stored data for a particular key with a known hash.
const unsigned char * getBuckets() const
uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
This class implements an extremely fast bulk output stream that can only output to a stream...
std::string Hash(const Unit &U)
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml","ocaml 3.10-compatible collector")
base_type::hash_value_type hash_value_type
~OnDiskChainedHashTableGenerator()
Info::data_type data_type
Provides lookup and iteration over an on disk hash table.