19 #ifndef LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H 20 #define LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H 22 #include "llvm/ADT/DenseMap.h" 23 #include "llvm/ADT/DenseSet.h" 24 #include "llvm/ADT/PointerUnion.h" 25 #include "llvm/ADT/STLExtras.h" 26 #include "llvm/ADT/SmallVector.h" 27 #include "llvm/ADT/TinyPtrVector.h" 28 #include "llvm/ADT/iterator_range.h" 29 #include "llvm/Support/Endian.h" 30 #include "llvm/Support/EndianStream.h" 31 #include "llvm/Support/OnDiskHashTable.h" 32 #include "llvm/Support/raw_ostream.h" 38 namespace serialization {
57 template<
typename ReaderInfo,
typename WriterInfo>
67 OnDiskTable(
file_type File,
unsigned NumBuckets,
unsigned NumEntries,
71 Table(NumBuckets, NumEntries, Buckets, Payload, Base, InfoObj) {}
75 std::vector<file_type> Files;
76 llvm::DenseMap<internal_key_type, data_type> Data;
79 using Table = llvm::PointerUnion<OnDiskTable *, MergedTable *>;
80 using TableVector = llvm::TinyPtrVector<void *>;
91 llvm::TinyPtrVector<file_type> PendingOverrides;
93 struct AsOnDiskTable {
94 using result_type = OnDiskTable *;
96 result_type operator()(
void *
P)
const {
97 return Table::getFromOpaqueValue(P).template get<OnDiskTable *>();
101 using table_iterator =
102 llvm::mapped_iterator<TableVector::iterator, AsOnDiskTable>;
103 using table_range = llvm::iterator_range<table_iterator>;
106 table_range tables() {
107 auto Begin = Tables.begin(),
End = Tables.end();
108 if (getMergedTable())
110 return llvm::make_range(llvm::map_iterator(
Begin, AsOnDiskTable()),
111 llvm::map_iterator(
End, AsOnDiskTable()));
114 MergedTable *getMergedTable()
const {
116 return Tables.empty() ? nullptr : Table::getFromOpaqueValue(*Tables.begin())
117 .
template dyn_cast<MergedTable*>();
122 for (
auto *
T : tables())
124 if (
auto *M = getMergedTable())
129 void removeOverriddenTables() {
131 Files.insert(PendingOverrides.begin(), PendingOverrides.end());
133 auto ShouldRemove = [&Files](
void *
T) ->
bool {
134 auto *ODT = Table::getFromOpaqueValue(
T).template get<OnDiskTable *>();
135 bool Remove = Files.count(ODT->File);
140 Tables.erase(std::remove_if(tables().begin().getCurrent(), Tables.end(),
143 PendingOverrides.clear();
147 MergedTable *Merged = getMergedTable();
149 Merged =
new MergedTable;
153 for (
auto *ODT : tables()) {
154 auto &HT = ODT->Table;
155 Info &InfoObj = HT.getInfoObj();
157 for (
auto I = HT.data_begin(), E = HT.data_end(); I != E; ++I) {
158 auto *LocalPtr = I.getItem();
161 auto L = InfoObj.ReadKeyDataLength(LocalPtr);
164 InfoObj.ReadDataInto(Key, LocalPtr + L.first, L.second,
168 Merged->Files.push_back(ODT->File);
173 Tables.push_back(Table(Merged).getOpaqueValue());
180 : Tables(
std::move(O.Tables)),
181 PendingOverrides(
std::move(O.PendingOverrides)) {
189 Tables = std::move(O.Tables);
191 PendingOverrides = std::move(O.PendingOverrides);
199 using namespace llvm::support;
203 uint32_t BucketOffset = endian::readNext<uint32_t, little, unaligned>(Ptr);
206 uint32_t NumFiles = endian::readNext<uint32_t, little, unaligned>(Ptr);
210 OverriddenFiles.reserve(NumFiles);
211 for (; NumFiles != 0; --NumFiles)
212 OverriddenFiles.push_back(InfoObj.ReadFileRef(Ptr));
213 PendingOverrides.insert(PendingOverrides.end(), OverriddenFiles.begin(),
214 OverriddenFiles.end());
218 auto NumBucketsAndEntries =
219 OnDiskTable::HashTable::readNumBucketsAndEntries(Buckets);
222 Table NewTable =
new OnDiskTable(File, NumBucketsAndEntries.first,
223 NumBucketsAndEntries.second,
224 Buckets, Ptr, Data, std::move(InfoObj));
225 Tables.push_back(NewTable.getOpaqueValue());
232 if (!PendingOverrides.empty())
233 removeOverriddenTables();
235 if (Tables.size() >
static_cast<unsigned>(Info::MaxTables))
241 if (MergedTable *M = getMergedTable()) {
242 auto It = M->Data.find(Key);
243 if (It != M->Data.end())
249 for (
auto *ODT : tables()) {
250 auto &HT = ODT->Table;
251 auto It = HT.find_hashed(Key, KeyHash);
253 HT.getInfoObj().ReadDataInto(Key, It.getDataPtr(), It.getDataLen(),
266 if (!PendingOverrides.empty())
267 removeOverriddenTables();
269 if (MergedTable *M = getMergedTable()) {
270 for (
auto &KV : M->Data)
271 Info::MergeDataInto(KV.second, ResultBuilder);
274 for (
auto *ODT : tables()) {
275 auto &HT = ODT->Table;
276 Info &InfoObj = HT.getInfoObj();
277 for (
auto I = HT.data_begin(), E = HT.data_end(); I != E; ++I) {
278 auto *LocalPtr = I.getItem();
281 auto L = InfoObj.ReadKeyDataLength(LocalPtr);
283 InfoObj.ReadDataInto(Key, LocalPtr + L.first, L.second, ResultBuilder);
292 template<
typename ReaderInfo,
typename WriterInfo>
295 using Generator = llvm::OnDiskChainedHashTableGenerator<WriterInfo>;
302 void insert(
typename WriterInfo::key_type_ref Key,
303 typename WriterInfo::data_type_ref Data, WriterInfo &Info) {
304 Gen.insert(Key, Data, Info);
309 using namespace llvm::support;
311 llvm::raw_svector_ostream OutStream(Out);
315 endian::Writer<little> Writer(OutStream);
318 Writer.write<uint32_t>(0);
320 if (
auto *Merged = Base ? Base->getMergedTable() :
nullptr) {
322 Writer.write<uint32_t>(Merged->Files.size());
323 for (
const auto &F : Merged->Files)
324 Info.EmitFileRef(OutStream, F);
327 for (
auto &KV : Merged->Data) {
328 if (!Gen.contains(KV.first, Info))
329 Gen.insert(KV.first, Info.ImportData(KV.second), Info);
332 Writer.write<uint32_t>(0);
337 uint32_t BucketOffset = Gen.Emit(OutStream, Info);
340 endian::write32le(Out.data(), BucketOffset);
347 #endif // LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H typename clang::serialization::reader::ASTDeclContextNameLookupTrait ::data_type data_type
Writer for the on-disk hash table.
void insert(typename WriterInfo::key_type_ref Key, typename WriterInfo::data_type_ref Data, WriterInfo &Info)
data_type find(const external_key_type &EKey)
Find and read the lookup results for EKey.
A collection of on-disk hash tables, merged when relevant for performance.
MultiOnDiskHashTable()=default
const FunctionProtoType * T
const unsigned char * storage_type
A pointer to an on-disk representation of the hash table.
typename clang::serialization::reader::ASTDeclContextNameLookupTrait ::file_type file_type
A handle to a file, used when overriding tables.
unsigned ComputeHash(Selector Sel)
MultiOnDiskHashTable(MultiOnDiskHashTable &&O)
Dataflow Directional Tag Classes.
void emit(llvm::SmallVectorImpl< char > &Out, WriterInfo &Info, const BaseTable *Base)
MultiOnDiskHashTable & operator=(MultiOnDiskHashTable &&O)
typename clang::serialization::reader::ASTDeclContextNameLookupTrait ::internal_key_type internal_key_type
data_type findAll()
Read all the lookup results into a single value.
typename clang::serialization::reader::ASTDeclContextNameLookupTrait ::external_key_type external_key_type
void add(file_type File, storage_type Data, Info InfoObj=Info())
Add the table Data loaded from file File.
MultiOnDiskHashTableGenerator()
typename clang::serialization::reader::ASTDeclContextNameLookupTrait ::data_type_builder data_type_builder