LLVM: lib/ProfileData/InstrProfReader.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
21
31#include
32#include
33#include
34#include
35#include
36#include
37#include <system_error>
38#include
39#include
40
41using namespace llvm;
42
43
44
49 }
52 }
55 }
58 }
61 }
64 }
67 }
70 }
71 return ProfileKind;
72}
73
77 : FS.getBufferForFile(Filename);
78 if (std::error_code EC = BufferOrErr.getError())
80 return std::move(BufferOrErr.get());
81}
82
86
87
88
89
90
91
92
93
94
98 std::vectorllvm::object::BuildID &BinaryIds,
101
102 const uint64_t BinaryIdsSize = BinaryIdsBuffer.size();
103 const uint8_t *BinaryIdsStart = BinaryIdsBuffer.data();
104
105 if (BinaryIdsSize == 0)
107
108 const uint8_t *BI = BinaryIdsStart;
109 const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize;
112
113 while (BI < BIEnd) {
114 size_t Remaining = BIEnd - BI;
115
116 if (Remaining < sizeof(uint64_t))
119 "not enough data to read binary id length");
120
122 if (BILen == 0)
124 "binary id length is 0");
125
126 Remaining = BIEnd - BI;
127
131
132
134
135
137 if (BI > End)
140 "binary id section is greater than buffer size");
141 }
142
144}
145
148 OS << "Binary IDs: \n";
149 for (const auto &BI : BinaryIds) {
150 for (auto I : BI)
152 OS << "\n";
153 }
154}
155
161 std::function<void(Error)> Warn) {
162
164 if (Error E = BufferOrError.takeError())
165 return std::move(E);
167 BIDFetcher, BIDFetcherCorrelatorKind, Warn);
168}
169
171 std::unique_ptr Buffer, const InstrProfCorrelator *Correlator,
174 std::function<void(Error)> Warn) {
175 if (Buffer->getBufferSize() == 0)
177
178 std::unique_ptr Result;
179
184 BIDFetcher, BIDFetcherCorrelatorKind,
185 Warn));
188 BIDFetcher, BIDFetcherCorrelatorKind,
189 Warn));
192 else
194
195
197 return std::move(E);
198
199 return std::move(Result);
200}
201
204 const Twine &RemappingPath) {
205
207 if (Error E = BufferOrError.takeError())
208 return std::move(E);
209
210
211 std::unique_ptr RemappingBuffer;
212 std::string RemappingPathStr = RemappingPath.str();
213 if (!RemappingPathStr.empty()) {
214 auto RemappingBufferOrError = setupMemoryBuffer(RemappingPathStr, FS);
215 if (Error E = RemappingBufferOrError.takeError())
216 return std::move(E);
217 RemappingBuffer = std::move(RemappingBufferOrError.get());
218 }
219
221 std::move(RemappingBuffer));
222}
223
226 std::unique_ptr RemappingBuffer) {
227
230 auto Result = std::make_unique(
231 std::move(Buffer), std::move(RemappingBuffer));
232
233
235 return std::move(E);
236
237 return std::move(Result);
238}
239
241
242
245 return count == 0 ||
247 [](char c) { return isPrint(c) || isSpace(c); });
248}
249
250
251
252
255
256 while (Line->starts_with(":")) {
258 if (Str.equals_insensitive("ir"))
260 else if (Str.equals_insensitive("fe"))
262 else if (Str.equals_insensitive("csir")) {
265 } else if (Str.equals_insensitive("entry_first"))
267 else if (Str.equals_insensitive("not_entry_first"))
269 else if (Str.equals_insensitive("instrument_loop_entries"))
271 else if (Str.equals_insensitive("single_byte_coverage"))
273 else if (Str.equals_insensitive("temporal_prof_traces")) {
275 if (auto Err = readTemporalProfTraceData())
276 return error(std::move(Err));
277 } else
279 ++Line;
280 }
282}
283
284
285
286
287
288
289Error TextInstrProfReader::readTemporalProfTraceData() {
290 if ((++Line).is_at_end())
292
294 if (Line->getAsInteger(0, NumTraces))
296
297 if ((++Line).is_at_end())
299
302
303 for (uint32_t i = 0; i < NumTraces; i++) {
304 if ((++Line).is_at_end())
306
308 if (Line->getAsInteger(0, Trace.Weight))
310
311 if ((++Line).is_at_end())
313
315 Line->split(FuncNames, ",", -1, false);
316 for (auto &FuncName : FuncNames)
317 Trace.FunctionNameRefs.push_back(
320 }
322}
323
326
327#define CHECK_LINE_END(Line) \
328 if (Line.is_at_end()) \
329 return error(instrprof_error::truncated);
330#define READ_NUM(Str, Dst) \
331 if ((Str).getAsInteger(10, (Dst))) \
332 return error(instrprof_error::malformed);
333#define VP_READ_ADVANCE(Val) \
334 CHECK_LINE_END(Line); \
335 uint32_t Val; \
336 READ_NUM((*Line), (Val)); \
337 Line++;
338
339 if (Line.is_at_end())
341
342 uint32_t NumValueKinds;
343 if (Line->getAsInteger(10, NumValueKinds)) {
344
346 }
347 if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
349 "number of value kinds is invalid");
350 Line++;
351
352 for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
354 if (ValueKind > IPVK_Last)
356 ;
359 continue;
360
364
365 std::vector CurrentValues;
366 for (uint32_t V = 0; V < NumValueData; V++) {
368 std::pair<StringRef, StringRef> VD = Line->rsplit(':');
369 uint64_t TakenCount, Value;
370 if (ValueKind == IPVK_IndirectCallTarget) {
373 } else {
375 return E;
377 }
378 } else if (ValueKind == IPVK_VTableTarget) {
381 else {
382 if (Error E = Symtab->addVTableName(VD.first))
383 return E;
385 }
386 } else {
388 }
389 READ_NUM(VD.second, TakenCount);
390 CurrentValues.push_back({Value, TakenCount});
391 Line++;
392 }
393 assert(CurrentValues.size() == NumValueData);
394 Record.addValueData(ValueKind, S, CurrentValues, nullptr);
395 }
396 }
398
399#undef CHECK_LINE_END
400#undef READ_NUM
401#undef VP_READ_ADVANCE
402}
403
405
406 while (!Line.is_at_end() && (Line->empty() || Line->starts_with("#")))
407 ++Line;
408
409 if (Line.is_at_end()) {
411 }
412
413
414 Record.Name = *Line++;
416 return error(std::move(E));
417
418
419 if (Line.is_at_end())
421 if ((Line++)->getAsInteger(0, Record.Hash))
423 "function hash is not a valid integer");
424
425
427 if (Line.is_at_end())
429 if ((Line++)->getAsInteger(10, NumCounters))
431 "number of counters is not a valid integer");
434
435
439 if (Line.is_at_end())
442 if ((Line++)->getAsInteger(10, Count))
445 }
446
447
448 if (Line->starts_with("$")) {
449 Record.BitmapBytes.clear();
450
452 if ((Line++)->drop_front(1).trim().getAsInteger(0, NumBitmapBytes))
454 "number of bitmap bytes is not a valid integer");
456
459 if (Line.is_at_end())
462 if ((Line++)->getAsInteger(0, BitmapByte))
464 "bitmap byte is not a valid integer");
465 Record.BitmapBytes.push_back(BitmapByte);
466 }
467 }
468 }
469
470
471 if (Error E = readValueProfileData(Record))
472 return error(std::move(E));
473
475}
476
477template
481
482template
485 std::optional<uint64_t> Weight) {
486 if (TemporalProfTimestamps.empty()) {
489 }
490
491 std::sort(TemporalProfTimestamps.begin(), TemporalProfTimestamps.end());
493 if (Weight)
494 Trace.Weight = *Weight;
495 for (auto &[TimestampValue, NameRef] : TemporalProfTimestamps)
496 Trace.FunctionNameRefs.push_back(NameRef);
499}
500
501template
503 if (DataBuffer.getBufferSize() < sizeof(uint64_t))
504 return false;
506 *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
509}
510
511template
518 DataBuffer->getBufferStart());
521}
522
523template
524Error RawInstrProfReader::readNextHeader(const char *CurrentPos) {
525 const char *End = DataBuffer->getBufferEnd();
526
527 while (CurrentPos != End && *CurrentPos == 0)
528 ++CurrentPos;
529
530 if (CurrentPos == End)
532
533
536 "not enough space for another header");
537
538 if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t))
540 "insufficient padding");
541
542 uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
545
546
548 return readHeader(*Header);
549}
550
551template
554 StringRef(VNamesStart, VNamesEnd - VNamesStart)))
555 return error(std::move(E));
557 const IntPtrT FPtr = swap(I->FunctionPointer);
558 if (!FPtr)
559 continue;
560 Symtab.mapAddress(FPtr, swap(I->NameRef));
561 }
562
563 if (VTableBegin != nullptr && VTableEnd != nullptr) {
566 const IntPtrT VPtr = swap(I->VTablePointer);
567 if (!VPtr)
568 continue;
569
570
571
572
575 }
576 }
578}
579
580template
586 ("Profile uses raw profile format version = " +
589 "\nPLEASE update this tool to version in the raw profile, or "
590 "regenerate raw profile with expected version.")
591 .str());
592
593 uint64_t BinaryIdSize = swap(Header.BinaryIdsSize);
594
595 const uint8_t *BinaryIdStart =
597 const uint8_t *BinaryIdEnd = BinaryIdStart + BinaryIdSize;
598 const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd();
599 if (BinaryIdSize % sizeof(uint64_t) || BinaryIdEnd > BufferEnd)
602 if (!BinaryIdsBuffer.empty()) {
604 BinaryIds, getDataEndianness()))
605 return Err;
606 }
607
610 NamesDelta = swap(Header.NamesDelta);
611 auto NumData = swap(Header.NumData);
612 auto PaddingBytesBeforeCounters = swap(Header.PaddingBytesBeforeCounters);
613 auto CountersSize = swap(Header.NumCounters) * getCounterTypeSize();
614 auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters);
616 auto PaddingBytesAfterBitmapBytes = swap(Header.PaddingBytesAfterBitmapBytes);
617 auto NamesSize = swap(Header.NamesSize);
618 auto VTableNameSize = swap(Header.VNamesSize);
619 auto NumVTables = swap(Header.NumVTables);
620 ValueKindLast = swap(Header.ValueKindLast);
621
623 auto PaddingBytesAfterNames = getNumPaddingBytes(NamesSize);
624 auto PaddingBytesAfterVTableNames = getNumPaddingBytes(VTableNameSize);
625
626 auto VTableSectionSize =
628 auto PaddingBytesAfterVTableProfData = getNumPaddingBytes(VTableSectionSize);
629
630
632 ptrdiff_t CountersOffset = DataOffset + DataSize + PaddingBytesBeforeCounters;
633 ptrdiff_t BitmapOffset =
634 CountersOffset + CountersSize + PaddingBytesAfterCounters;
635 ptrdiff_t NamesOffset =
636 BitmapOffset + NumBitmapBytes + PaddingBytesAfterBitmapBytes;
637 ptrdiff_t VTableProfDataOffset =
638 NamesOffset + NamesSize + PaddingBytesAfterNames;
639 ptrdiff_t VTableNameOffset = VTableProfDataOffset + VTableSectionSize +
640 PaddingBytesAfterVTableProfData;
641 ptrdiff_t ValueDataOffset =
642 VTableNameOffset + VTableNameSize + PaddingBytesAfterVTableNames;
643
644 auto *Start = reinterpret_cast<const char *>(&Header);
645 if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
647
648 if (BIDFetcher) {
649 std::vectorobject::BuildID BinaryIDs;
650 if (Error E = readBinaryIds(BinaryIDs))
651 return E;
653 BIDFetcher, BinaryIDs)
654 .moveInto(BIDFetcherCorrelator)) {
655 return E;
656 }
657 if (auto Err = BIDFetcherCorrelator->correlateProfileData(0))
658 return Err;
659 }
660
661 if (Correlator) {
662
663
665 NamesDelta == 0))
667 Data = Correlator->getDataPointer();
670 NamesEnd = NamesStart + Correlator->getNamesSize();
671 } else if (BIDFetcherCorrelator) {
674 BIDFetcherCorrelator.get());
676 DataEnd = Data + BIDFetcherCorrelatorImpl->getDataSize();
677 NamesStart = BIDFetcherCorrelatorImpl->getNamesPointer();
678 NamesEnd = NamesStart + BIDFetcherCorrelatorImpl->getNamesSize();
679 } else {
681 Start + DataOffset);
682 DataEnd = Data + NumData;
683 VTableBegin =
685 Start + VTableProfDataOffset);
686 VTableEnd = VTableBegin + NumVTables;
687 NamesStart = Start + NamesOffset;
688 NamesEnd = NamesStart + NamesSize;
689 VNamesStart = Start + VTableNameOffset;
690 VNamesEnd = VNamesStart + VTableNameSize;
691 }
692
693 CountersStart = Start + CountersOffset;
694 CountersEnd = CountersStart + CountersSize;
695 BitmapStart = Start + BitmapOffset;
697 ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
698
699 std::unique_ptr NewSymtab = std::make_unique();
700 if (Error E = createSymtab(*NewSymtab))
701 return E;
702
703 Symtab = std::move(NewSymtab);
705}
706
707template
711}
712
713template
717}
718
719template
720Error RawInstrProfReader::readRawCounts(
725
727 if (CounterBaseOffset < 0)
730 ("counter offset " + Twine(CounterBaseOffset) + " is negative").str());
731
732 if (CounterBaseOffset >= CountersEnd - CountersStart)
734 ("counter offset " + Twine(CounterBaseOffset) +
735 " is greater than the maximum counter offset " +
736 Twine(CountersEnd - CountersStart - 1))
737 .str());
738
739 uint64_t MaxNumCounters =
740 (CountersEnd - (CountersStart + CounterBaseOffset)) /
741 getCounterTypeSize();
745 " is greater than the maximum number of counters " +
746 Twine(MaxNumCounters))
747 .str());
748
749 Record.Counts.clear();
752 const char *Ptr =
753 CountersStart + CounterBaseOffset + I * getCounterTypeSize();
754 if (I == 0 && hasTemporalProfile()) {
755 uint64_t TimestampValue = swap(*reinterpret_cast<const uint64_t *>(Ptr));
756 if (TimestampValue != 0 &&
757 TimestampValue != std::numeric_limits<uint64_t>::max()) {
758 TemporalProfTimestamps.emplace_back(TimestampValue,
760 TemporalProfTraceStreamSize = 1;
761 }
762 if (hasSingleByteCoverage()) {
763
764
765
766
767 I += 7;
768 }
769 continue;
770 }
771 if (hasSingleByteCoverage()) {
772
773 Record.Counts.push_back(*Ptr == 0 ? 1 : 0);
774 } else {
775 uint64_t CounterValue = swap(*reinterpret_cast<const uint64_t *>(Ptr));
776 if (CounterValue > MaxCounterValue && Warn)
779
780 Record.Counts.push_back(CounterValue);
781 }
782 }
783
785}
786
787template
790
791 Record.BitmapBytes.clear();
793
794
795
798
799
801 if (BitmapOffset < 0)
804 ("bitmap offset " + Twine(BitmapOffset) + " is negative").str());
805
806 if (BitmapOffset >= BitmapEnd - BitmapStart)
808 ("bitmap offset " + Twine(BitmapOffset) +
809 " is greater than the maximum bitmap offset " +
810 Twine(BitmapEnd - BitmapStart - 1))
811 .str());
812
813 uint64_t MaxNumBitmapBytes =
814 (BitmapEnd - (BitmapStart + BitmapOffset)) / sizeof(uint8_t);
818 " is greater than the maximum number of bitmap bytes " +
819 Twine(MaxNumBitmapBytes))
820 .str());
821
823 const char *Ptr = BitmapStart + BitmapOffset + I;
824 Record.BitmapBytes.push_back(swap(*Ptr));
825 }
826
828}
829
830template
831Error RawInstrProfReader::readValueProfilingData(
833 Record.clearValueData();
834 CurValueDataSize = 0;
835
836 uint32_t NumValueKinds = 0;
837 for (uint32_t I = 0; I < IPVK_Last + 1; I++)
838 NumValueKinds += (Data->NumValueSites[I] != 0);
839
840 if (!NumValueKinds)
842
844 ValueProfData::getValueProfData(
845 ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(),
846 getDataEndianness());
847
849 return E;
850
851
852
853
854 VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get());
855 CurValueDataSize = VDataPtrOrErr.get()->getSize();
857}
858
859template
861
862
863 while (atEnd())
864
865 if (Error E = readNextHeader(getNextHeaderPos()))
866 return error(std::move(E));
867
868
870 return error(std::move(E));
871
872
874 return error(std::move(E));
875
876
878 return error(std::move(E));
879
880
881 if (Error E = readRawBitmapBytes(Record))
882 return error(std::move(E));
883
884
885 if (Error E = readValueProfilingData(Record))
886 return error(std::move(E));
887
888
889 advanceData();
891}
892
893template
895 std::vectorllvm::object::BuildID &BinaryIds) {
896 BinaryIds.insert(BinaryIds.begin(), this->BinaryIds.begin(),
897 this->BinaryIds.end());
899}
900
901template
903 if (!BinaryIds.empty())
906}
907
908namespace llvm {
909
912
913}
914
919
922
924 const unsigned char *&D, const unsigned char *const End) {
926 ValueProfData::getValueProfData(D, End, ValueProfDataEndianness);
927
929 return false;
930
931 VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr);
932 D += VDataPtrOrErr.get()->TotalSize;
933
934 return true;
935}
936
940
941
944
945 DataBuffer.clear();
946 std::vector<uint64_t> CounterBuffer;
947 std::vector<uint8_t> BitmapByteBuffer;
948
949 const unsigned char *End = D + N;
950 while (D < End) {
951
955
956
958
963 }
964
965 if (D + CountsSize * sizeof(uint64_t) > End)
967
968 CounterBuffer.clear();
969 CounterBuffer.reserve(CountsSize);
970 for (uint64_t J = 0; J < CountsSize; ++J)
971 CounterBuffer.push_back(
973
974
980
981 if (D + BitmapBytes * sizeof(uint8_t) > End)
983 BitmapByteBuffer.clear();
984 BitmapByteBuffer.reserve(BitmapBytes);
985 for (uint64_t J = 0; J < BitmapBytes; ++J)
986 BitmapByteBuffer.push_back(static_cast<uint8_t>(
988 }
989
990 DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer),
991 std::move(BitmapByteBuffer));
992
993
996 DataBuffer.clear();
998 }
999 }
1000 return DataBuffer;
1001}
1002
1003template
1006 auto Iter = HashTable->find(FuncName);
1007 if (Iter == HashTable->end())
1009
1010 Data = (*Iter);
1011 if (Data.empty())
1013 "profile data is empty");
1014
1016}
1017
1018template
1023
1024 Data = *RecordIterator;
1025
1026 if (Data.empty())
1028 "profile data is empty");
1029
1031}
1032
1033template
1035 const unsigned char *Buckets, const unsigned char *const Payload,
1038 FormatVersion = Version;
1039 HashTable.reset(HashTableImpl::Create(
1040 Buckets, Payload, Base,
1041 typename HashTableImpl::InfoType(HashType, Version)));
1042 RecordIterator = HashTable->data_begin();
1043}
1044
1045template
1049
1050namespace {
1051
1054
1055public:
1057 : Underlying(Underlying) {}
1058
1061 return Underlying.getRecords(FuncName, Data);
1062 }
1063};
1064}
1065
1066
1067template
1070public:
1072 std::unique_ptr RemapBuffer,
1074 : RemapBuffer(std::move(RemapBuffer)), Underlying(Underlying) {
1075 }
1076
1077
1079
1080
1081
1082
1083 std::pair<StringRef, StringRef> Parts = {StringRef(), Name};
1084 while (true) {
1086 if (Parts.first.starts_with("_Z"))
1087 return Parts.first;
1088 if (Parts.second.empty())
1089 return Name;
1090 }
1091 }
1092
1093
1094
1103
1105 if (Error E = Remappings.read(*RemapBuffer))
1106 return E;
1107 for (StringRef Name : Underlying.HashTable->keys()) {
1109 if (auto Key = Remappings.insert(RealName)) {
1110
1111
1112
1113 MappedNames.insert({Key, RealName});
1114 }
1115 }
1117 }
1118
1122 if (auto Key = Remappings.lookup(RealName)) {
1123 StringRef Remapped = MappedNames.lookup(Key);
1124 if (!Remapped.empty()) {
1125 if (RealName.begin() == FuncName.begin() &&
1126 RealName.end() == FuncName.end())
1127 FuncName = Remapped;
1128 else {
1129
1131 reconstituteName(FuncName, RealName, Remapped, Reconstituted);
1132 Error E = Underlying.getRecords(Reconstituted, Data);
1133 if (!E)
1134 return E;
1135
1136
1137
1139 std::move(E), [](std::unique_ptr Err) {
1142 : Error(std::move(Err));
1143 }))
1144 return Unhandled;
1145 }
1146 }
1147 }
1148 return Underlying.getRecords(FuncName, Data);
1149 }
1150
1151private:
1152
1153
1154 std::unique_ptr RemapBuffer;
1155
1156
1158
1159
1160
1161
1162
1164
1165
1167};
1168
1170 using namespace support;
1171
1172 if (DataBuffer.getBufferSize() < 8)
1173 return false;
1176
1178}
1179
1180const unsigned char *
1182 const unsigned char *Cur, bool UseCS) {
1184 using namespace support;
1185
1195 std::unique_ptrIndexedInstrProf::Summary SummaryData =
1197
1198 const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
1199 uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
1200 for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
1202
1204 for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) {
1208 }
1209 std::unique_ptrllvm::ProfileSummary &Summary =
1210 UseCS ? this->CS_Summary : this->Summary;
1211
1212
1213 Summary = std::make_unique(
1215 DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
1216 SummaryData->get(Summary::MaxBlockCount),
1217 SummaryData->get(Summary::MaxInternalBlockCount),
1218 SummaryData->get(Summary::MaxFunctionCount),
1219 SummaryData->get(Summary::TotalNumBlocks),
1220 SummaryData->get(Summary::TotalNumFunctions));
1221 return Cur + SummarySize;
1222 } else {
1223
1224
1225
1226
1227
1229 Summary = Builder.getSummary();
1230 return Cur;
1231 }
1232}
1233
1235 using namespace support;
1236
1237 const unsigned char *Start =
1238 (const unsigned char *)DataBuffer->getBufferStart();
1239 const unsigned char *Cur = Start;
1240 if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
1242
1244 if (!HeaderOr)
1245 return HeaderOr.takeError();
1246
1248 Cur += Header->size();
1249
1251 false);
1254 true);
1255
1260
1261
1262 auto IndexPtr = std::make_unique<InstrProfReaderIndex>(
1263 Start + Header->HashOffset, Cur, Start, HashType, Header->Version);
1264
1265
1266
1267 if (Header->getIndexedProfileVersion() >= 8 &&
1269 if (Error E = MemProfReader.deserialize(Start, Header->MemProfOffset))
1270 return E;
1271 }
1272
1273
1274
1275 if (Header->getIndexedProfileVersion() >= 9) {
1276 const unsigned char *Ptr = Start + Header->BinaryIdOffset;
1277
1280 if (BinaryIdsSize % sizeof(uint64_t))
1282
1284 if (Ptr > (const unsigned char *)DataBuffer->getBufferEnd())
1286 "corrupted binary ids");
1287 }
1288
1289 if (Header->getIndexedProfileVersion() >= 12) {
1290 const unsigned char *Ptr = Start + Header->VTableNamesOffset;
1291
1292 uint64_t CompressedVTableNamesLen =
1294
1295
1296
1297 const char *VTableNamePtr = (const char *)Ptr;
1298 if (VTableNamePtr > DataBuffer->getBufferEnd())
1300
1301 VTableName = StringRef(VTableNamePtr, CompressedVTableNamesLen);
1302 }
1303
1304 if (Header->getIndexedProfileVersion() >= 10 &&
1306 const unsigned char *Ptr = Start + Header->TemporalProfTracesOffset;
1307 const auto *PtrEnd = (const unsigned char *)DataBuffer->getBufferEnd();
1308
1309 if (Ptr + 2 * sizeof(uint64_t) > PtrEnd)
1315 for (unsigned i = 0; i < NumTraces; i++) {
1316
1317 if (Ptr + 2 * sizeof(uint64_t) > PtrEnd)
1322 const uint64_t NumFunctions =
1324
1325 if (Ptr + NumFunctions * sizeof(uint64_t) > PtrEnd)
1327 for (unsigned j = 0; j < NumFunctions; j++) {
1330 Trace.FunctionNameRefs.push_back(NameRef);
1331 }
1333 }
1334 }
1335
1336
1337 if (RemappingBuffer) {
1338 Remapper =
1339 std::make_unique<InstrProfReaderItaniumRemapper>(
1340 std::move(RemappingBuffer), *IndexPtr);
1341 if (Error E = Remapper->populateRemappings())
1342 return E;
1343 } else {
1344 Remapper = std::make_unique(*IndexPtr);
1345 }
1346 Index = std::move(IndexPtr);
1347
1349}
1350
1354
1355 auto NewSymtab = std::make_unique();
1356
1357 if (Error E = NewSymtab->initVTableNamesFromCompressedStrings(VTableName)) {
1360 }
1361
1362
1363 if (Error E = Index->populateSymtab(*NewSymtab)) {
1366 }
1367
1368 Symtab = std::move(NewSymtab);
1370}
1371
1374 uint64_t *MismatchedFuncSum) {
1377 auto Err = Remapper->getRecords(FuncName, Data);
1378 if (Err) {
1379
1380
1381 auto Err2 =
1385 if (auto Err = Remapper->getRecords(DeprecatedFuncName, Data))
1386 return Err;
1388 });
1389 if (Err2)
1390 return std::move(Err2);
1391 }
1392
1393
1394
1395
1396 bool CSBitMatch = false;
1399 for (uint64_t CountValue : Counts) {
1400 if (CountValue == (uint64_t)-1)
1401 continue;
1402
1403 if (std::numeric_limits<uint64_t>::max() - CountValue <= ValueSum)
1404 return std::numeric_limits<uint64_t>::max();
1405 ValueSum += CountValue;
1406 }
1407 return ValueSum;
1408 };
1409
1411
1413 return std::move(I);
1416 CSBitMatch = true;
1417 if (MismatchedFuncSum == nullptr)
1418 continue;
1419 FuncSum = std::max(FuncSum, getFuncSum(I.Counts));
1420 }
1421 }
1422 if (CSBitMatch) {
1423 if (MismatchedFuncSum != nullptr)
1424 *MismatchedFuncSum = FuncSum;
1426 }
1428}
1429
1435 MemProfFrameTable);
1436
1438 MemProfCallStackTable, FrameIdConv);
1439
1441
1442
1446 "memprof call stack not found for call stack id " +
1448 }
1449
1450
1453 "memprof frame not found for frame id " +
1455 }
1456
1458}
1459
1462
1463 if (MemProfRecordTable == nullptr)
1465 "no memprof data available in profile");
1466 auto Iter = MemProfRecordTable->find(FuncNameHash);
1467 if (Iter == MemProfRecordTable->end())
1470 "memprof record not found for function hash " + Twine(FuncNameHash));
1471
1473 switch (Version) {
1475 assert(MemProfFrameTable && "MemProfFrameTable must be available");
1476 assert(MemProfCallStackTable && "MemProfCallStackTable must be available");
1478 *MemProfCallStackTable);
1479
1482 assert(!MemProfFrameTable && "MemProfFrameTable must not be available");
1483 assert(!MemProfCallStackTable &&
1484 "MemProfCallStackTable must not be available");
1485 assert(FrameBase && "FrameBase must be available");
1486 assert(CallStackBase && "CallStackBase must be available");
1487 {
1492 }
1493 }
1494
1497 formatv("MemProf version {} not supported; "
1498 "requires version between {} and {}, inclusive",
1501}
1502
1505 assert(MemProfRecordTable);
1507
1510 RadixTreeSize);
1511
1512
1513
1514 BitVector Worklist(RadixTreeSize);
1515
1516
1517
1518
1520 MemProfRecordTable->data()) {
1522 IndexedRecord.AllocSites)
1523 Worklist.set(IndexedAI.CSId);
1524 }
1525
1526
1527 for (unsigned CS : Worklist.set_bits())
1528 Extractor(CS);
1529
1531 std::move(Extractor.CallerCalleePairs);
1532
1533
1534 for (auto &[CallerGUID, CallList] : Pairs) {
1536 CallList.erase(llvm::unique(CallList), CallList.end());
1537 }
1538
1539 return Pairs;
1540}
1541
1545 MemProfRecordTable->getNumEntries());
1546 for (uint64_t Key : MemProfRecordTable->keys()) {
1548 if (Record.takeError())
1549 continue;
1554 }
1555
1556 if (DataAccessProfileData != nullptr) {
1557 for (const auto &[SymHandleRef, RecordRef] :
1558 DataAccessProfileData->getRecords())
1561 RecordRef.Locations));
1562 for (StringRef ColdSymbol : DataAccessProfileData->getKnownColdSymbols())
1564 ColdSymbol.str());
1565 for (uint64_t Hash : DataAccessProfileData->getKnownColdHashes())
1567 Hash);
1568 }
1569 return AllMemProfData;
1570}
1571
1574 std::vector<uint64_t> &Counts) {
1577 return error(std::move(E));
1578
1579 Counts = Record.get().Counts;
1581}
1582
1588 return error(std::move(E));
1589
1590 const auto &BitmapBytes = Record.get().BitmapBytes;
1591 size_t I = 0, E = BitmapBytes.size();
1592 Bitmap.resize(E * CHAR_BIT);
1594 [&](auto X) {
1595 using XTy = decltype(X);
1596 alignas(XTy) uint8_t W[sizeof(X)];
1597 size_t N = std::min(E - I, sizeof(W));
1598 std::memset(W, 0, sizeof(W));
1599 std::memcpy(W, &BitmapBytes[I], N);
1603 },
1604 Bitmap, Bitmap);
1606
1608}
1609
1612
1613 Error E = Index->getRecords(Data);
1614 if (E)
1615 return error(std::move(E));
1616
1618 if (RecordIndex >= Data.size()) {
1619 Index->advanceToNextKey();
1620 RecordIndex = 0;
1621 }
1623}
1624
1626 std::vectorllvm::object::BuildID &BinaryIds) {
1629}
1630
1632 std::vectorllvm::object::BuildID BinaryIds;
1634 return E;
1637}
1638
1641 for (const auto &Func : *this) {
1644 if (FuncIsCS != IsCS)
1645 continue;
1646 }
1647 Func.accumulateCounts(Sum);
1648 ++NumFuncs;
1649 }
1651}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
Provides ErrorOr smart pointer.
InstrProfLookupTrait::offset_type offset_type
Definition InstrProfReader.cpp:921
static Error initializeReader(InstrProfReader &Reader)
Definition InstrProfReader.cpp:83
#define READ_NUM(Str, Dst)
#define CHECK_LINE_END(Line)
static Error readBinaryIdsInternal(const MemoryBuffer &DataBuffer, ArrayRef< uint8_t > BinaryIdsBuffer, std::vector< llvm::object::BuildID > &BinaryIds, const llvm::endianness Endian)
Read a list of binary ids from a profile that consist of a.
Definition InstrProfReader.cpp:96
#define VP_READ_ADVANCE(Val)
InstrProfLookupTrait::data_type data_type
Definition InstrProfReader.cpp:920
static InstrProfKind getProfileKindFromVersion(uint64_t Version)
Definition InstrProfReader.cpp:45
static Expected< memprof::MemProfRecord > getMemProfRecordV2(const memprof::IndexedMemProfRecord &IndexedRecord, MemProfFrameHashTable &MemProfFrameTable, MemProfCallStackHashTable &MemProfCallStackTable)
Definition InstrProfReader.cpp:1431
static void printBinaryIdsInternal(raw_ostream &OS, ArrayRef< llvm::object::BuildID > BinaryIds)
Definition InstrProfReader.cpp:146
#define VARIANT_MASK_CSIR_PROF
#define VARIANT_MASK_MEMPROF
#define VARIANT_MASK_TEMPORAL_PROF
#define VARIANT_MASK_IR_PROF
#define VARIANT_MASK_BYTE_COVERAGE
#define VARIANT_MASK_INSTR_ENTRY
#define VARIANT_MASK_FUNCTION_ENTRY_ONLY
#define VARIANT_MASK_INSTR_LOOP_ENTRIES
static StringRef getName(Value *V)
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
Defines the virtual file system interface vfs::FileSystem.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
iterator_range< const_set_bits_iterator > set_bits() const
static BitVector & apply(F &&f, BitVector &Out, BitVector const &Arg, ArgTys const &...Args)
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
Reader for the indexed binary instrprof format.
Error readNextRecord(NamedInstrProfRecord &Record) override
Read a single record.
Definition InstrProfReader.cpp:1610
static Expected< std::unique_ptr< IndexedInstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const Twine &RemappingPath="")
Factory method to create an indexed reader.
Definition InstrProfReader.cpp:203
Error readHeader() override
Read the file header.
Definition InstrProfReader.cpp:1234
Error printBinaryIds(raw_ostream &OS) override
Print binary ids.
Definition InstrProfReader.cpp:1631
Error getFunctionBitmap(StringRef FuncName, uint64_t FuncHash, BitVector &Bitmap)
Fill Bitmap with the profile data for the given function name.
Definition InstrProfReader.cpp:1583
InstrProfSymtab & getSymtab() override
Return the PGO symtab.
Definition InstrProfReader.cpp:1351
static bool hasFormat(const MemoryBuffer &DataBuffer)
Return true if the given buffer is in an indexed instrprof format.
Definition InstrProfReader.cpp:1169
Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector< uint64_t > &Counts)
Fill Counts with the profile data for the given function name.
Definition InstrProfReader.cpp:1572
Expected< NamedInstrProfRecord > getInstrProfRecord(StringRef FuncName, uint64_t FuncHash, StringRef DeprecatedFuncName="", uint64_t *MismatchedFuncSum=nullptr)
Return the NamedInstrProfRecord associated with FuncName and FuncHash.
Definition InstrProfReader.cpp:1372
Error readBinaryIds(std::vector< llvm::object::BuildID > &BinaryIds) override
Read a list of binary ids.
Definition InstrProfReader.cpp:1625
LLVM_ABI memprof::AllMemProfData getAllMemProfData() const
Definition InstrProfReader.cpp:1542
LLVM_ABI Expected< memprof::MemProfRecord > getMemProfRecord(const uint64_t FuncNameHash) const
Definition InstrProfReader.cpp:1461
LLVM_ABI DenseMap< uint64_t, SmallVector< memprof::CallEdgeTy, 0 > > getMemProfCallerCalleePairs() const
Definition InstrProfReader.cpp:1504
InstrProfCorrelatorImpl - A child of InstrProfCorrelator with a template pointer type so that the Pro...
const RawInstrProf::ProfileData< IntPtrT > * getDataPointer() const
Return a pointer to the underlying ProfileData vector that this class constructs.
size_t getDataSize() const
Return the number of ProfileData elements.
InstrProfCorrelator - A base class used to create raw instrumentation data to their functions.
const char * getNamesPointer() const
Return a pointer to the names string that this class constructs.
ProfCorrelatorKind
Indicate if we should use the debug info or profile metadata sections to correlate.
LLVM_ABI std::optional< size_t > getDataSize() const
Return the number of ProfileData elements.
static LLVM_ABI llvm::Expected< std::unique_ptr< InstrProfCorrelator > > get(StringRef Filename, ProfCorrelatorKind FileKind, const object::BuildIDFetcher *BIDFetcher=nullptr, const ArrayRef< llvm::object::BuildID > BIs={})
size_t getNamesSize() const
Return the number of bytes in the names string.
static std::pair< instrprof_error, std::string > take(Error E)
Consume an Error and return the raw enum value contained within it, and the optional error message.
LLVM_ABI data_type ReadData(StringRef K, const unsigned char *D, offset_type N)
Definition InstrProfReader.cpp:937
LLVM_ABI bool readValueProfilingData(const unsigned char *&D, const unsigned char *const End)
Definition InstrProfReader.cpp:923
LLVM_ABI hash_value_type ComputeHash(StringRef K)
Definition InstrProfReader.cpp:916
ArrayRef< NamedInstrProfRecord > data_type
InstrProfKind getProfileKind() const override
Definition InstrProfReader.cpp:1046
Error getRecords(ArrayRef< NamedInstrProfRecord > &Data) override
Definition InstrProfReader.cpp:1019
InstrProfReaderIndex(const unsigned char *Buckets, const unsigned char *const Payload, const unsigned char *const Base, IndexedInstrProf::HashT HashType, uint64_t Version)
Definition InstrProfReader.cpp:1034
bool atEnd() const override
A remapper that applies remappings based on a symbol remapping file.
Definition InstrProfReader.cpp:1069
static StringRef extractName(StringRef Name)
Extract the original function name from a PGO function name.
Definition InstrProfReader.cpp:1078
InstrProfReaderItaniumRemapper(std::unique_ptr< MemoryBuffer > RemapBuffer, InstrProfReaderIndex< HashTableImpl > &Underlying)
Definition InstrProfReader.cpp:1071
Error populateRemappings() override
Definition InstrProfReader.cpp:1104
static void reconstituteName(StringRef OrigName, StringRef ExtractedName, StringRef Replacement, SmallVectorImpl< char > &Out)
Given a mangled name extracted from a PGO function name, and a new form for that mangled name,...
Definition InstrProfReader.cpp:1095
Error getRecords(StringRef FuncName, ArrayRef< NamedInstrProfRecord > &Data) override
Definition InstrProfReader.cpp:1119
Name matcher supporting fuzzy matching of symbol names to names in profiles.
Base class and interface for reading profiling data of any known instrprof format.
std::unique_ptr< InstrProfSymtab > Symtab
Error success()
Clear the current error and return a successful one.
SmallVector< TemporalProfTraceTy > TemporalProfTraces
A list of temporal profile traces.
uint64_t TemporalProfTraceStreamSize
The total number of temporal profile traces seen.
virtual bool isIRLevelProfile() const =0
virtual Error readHeader()=0
Read the header. Required before reading first record.
LLVM_ABI void accumulateCounts(CountSumOrPercent &Sum, bool IsCS)
Compute the sum of counts and return in Sum.
Definition InstrProfReader.cpp:1639
static LLVM_ABI Expected< std::unique_ptr< InstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const InstrProfCorrelator *Correlator=nullptr, const object::BuildIDFetcher *BIDFetcher=nullptr, const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind=InstrProfCorrelator::ProfCorrelatorKind::NONE, std::function< void(Error)> Warn=nullptr)
Factory method to create an appropriately typed reader for the given instrprof file.
Definition InstrProfReader.cpp:156
A symbol table used for function [IR]PGO name look-up with keys (such as pointers,...
static bool isExternalSymbol(const StringRef &Symbol)
True if Symbol is the value used to represent external symbols.
void mapAddress(uint64_t Addr, uint64_t MD5Val)
Map a function address to its name's MD5 hash.
LLVM_ABI Error create(object::SectionRef &Section)
Create InstrProfSymtab from an object file section which contains function PGO names.
void mapVTableAddress(uint64_t StartAddr, uint64_t EndAddr, uint64_t MD5Val)
Map the address range (i.e., [start_address, end_address)) of a variable to its names' MD5 hash.
This interface provides simple read-only access to a block of memory, and provides simple methods for...
size_t getBufferSize() const
const char * getBufferEnd() const
static ErrorOr< std::unique_ptr< MemoryBuffer > > getSTDIN()
Read all of stdin into a file buffer, and return it.
const char * getBufferStart() const
static LLVM_ABI const ArrayRef< uint32_t > DefaultCutoffs
A vector of useful cutoff values for detailed summary.
Reader for the raw instrprof binary format from runtime.
Error readHeader() override
Read the header. Required before reading first record.
Definition InstrProfReader.cpp:512
Error readNextRecord(NamedInstrProfRecord &Record) override
Read a single record.
Definition InstrProfReader.cpp:860
Error printBinaryIds(raw_ostream &OS) override
Print binary ids.
Definition InstrProfReader.cpp:902
static bool hasFormat(const MemoryBuffer &DataBuffer)
InstrProfKind getProfileKind() const override
Returns a BitsetEnum describing the attributes of the raw instr profile.
Definition InstrProfReader.cpp:478
Error readBinaryIds(std::vector< llvm::object::BuildID > &BinaryIds) override
Read a list of binary ids.
Definition InstrProfReader.cpp:894
SmallVector< TemporalProfTraceTy > & getTemporalProfTraces(std::optional< uint64_t > Weight={}) override
Definition InstrProfReader.cpp:484
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
iterator insert(iterator I, T &&Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
Reader for symbol remapping files.
Reader for the simple text based instrprof format.
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if the given buffer is in text instrprof format.
Definition InstrProfReader.cpp:240
Error readNextRecord(NamedInstrProfRecord &Record) override
Read a single record.
Definition InstrProfReader.cpp:404
Error readHeader() override
Read the header.
Definition InstrProfReader.cpp:253
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
BuildIDFetcher searches local cache directories for debug info.
This class implements an extremely fast bulk output stream that can only output to a stream.
The virtual file system interface.
std::unique_ptr< Summary > allocSummary(uint32_t TotalSize)
uint64_t ComputeHash(StringRef K)
constexpr uint64_t MaximumSupportedVersion
constexpr uint64_t MinimumSupportedVersion
SmallVector< uint8_t, 10 > BuildID
A build ID in binary form.
value_type byte_swap(value_type value, endianness endian)
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
value_type readNext(const CharT *&memory, endianness endian)
Read a value of a particular endianness from a buffer, and increment the buffer past that value.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr CountersDelta
FunctionAddr VTableAddr Value
FunctionAddr NumBitmapBytes
RawInstrProfReader< uint64_t > RawInstrProfReader64
static Expected< std::unique_ptr< MemoryBuffer > > setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS)
constexpr T byteswap(T V) noexcept
Reverses the bytes in the given integer value V.
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
FunctionAddr VTableAddr uintptr_t uintptr_t DataSize
auto unique(Range &&R, Predicate P)
auto dyn_cast_or_null(const Y &Val)
FunctionAddr VTableAddr uintptr_t BitmapDelta
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
FunctionAddr VTableAddr uintptr_t uintptr_t Version
void sort(IteratorTy Start, IteratorTy End)
OnDiskIterableChainedHashTable< memprof::CallStackLookupTrait > MemProfCallStackHashTable
constexpr T alignToPowerOf2(U Value, V Align)
Will overflow only if result is not representable in T.
FunctionAddr NumValueSites[IPVK_Last+1]
OnDiskIterableChainedHashTable< memprof::FrameLookupTrait > MemProfFrameHashTable
FunctionAddr VTableAddr Count
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
@ raw_profile_version_mismatch
@ counter_value_too_large
@ unexpected_correlation_info
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
constexpr char GlobalIdentifierDelimiter
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
std::vector< ProfileSummaryEntry > SummaryEntryVector
void consumeError(Error Err)
Consume a Error without doing anything.
InstrProfKind
An enum describing the attributes of an instrumented profile.
@ LoopEntriesInstrumentation
@ FunctionEntryInstrumentation
@ FrontendInstrumentation
RawInstrProfReader< uint32_t > RawInstrProfReader32
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
uint64_t Cutoff
The required percentile of total execution count.
uint64_t NumBlocks
Number of blocks >= the minumum execution count.
uint64_t MinBlockCount
The minimum execution count for this percentile.
static uint32_t getSize(uint32_t NumSumFields, uint32_t NumCutoffEntries)
uint64_t NumSummaryFields
uint64_t NumCutoffEntries
Profiling information for a single function.
LLVM_ABI void addValueData(uint32_t ValueKind, uint32_t Site, ArrayRef< InstrProfValueData > VData, InstrProfSymtab *SymTab)
Add ValueData for ValueKind at value Site.
void reserveSites(uint32_t ValueKind, uint32_t NumValueSites)
Reserve space for NumValueSites sites.
static bool hasCSFlagInHash(uint64_t FuncHash)
An ordered list of functions identified by their NameRef found in INSTR_PROF_DATA.
YamlDataAccessProfData YamlifiedDataAccessProfiles
std::vector< GUIDMemProfRecordPair > HeapProfileRecords
std::optional< CallStackId > LastUnmappedId
The data access profiles for a symbol.
std::optional< FrameId > LastUnmappedId
LLVM_ABI MemProfRecord toMemProfRecord(llvm::function_ref< std::vector< Frame >(const CallStackId)> Callback) const
std::vector< memprof::DataAccessProfRecord > Records
std::vector< uint64_t > KnownColdStrHashes
std::vector< std::string > KnownColdSymbols