55#include < string>
66#include < vector>
77
8- #include " llvm/ADT/DenseMap.h"
98#include " llvm/ADT/SmallVector.h"
109#include " llvm/ProfileData/MemProfData.inc"
1110#include " llvm/ProfileData/ProfileCommon.h"
@@ -135,65 +134,25 @@ struct PortableMemInfoBlock {
135134};
136135
137136struct 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;
146139 uint32_t LineOffset;
147- // The source column number of the call to help distinguish multiple calls
148- // on the same line.
149140 uint32_t Column;
150- // Whether the current frame is inlined.
151141 bool IsInlineFrame;
152142
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+ };
155147
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.
182148 std::vector<Frame> CallStack;
183- // The statistics obtained from the runtime for the allocation.
184149 PortableMemInfoBlock Info;
185150
186151 void clear () {
187152 CallStack.clear ();
188153 Info.clear ();
189154 }
190155
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-
197156 // Prints out the contents of the memprof record in YAML.
198157 void print (llvm::raw_ostream &OS) const {
199158 OS << " Callstack:\n " ;
@@ -209,138 +168,6 @@ struct MemProfRecord {
209168
210169 Info.printYAML (OS);
211170 }
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- }
344171};
345172
346173} // namespace memprof
0 commit comments