|
10 | 10 |
|
11 | 11 | namespace llvm {
|
12 | 12 | namespace memprof {
|
| 13 | +namespace { |
| 14 | +size_t serializedSizeV0(const IndexedAllocationInfo &IAI) { |
| 15 | + size_t Size = 0; |
| 16 | + // The number of frames to serialize. |
| 17 | + Size += sizeof(uint64_t); |
| 18 | + // The callstack frame ids. |
| 19 | + Size += sizeof(FrameId) * IAI.CallStack.size(); |
| 20 | + // The size of the payload. |
| 21 | + Size += PortableMemInfoBlock::serializedSize(); |
| 22 | + return Size; |
| 23 | +} |
13 | 24 |
|
14 |
| -void IndexedMemProfRecord::serialize(const MemProfSchema &Schema, |
15 |
| - raw_ostream &OS) { |
| 25 | +size_t serializedSizeV2(const IndexedAllocationInfo &IAI) { |
| 26 | + size_t Size = 0; |
| 27 | + // The CallStackId |
| 28 | + Size += sizeof(CallStackId); |
| 29 | + // The size of the payload. |
| 30 | + Size += PortableMemInfoBlock::serializedSize(); |
| 31 | + return Size; |
| 32 | +} |
| 33 | +} // namespace |
| 34 | + |
| 35 | +size_t IndexedAllocationInfo::serializedSize(IndexedVersion Version) const { |
| 36 | + switch (Version) { |
| 37 | + case Version0: |
| 38 | + case Version1: |
| 39 | + return serializedSizeV0(*this); |
| 40 | + case Version2: |
| 41 | + return serializedSizeV2(*this); |
| 42 | + } |
| 43 | + llvm_unreachable("unsupported MemProf version"); |
| 44 | +} |
| 45 | + |
| 46 | +namespace { |
| 47 | +size_t serializedSizeV0(const IndexedMemProfRecord &Record) { |
| 48 | + size_t Result = sizeof(GlobalValue::GUID); |
| 49 | + for (const IndexedAllocationInfo &N : Record.AllocSites) |
| 50 | + Result += N.serializedSize(Version0); |
| 51 | + |
| 52 | + // The number of callsites we have information for. |
| 53 | + Result += sizeof(uint64_t); |
| 54 | + for (const auto &Frames : Record.CallSites) { |
| 55 | + // The number of frame ids to serialize. |
| 56 | + Result += sizeof(uint64_t); |
| 57 | + Result += Frames.size() * sizeof(FrameId); |
| 58 | + } |
| 59 | + return Result; |
| 60 | +} |
| 61 | + |
| 62 | +size_t serializedSizeV2(const IndexedMemProfRecord &Record) { |
| 63 | + size_t Result = sizeof(GlobalValue::GUID); |
| 64 | + for (const IndexedAllocationInfo &N : Record.AllocSites) |
| 65 | + Result += N.serializedSize(Version2); |
| 66 | + |
| 67 | + // The number of callsites we have information for. |
| 68 | + Result += sizeof(uint64_t); |
| 69 | + // The CallStackId |
| 70 | + Result += Record.CallSiteIds.size() * sizeof(CallStackId); |
| 71 | + return Result; |
| 72 | +} |
| 73 | +} // namespace |
| 74 | + |
| 75 | +size_t IndexedMemProfRecord::serializedSize(IndexedVersion Version) const { |
| 76 | + switch (Version) { |
| 77 | + case Version0: |
| 78 | + case Version1: |
| 79 | + return serializedSizeV0(*this); |
| 80 | + case Version2: |
| 81 | + return serializedSizeV2(*this); |
| 82 | + } |
| 83 | + llvm_unreachable("unsupported MemProf version"); |
| 84 | +} |
| 85 | + |
| 86 | +namespace { |
| 87 | +void serializeV0(const IndexedMemProfRecord &Record, |
| 88 | + const MemProfSchema &Schema, raw_ostream &OS) { |
16 | 89 | using namespace support;
|
17 | 90 |
|
18 | 91 | endian::Writer LE(OS, llvm::endianness::little);
|
19 | 92 |
|
20 |
| - LE.write<uint64_t>(AllocSites.size()); |
21 |
| - for (const IndexedAllocationInfo &N : AllocSites) { |
| 93 | + LE.write<uint64_t>(Record.AllocSites.size()); |
| 94 | + for (const IndexedAllocationInfo &N : Record.AllocSites) { |
22 | 95 | LE.write<uint64_t>(N.CallStack.size());
|
23 | 96 | for (const FrameId &Id : N.CallStack)
|
24 | 97 | LE.write<FrameId>(Id);
|
25 | 98 | N.Info.serialize(Schema, OS);
|
26 | 99 | }
|
27 | 100 |
|
28 | 101 | // Related contexts.
|
29 |
| - LE.write<uint64_t>(CallSites.size()); |
30 |
| - for (const auto &Frames : CallSites) { |
| 102 | + LE.write<uint64_t>(Record.CallSites.size()); |
| 103 | + for (const auto &Frames : Record.CallSites) { |
31 | 104 | LE.write<uint64_t>(Frames.size());
|
32 | 105 | for (const FrameId &Id : Frames)
|
33 | 106 | LE.write<FrameId>(Id);
|
34 | 107 | }
|
35 | 108 | }
|
36 | 109 |
|
37 |
| -IndexedMemProfRecord |
38 |
| -IndexedMemProfRecord::deserialize(const MemProfSchema &Schema, |
39 |
| - const unsigned char *Ptr) { |
| 110 | +void serializeV2(const IndexedMemProfRecord &Record, |
| 111 | + const MemProfSchema &Schema, raw_ostream &OS) { |
| 112 | + using namespace support; |
| 113 | + |
| 114 | + endian::Writer LE(OS, llvm::endianness::little); |
| 115 | + |
| 116 | + LE.write<uint64_t>(Record.AllocSites.size()); |
| 117 | + for (const IndexedAllocationInfo &N : Record.AllocSites) { |
| 118 | + LE.write<CallStackId>(N.CSId); |
| 119 | + N.Info.serialize(Schema, OS); |
| 120 | + } |
| 121 | + |
| 122 | + // Related contexts. |
| 123 | + LE.write<uint64_t>(Record.CallSiteIds.size()); |
| 124 | + for (const auto &CSId : Record.CallSiteIds) |
| 125 | + LE.write<CallStackId>(CSId); |
| 126 | +} |
| 127 | +} // namespace |
| 128 | + |
| 129 | +void IndexedMemProfRecord::serialize(const MemProfSchema &Schema, |
| 130 | + raw_ostream &OS, IndexedVersion Version) { |
| 131 | + switch (Version) { |
| 132 | + case Version0: |
| 133 | + case Version1: |
| 134 | + serializeV0(*this, Schema, OS); |
| 135 | + return; |
| 136 | + case Version2: |
| 137 | + serializeV2(*this, Schema, OS); |
| 138 | + return; |
| 139 | + } |
| 140 | + llvm_unreachable("unsupported MemProf version"); |
| 141 | +} |
| 142 | + |
| 143 | +namespace { |
| 144 | +IndexedMemProfRecord deserializeV0(const MemProfSchema &Schema, |
| 145 | + const unsigned char *Ptr) { |
40 | 146 | using namespace support;
|
41 | 147 |
|
42 | 148 | IndexedMemProfRecord Record;
|
@@ -73,11 +179,57 @@ IndexedMemProfRecord::deserialize(const MemProfSchema &Schema,
|
73 | 179 | Frames.push_back(Id);
|
74 | 180 | }
|
75 | 181 | Record.CallSites.push_back(Frames);
|
| 182 | + Record.CallSiteIds.push_back(hashCallStack(Frames)); |
76 | 183 | }
|
77 | 184 |
|
78 | 185 | return Record;
|
79 | 186 | }
|
80 | 187 |
|
| 188 | +IndexedMemProfRecord deserializeV2(const MemProfSchema &Schema, |
| 189 | + const unsigned char *Ptr) { |
| 190 | + using namespace support; |
| 191 | + |
| 192 | + IndexedMemProfRecord Record; |
| 193 | + |
| 194 | + // Read the meminfo nodes. |
| 195 | + const uint64_t NumNodes = |
| 196 | + endian::readNext<uint64_t, llvm::endianness::little, unaligned>(Ptr); |
| 197 | + for (uint64_t I = 0; I < NumNodes; I++) { |
| 198 | + IndexedAllocationInfo Node; |
| 199 | + Node.CSId = |
| 200 | + endian::readNext<CallStackId, llvm::endianness::little, unaligned>(Ptr); |
| 201 | + Node.Info.deserialize(Schema, Ptr); |
| 202 | + Ptr += PortableMemInfoBlock::serializedSize(); |
| 203 | + Record.AllocSites.push_back(Node); |
| 204 | + } |
| 205 | + |
| 206 | + // Read the callsite information. |
| 207 | + const uint64_t NumCtxs = |
| 208 | + endian::readNext<uint64_t, llvm::endianness::little, unaligned>(Ptr); |
| 209 | + for (uint64_t J = 0; J < NumCtxs; J++) { |
| 210 | + CallStackId CSId = |
| 211 | + endian::readNext<CallStackId, llvm::endianness::little, unaligned>(Ptr); |
| 212 | + Record.CallSiteIds.push_back(CSId); |
| 213 | + } |
| 214 | + |
| 215 | + return Record; |
| 216 | +} |
| 217 | +} // namespace |
| 218 | + |
| 219 | +IndexedMemProfRecord |
| 220 | +IndexedMemProfRecord::deserialize(const MemProfSchema &Schema, |
| 221 | + const unsigned char *Ptr, |
| 222 | + IndexedVersion Version) { |
| 223 | + switch (Version) { |
| 224 | + case Version0: |
| 225 | + case Version1: |
| 226 | + return deserializeV0(Schema, Ptr); |
| 227 | + case Version2: |
| 228 | + return deserializeV2(Schema, Ptr); |
| 229 | + } |
| 230 | + llvm_unreachable("unsupported MemProf version"); |
| 231 | +} |
| 232 | + |
81 | 233 | GlobalValue::GUID IndexedMemProfRecord::getGUID(const StringRef FunctionName) {
|
82 | 234 | // Canonicalize the function name to drop suffixes such as ".llvm.". Note
|
83 | 235 | // we do not drop any ".__uniq." suffixes, as getCanonicalFnName does not drop
|
|
0 commit comments