18 #ifndef LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H
19 #define LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H
21 #include "llvm/ADT/PointerUnion.h"
22 #include "llvm/Support/EndianStream.h"
23 #include "llvm/Support/OnDiskHashTable.h"
26 namespace serialization {
52 OnDiskTable(
file_type File,
unsigned NumBuckets,
unsigned NumEntries,
56 Table(NumBuckets, NumEntries, Buckets, Payload, Base, InfoObj) {}
60 std::vector<file_type> Files;
61 llvm::DenseMap<internal_key_type, data_type> Data;
64 typedef llvm::PointerUnion<OnDiskTable*, MergedTable*> Table;
65 typedef llvm::TinyPtrVector<void*> TableVector;
76 llvm::TinyPtrVector<file_type> PendingOverrides;
78 struct AsOnDiskTable {
79 typedef OnDiskTable *result_type;
80 result_type operator()(
void *
P)
const {
81 return Table::getFromOpaqueValue(P).template get<OnDiskTable *>();
84 typedef llvm::mapped_iterator<TableVector::iterator, AsOnDiskTable>
86 typedef llvm::iterator_range<table_iterator> table_range;
89 table_range tables() {
90 auto Begin = Tables.begin(),
End = Tables.end();
93 return llvm::make_range(llvm::map_iterator(Begin, AsOnDiskTable()),
94 llvm::map_iterator(
End, AsOnDiskTable()));
97 MergedTable *getMergedTable()
const {
99 return Tables.empty() ?
nullptr : Table::getFromOpaqueValue(*Tables.begin())
100 .
template dyn_cast<MergedTable*>();
105 for (
auto *T : tables())
107 if (
auto *M = getMergedTable())
112 void removeOverriddenTables() {
114 Files.insert(PendingOverrides.begin(), PendingOverrides.end());
116 auto ShouldRemove = [&Files](
void *T) ->
bool {
117 auto *ODT = Table::getFromOpaqueValue(T).template get<OnDiskTable *>();
118 bool Remove = Files.count(ODT->File);
123 Tables.erase(std::remove_if(tables().
begin().getCurrent(), Tables.end(),
126 PendingOverrides.clear();
130 MergedTable *Merged = getMergedTable();
132 Merged =
new MergedTable;
136 for (
auto *ODT : tables()) {
137 auto &HT = ODT->Table;
138 Info &InfoObj = HT.getInfoObj();
140 for (
auto I = HT.data_begin(),
E = HT.data_end();
I !=
E; ++
I) {
141 auto *LocalPtr =
I.getItem();
144 auto L = InfoObj.ReadKeyDataLength(LocalPtr);
147 InfoObj.ReadDataInto(Key, LocalPtr + L.first, L.second,
151 Merged->Files.push_back(ODT->File);
156 Tables.push_back(Table(Merged).getOpaqueValue());
160 template<
typename ReaderInfo,
typename WriterInfo>
166 : Tables(std::move(O.Tables)),
167 PendingOverrides(std::move(O.PendingOverrides)) {
174 Tables = std::move(O.Tables);
176 PendingOverrides = std::move(O.PendingOverrides);
183 using namespace llvm::support;
186 uint32_t BucketOffset = endian::readNext<uint32_t, little, unaligned>(Ptr);
189 uint32_t NumFiles = endian::readNext<uint32_t, little, unaligned>(Ptr);
193 OverriddenFiles.reserve(NumFiles);
194 for (; NumFiles != 0; --NumFiles)
195 OverriddenFiles.push_back(InfoObj.ReadFileRef(Ptr));
196 PendingOverrides.insert(PendingOverrides.end(), OverriddenFiles.begin(),
197 OverriddenFiles.end());
201 auto NumBucketsAndEntries =
202 OnDiskTable::HashTable::readNumBucketsAndEntries(Buckets);
205 Table NewTable =
new OnDiskTable(File, NumBucketsAndEntries.first,
206 NumBucketsAndEntries.second,
207 Buckets, Ptr, Data, std::move(InfoObj));
208 Tables.push_back(NewTable.getOpaqueValue());
215 if (!PendingOverrides.empty())
216 removeOverriddenTables();
218 if (Tables.size() >
static_cast<unsigned>(Info::MaxTables))
224 if (MergedTable *M = getMergedTable()) {
225 auto It = M->Data.find(Key);
226 if (It != M->Data.end())
232 for (
auto *ODT : tables()) {
233 auto &HT = ODT->Table;
234 auto It = HT.find_hashed(Key, KeyHash);
236 HT.getInfoObj().ReadDataInto(Key, It.getDataPtr(), It.getDataLen(),
249 if (!PendingOverrides.empty())
250 removeOverriddenTables();
252 if (MergedTable *M = getMergedTable()) {
253 for (
auto &KV : M->Data)
254 Info::MergeDataInto(KV.second, ResultBuilder);
257 for (
auto *ODT : tables()) {
258 auto &HT = ODT->Table;
259 Info &InfoObj = HT.getInfoObj();
260 for (
auto I = HT.data_begin(),
E = HT.data_end();
I !=
E; ++
I) {
261 auto *LocalPtr =
I.getItem();
264 auto L = InfoObj.ReadKeyDataLength(LocalPtr);
266 InfoObj.ReadDataInto(Key, LocalPtr + L.first, L.second, ResultBuilder);
275 template<
typename ReaderInfo,
typename WriterInfo>
278 typedef llvm::OnDiskChainedHashTableGenerator<WriterInfo> Generator;
285 void insert(
typename WriterInfo::key_type_ref Key,
286 typename WriterInfo::data_type_ref Data, WriterInfo &Info) {
287 Gen.insert(Key, Data, Info);
292 using namespace llvm::support;
293 llvm::raw_svector_ostream OutStream(Out);
297 endian::Writer<little> Writer(OutStream);
300 Writer.write<uint32_t>(0);
302 if (
auto *Merged = Base ? Base->getMergedTable() :
nullptr) {
304 Writer.write<uint32_t>(Merged->Files.size());
305 for (
const auto &F : Merged->Files)
306 Info.EmitFileRef(OutStream, F);
309 for (
auto &KV : Merged->Data) {
310 if (!Gen.contains(KV.first, Info))
311 Gen.insert(KV.first, Info.ImportData(KV.second), Info);
314 Writer.write<uint32_t>(0);
319 uint32_t BucketOffset = Gen.Emit(OutStream, Info);
322 endian::write32le(Out.data(), BucketOffset);
Info::data_type_builder data_type_builder
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.
detail::InMemoryDirectory::const_iterator I
Info::internal_key_type internal_key_type
Information about a module that has been loaded by the ASTReader.
The result type of a method or function.
const unsigned char * storage_type
A pointer to an on-disk representation of the hash table.
unsigned ComputeHash(Selector Sel)
Info::external_key_type external_key_type
MultiOnDiskHashTable(MultiOnDiskHashTable &&O)
Info::data_type data_type
void emit(llvm::SmallVectorImpl< char > &Out, WriterInfo &Info, const BaseTable *Base)
MultiOnDiskHashTable & operator=(MultiOnDiskHashTable &&O)
DeclarationName - The name of a declaration.
detail::InMemoryDirectory::const_iterator E
A key used when looking up entities by DeclarationName.
data_type findAll()
Read all the lookup results into a single value.
void add(file_type File, storage_type Data, Info InfoObj=Info())
Add the table Data loaded from file File.
Info::file_type file_type
A handle to a file, used when overriding tables.
MultiOnDiskHashTableGenerator()