5
5
#include < string>
6
6
#include < vector>
7
7
8
- #include " llvm/ADT/DenseMap.h"
9
8
#include " llvm/ADT/SmallVector.h"
10
9
#include " llvm/ProfileData/MemProfData.inc"
11
10
#include " llvm/ProfileData/ProfileCommon.h"
@@ -135,65 +134,25 @@ struct PortableMemInfoBlock {
135
134
};
136
135
137
136
struct MemProfRecord {
138
- // Describes a call frame for a dynamic allocation context. The contents of
139
- // the frame are populated by symbolizing the stack depot call frame from the
140
- // compiler runtime.
141
- PACKED (struct Frame {
142
- // A uuid (uint64_t) identifying the function. It is obtained by
143
- // llvm::md5(FunctionName) which returns the lower 64 bits.
144
- GlobalValue::GUID Function;
145
- // The source line offset of the call from the beginning of parent function.
137
+ struct Frame {
138
+ std::string Function;
146
139
uint32_t LineOffset;
147
- // The source column number of the call to help distinguish multiple calls
148
- // on the same line.
149
140
uint32_t Column;
150
- // Whether the current frame is inlined.
151
141
bool IsInlineFrame;
152
142
153
- Frame (uint64_t Hash, uint32_t Off, uint32_t Col, bool Inline)
154
- : Function(Hash), LineOffset(Off), Column(Col), IsInlineFrame(Inline) {}
143
+ Frame (std::string Str, uint32_t Off, uint32_t Col, bool Inline)
144
+ : Function(std::move(Str)), LineOffset(Off), Column(Col),
145
+ IsInlineFrame (Inline) {}
146
+ };
155
147
156
- bool operator ==(const Frame &Other) const {
157
- return Other.Function == Function && Other.LineOffset == LineOffset &&
158
- Other.Column == Column && Other.IsInlineFrame == IsInlineFrame;
159
- }
160
-
161
- bool operator !=(const Frame &Other) const { return !operator ==(Other); }
162
-
163
- // Write the contents of the frame to the ostream \p OS.
164
- void write (raw_ostream & OS) const {
165
- using namespace support ;
166
-
167
- endian::Writer LE (OS, little);
168
-
169
- // If the type of the GlobalValue::GUID changes, then we need to update
170
- // the reader and the writer.
171
- static_assert (std::is_same<GlobalValue::GUID, uint64_t >::value,
172
- " Expect GUID to be uint64_t." );
173
- LE.write <uint64_t >(Function);
174
-
175
- LE.write <uint32_t >(LineOffset);
176
- LE.write <uint32_t >(Column);
177
- LE.write <bool >(IsInlineFrame);
178
- }
179
- });
180
-
181
- // The dynamic calling context for the allocation.
182
148
std::vector<Frame> CallStack;
183
- // The statistics obtained from the runtime for the allocation.
184
149
PortableMemInfoBlock Info;
185
150
186
151
void clear () {
187
152
CallStack.clear ();
188
153
Info.clear ();
189
154
}
190
155
191
- size_t serializedSize () const {
192
- return sizeof (uint64_t ) + // The number of frames to serialize.
193
- sizeof (Frame) * CallStack.size () + // The contents of the frames.
194
- PortableMemInfoBlock::serializedSize (); // The size of the payload.
195
- }
196
-
197
156
// Prints out the contents of the memprof record in YAML.
198
157
void print (llvm::raw_ostream &OS) const {
199
158
OS << " Callstack:\n " ;
@@ -209,138 +168,6 @@ struct MemProfRecord {
209
168
210
169
Info.printYAML (OS);
211
170
}
212
-
213
- bool operator ==(const MemProfRecord &Other) const {
214
- if (Other.Info != Info)
215
- return false ;
216
-
217
- if (Other.CallStack .size () != CallStack.size ())
218
- return false ;
219
-
220
- for (size_t I = 0 ; I < Other.CallStack .size (); I++) {
221
- if (Other.CallStack [I] != CallStack[I])
222
- return false ;
223
- }
224
- return true ;
225
- }
226
- };
227
-
228
- // Serializes the memprof records in \p Records to the ostream \p OS based on
229
- // the schema provided in \p Schema.
230
- void serializeRecords (const ArrayRef<MemProfRecord> Records,
231
- const MemProfSchema &Schema, raw_ostream &OS);
232
-
233
- // Deserializes memprof records from the Buffer
234
- SmallVector<MemProfRecord, 4 > deserializeRecords (const MemProfSchema &Schema,
235
- const unsigned char *Buffer);
236
-
237
- // Reads a memprof schema from a buffer. All entries in the buffer are
238
- // interpreted as uint64_t. The first entry in the buffer denotes the number of
239
- // ids in the schema. Subsequent entries are integers which map to memprof::Meta
240
- // enum class entries. After successfully reading the schema, the pointer is one
241
- // byte past the schema contents.
242
- Expected<MemProfSchema> readMemProfSchema (const unsigned char *&Buffer);
243
-
244
- using FunctionMemProfMap =
245
- DenseMap<uint64_t , SmallVector<memprof::MemProfRecord, 4 >>;
246
-
247
- // / Trait for lookups into the on-disk hash table for memprof format in the
248
- // / indexed profile.
249
- class MemProfRecordLookupTrait {
250
- public:
251
- using data_type = ArrayRef<MemProfRecord>;
252
- using internal_key_type = uint64_t ;
253
- using external_key_type = uint64_t ;
254
- using hash_value_type = uint64_t ;
255
- using offset_type = uint64_t ;
256
-
257
- MemProfRecordLookupTrait () = delete ;
258
- MemProfRecordLookupTrait (const MemProfSchema &S) : Schema(S) {}
259
-
260
- static bool EqualKey (uint64_t A, uint64_t B) { return A == B; }
261
- static uint64_t GetInternalKey (uint64_t K) { return K; }
262
- static uint64_t GetExternalKey (uint64_t K) { return K; }
263
-
264
- hash_value_type ComputeHash (uint64_t K) { return K; }
265
-
266
- static std::pair<offset_type, offset_type>
267
- ReadKeyDataLength (const unsigned char *&D) {
268
- using namespace support ;
269
-
270
- offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
271
- offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
272
- return std::make_pair (KeyLen, DataLen);
273
- }
274
-
275
- uint64_t ReadKey (const unsigned char *D, offset_type /* Unused*/ ) {
276
- using namespace support ;
277
- return endian::readNext<external_key_type, little, unaligned>(D);
278
- }
279
-
280
- data_type ReadData (uint64_t K, const unsigned char *D,
281
- offset_type /* Unused*/ ) {
282
- Records = deserializeRecords (Schema, D);
283
- return Records;
284
- }
285
-
286
- private:
287
- // Holds the memprof schema used to deserialize records.
288
- MemProfSchema Schema;
289
- // Holds the records from one function deserialized from the indexed format.
290
- llvm::SmallVector<MemProfRecord, 4 > Records;
291
- };
292
-
293
- class MemProfRecordWriterTrait {
294
- public:
295
- using key_type = uint64_t ;
296
- using key_type_ref = uint64_t ;
297
-
298
- using data_type = ArrayRef<MemProfRecord>;
299
- using data_type_ref = ArrayRef<MemProfRecord>;
300
-
301
- using hash_value_type = uint64_t ;
302
- using offset_type = uint64_t ;
303
-
304
- // Pointer to the memprof schema to use for the generator. Unlike the reader
305
- // we must use a default constructor with no params for the writer trait so we
306
- // have a public member which must be initialized by the user.
307
- MemProfSchema *Schema = nullptr ;
308
-
309
- MemProfRecordWriterTrait () = default ;
310
-
311
- static hash_value_type ComputeHash (key_type_ref K) { return K; }
312
-
313
- static std::pair<offset_type, offset_type>
314
- EmitKeyDataLength (raw_ostream &Out, key_type_ref K, data_type_ref V) {
315
- using namespace support ;
316
-
317
- endian::Writer LE (Out, little);
318
-
319
- offset_type N = sizeof (K);
320
- LE.write <offset_type>(N);
321
-
322
- offset_type M = 0 ;
323
-
324
- M += sizeof (uint64_t );
325
- for (const auto &Record : V) {
326
- M += Record.serializedSize ();
327
- }
328
-
329
- LE.write <offset_type>(M);
330
- return std::make_pair (N, M);
331
- }
332
-
333
- void EmitKey (raw_ostream &Out, key_type_ref K, offset_type /* Unused*/ ) {
334
- using namespace support ;
335
- endian::Writer LE (Out, little);
336
- LE.write <uint64_t >(K);
337
- }
338
-
339
- void EmitData (raw_ostream &Out, key_type_ref /* Unused*/ , data_type_ref V,
340
- offset_type /* Unused*/ ) {
341
- assert (Schema != nullptr && " MemProf schema is not initialized!" );
342
- serializeRecords (V, *Schema, Out);
343
- }
344
171
};
345
172
346
173
} // namespace memprof
0 commit comments