LLDB mainline
TraceHTR.h
Go to the documentation of this file.
1//===-- TraceHTR.h --------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLDB_TARGET_TRACE_HTR_H
10#define LLDB_TARGET_TRACE_HTR_H
11
12#include "lldb/Target/Thread.h"
13#include "lldb/Target/Trace.h"
14
15#include <optional>
16#include <unordered_map>
17#include <unordered_set>
18
19namespace lldb_private {
20
21/// Metadata associated with an HTR block
22/// See lldb/docs/htr.rst for comprehensive HTR documentation
24public:
25 /// Constructor for a block's metadata.
26 ///
27 /// \param[in] first_instruction_load_address
28 /// The load address of the block's first instruction.
29 ///
30 /// \param[in] num_instructions
31 /// The total number of instructions in the block.
32 ///
33 /// \param[in] func_calls
34 /// The map of a function name to the number of times it is called from
35 /// the block.
36 HTRBlockMetadata(lldb::addr_t first_instruction_load_address,
37 size_t num_instructions,
38 llvm::DenseMap<ConstString, size_t> &&func_calls)
39 : m_first_instruction_load_address(first_instruction_load_address),
40 m_num_instructions(num_instructions), m_func_calls(func_calls) {}
41
42 /// Merge two \a HTRBlockMetadata in place.
43 ///
44 /// \param[in][out] merged_metadata
45 /// Metadata that metadata_to_merge will be merged into.
46 ///
47 /// \param[in] metadata_to_merge
48 /// Metadata to merge into merged_metadata.
49 static void MergeMetadata(HTRBlockMetadata &merged_metadata,
50 HTRBlockMetadata const &metadata_to_merge);
51 /// Get the number of instructions in the block.
52 ///
53 /// \return
54 /// The number of instructions in the block.
55 size_t GetNumInstructions() const;
56
57 /// Get the name of the most frequently called function from the block.
58 ///
59 /// \return
60 /// The name of the function that is called the most from this block or
61 /// std::nullopt if no function is called from this block.
62 std::optional<llvm::StringRef> GetMostFrequentlyCalledFunction() const;
63
64 /// Get the load address of the first instruction in the block.
65 ///
66 /// \return
67 /// The load address of the first instruction in the block.
69
70 /// Get the function calls map for the block.
71 /// Function calls are identified in the instruction layer by finding 'call'
72 /// instructions and determining the function they are calling. As these
73 /// instructions are merged into blocks, we merge these different function
74 /// calls into a single map containing the function names to the number of
75 /// times it is called from this block.
76 ///
77 /// \return
78 /// The mapping of function name to the number of times it is called from
79 /// this block.
80 llvm::DenseMap<ConstString, size_t> const &GetFunctionCalls() const;
81
82private:
85 llvm::DenseMap<ConstString, size_t> m_func_calls;
86};
87
88/// Block structure representing a sequence of trace "units" (ie instructions).
89/// Sequences of blocks are merged to create a new, single block
90/// See lldb/docs/htr.rst for comprehensive HTR documentation
91class HTRBlock {
92public:
93 /// Constructor for a block of an HTR layer.
94 ///
95 /// \param[in] offset
96 /// The offset of the start of this block in the previous layer.
97 ///
98 /// \param[in] size
99 /// Number of blocks/instructions that make up this block in the previous
100 /// layer.
101 ///
102 /// \param[in] metadata
103 /// General metadata for this block.
104 HTRBlock(size_t offset, size_t size, HTRBlockMetadata metadata)
105 : m_offset(offset), m_size(size), m_metadata(metadata) {}
106
107 /// Get the offset of the start of this block in the previous layer.
108 ///
109 /// \return
110 /// The offset of the block.
111 size_t GetOffset() const;
112
113 /// Get the number of blocks/instructions that make up this block in the
114 /// previous layer.
115 ///
116 /// \return
117 /// The size of the block.
118 size_t GetSize() const;
119
120 /// Get the metadata for this block.
121 ///
122 /// \return
123 /// The metadata of the block.
124 HTRBlockMetadata const &GetMetadata() const;
125
126private:
127 /// Offset in the previous layer
128 size_t m_offset;
129 /// Number of blocks/instructions that make up this block in the previous
130 /// layer
131 size_t m_size;
132 /// General metadata for this block
134};
135
136/// HTR layer interface
137/// See lldb/docs/htr.rst for comprehensive HTR documentation
139public:
140 /// Construct new HTR layer.
141 //
142 /// \param[in] id
143 /// The layer's id.
144 IHTRLayer(size_t id) : m_layer_id(id) {}
145
146 /// Get the ID of the layer.
147 ///
148 /// \return
149 /// The layer ID of this layer.
150 size_t GetLayerId() const;
151
152 /// Get the metadata of a unit (instruction or block) in the layer.
153 ///
154 /// \param[in] index
155 /// The position of the unit in the layer.
156 ///
157 /// \return
158 /// The metadata of the unit in the layer.
159 virtual HTRBlockMetadata GetMetadataByIndex(size_t index) const = 0;
160
161 /// Get the total number of units (instruction or block) in this layer.
162 ///
163 /// \return
164 /// The total number of units in the layer.
165 virtual size_t GetNumUnits() const = 0;
166
167 /// Creates a new block from the result of merging a contiguous sequence of
168 /// "units" (instructions or blocks depending on layer type) in this layer
169 /// This allows the implementation class to decide how to store/generate this
170 /// metadata. For example, in the case of the instruction layer we want to
171 /// lazily generate this metadata instead of storing it for each instruction.
172 ///
173 /// \param[in] start_unit_index
174 /// The index of the first unit to be merged.
175 ///
176 /// \param[in] num_units
177 /// The number of units to be merged. Must be >= 1, since merging 0 blocks
178 /// does not make sense.
179 ///
180 /// \return
181 /// A new block instance representing the merge of the specified units.
182 HTRBlock MergeUnits(size_t start_unit_index, size_t num_units);
183
184 virtual ~IHTRLayer() = default;
185
186protected:
187 /// ID of the layer.
189};
190
191/// "Base" layer of HTR representing the dynamic instructions of the trace.
192/// See lldb/docs/htr.rst for comprehensive HTR documentation
194public:
195 /// Construct new instruction layer.
196 //
197 /// \param[in] id
198 /// The layer's id.
200
201 size_t GetNumUnits() const override;
202
203 HTRBlockMetadata GetMetadataByIndex(size_t index) const override;
204
205 /// Get the dynamic instruction trace.
206 ///
207 /// \return
208 /// The dynamic instruction trace.
209 llvm::ArrayRef<lldb::addr_t> GetInstructionTrace() const;
210
211 /// Add metadata for a 'call' instruction of the trace.
212 ///
213 /// \param[in] load_addr
214 /// The load address of the 'call' instruction.
215 ///
216 /// \param[in] func_name
217 /// The name of the function the 'call' instruction is calling if it can
218 /// be determined, std::nullopt otherwise.
220 std::optional<ConstString> func_name);
221
222 /// Append the load address of an instruction to the dynamic instruction
223 /// trace.
224 ///
225 /// \param[in] load_addr
226 /// The load address of the instruction.
227 void AppendInstruction(lldb::addr_t load_addr);
228
229private:
230 // Dynamic instructions of trace are stored in chronological order.
231 std::vector<lldb::addr_t> m_instruction_trace;
232 // Only store metadata for instructions of interest (call instructions)
233 // If we stored metadata for each instruction this would be wasteful since
234 // most instructions don't contain useful metadata
235
236 // This map contains the load address of all the call instructions.
237 // load address maps to the name of the function it calls (std::nullopt if
238 // function name can't be determined)
239 std::unordered_map<lldb::addr_t, std::optional<ConstString>> m_call_isns;
240};
241
242/// HTR layer composed of blocks of the trace.
243/// See lldb/docs/htr.rst for comprehensive HTR documentation
244class HTRBlockLayer : public IHTRLayer {
245public:
246 /// Construct new block layer.
247 //
248 /// \param[in] id
249 /// The layer's id.
250 HTRBlockLayer(size_t id) : IHTRLayer(id) {}
251
252 size_t GetNumUnits() const override;
253
254 HTRBlockMetadata GetMetadataByIndex(size_t index) const override;
255
256 /// Get an \a HTRBlock from its block id.
257 ///
258 /// \param[in] block_id
259 /// The id of the block to retrieve.
260 ///
261 /// \return
262 /// The \a HTRBlock with the specified id, nullptr if no there is no block
263 /// in the layer with the specified block id.
264 HTRBlock const *GetBlockById(size_t block_id) const;
265
266 /// Get the block ID trace for this layer.
267 /// This block ID trace stores the block ID of each block that occured in the
268 /// trace and the block defs map maps block ID to the corresponding \a
269 /// HTRBlock.
270 ///
271 /// \return
272 /// The block ID trace for this layer.
273 llvm::ArrayRef<size_t> GetBlockIdTrace() const;
274
275 /// Appends a new block to the layer.
276 ///
277 /// \param[in] block_id
278 /// The block id of the new block.
279 ///
280 /// \param[in] block
281 /// The new \a HTRBlock to be appended to the layer. This block is moved
282 /// into the layer.
283 void AppendNewBlock(size_t block_id, HTRBlock &&block);
284
285 /// Appends a repeated block to the layer.
286 ///
287 /// \param[in] block_id
288 /// The block id of the repeated block.
289 void AppendRepeatedBlock(size_t block_id);
290
291private:
292 /// Maps a unique Block ID to the corresponding HTRBlock
293 std::unordered_map<size_t, HTRBlock> m_block_defs;
294 /// Reduce memory footprint by just storing a trace of block IDs and use
295 /// m_block_defs to map a block_id to its corresponding HTRBlock
296 std::vector<size_t> m_block_id_trace;
297};
298
299typedef std::unique_ptr<lldb_private::HTRBlockLayer> HTRBlockLayerUP;
300typedef std::unique_ptr<lldb_private::HTRInstructionLayer>
302
303/// Top-level HTR class
304/// See lldb/docs/htr.rst for comprehensive HTR documentation
305class TraceHTR {
306
307public:
308 /// Constructor for a trace's HTR.
309 ///
310 /// \param[in] thread
311 /// The thread the trace belongs to.
312 ///
313 /// \param[in] cursor
314 /// The trace cursor that gives access to the trace's contents.
315 TraceHTR(Thread &thread, TraceCursor &cursor);
316
317 /// Executes passes on the HTR layers until no further
318 /// summarization/compression is achieved
319 void ExecutePasses();
320
321 /// Export HTR layers to the specified format and outfile.
322 ///
323 /// \param[in] outfile
324 /// The file that the exported HTR data will be written to.
325 ///
326 /// \return
327 /// Success if the export is successful, Error otherwise.
328 llvm::Error Export(std::string outfile);
329
330 /// Get the block layers of this HTR.
331 ///
332 /// \return
333 /// The block layers of this HTR.
334 llvm::ArrayRef<HTRBlockLayerUP> GetBlockLayers() const;
335
336 /// Get the instruction layer of this HTR.
337 ///
338 /// \return
339 /// The instruction layer of this HTR.
341
342 /// Add a new block layer to this HTR.
343 ///
344 /// \param[in]
345 /// The new block layer to be added.
346 void AddNewBlockLayer(HTRBlockLayerUP &&block_layer);
347
348private:
349 // There is a single instruction layer per HTR
351 // There are one or more block layers per HTR
352 std::vector<HTRBlockLayerUP> m_block_layer_ups;
353};
354
355// Serialization functions for exporting HTR to Chrome Trace Format
356llvm::json::Value toJSON(const TraceHTR &htr);
357llvm::json::Value toJSON(const HTRBlock &block);
358llvm::json::Value toJSON(const HTRBlockMetadata &metadata);
359
360/// The HTR passes are defined below:
361
362/// Creates a new layer by merging the "basic super blocks" in the current layer
363///
364/// A "basic super block" is the longest sequence of blocks that always occur in
365/// the same order. (The concept is akin to “Basic Block" in compiler theory,
366/// but refers to dynamic occurrences rather than CFG nodes)
367///
368/// Procedure to find all basic super blocks:
369//
370/// - For each block, compute the number of distinct predecessor and
371/// successor blocks.
372/// Predecessor - the block that occurs directly before (to the left of)
373/// the current block Successor - the block that occurs directly after
374/// (to the right of) the current block
375/// - A block with more than one distinct successor is always the start of a
376/// super block, the super block will continue until the next block with
377/// more than one distinct predecessor or successor.
378///
379/// The implementation makes use of two terms - 'heads' and 'tails' known as
380/// the 'endpoints' of a basic super block:
381/// A 'head' is defined to be a block in the trace that doesn't have a
382/// unique predecessor
383/// A 'tail' is defined to be a block in the trace that doesn't have a
384/// unique successor
385///
386/// A basic super block is defined to be a sequence of blocks between two
387/// endpoints
388///
389/// A head represents the start of the next group, so the current group
390/// ends at the block preceding the head and the next group begins with
391/// this head block
392///
393/// A tail represents the end of the current group, so the current group
394/// ends with the tail block and the next group begins with the
395/// following block.
396///
397/// See lldb/docs/htr.rst for comprehensive HTR documentation
398///
399/// \param[in] layer
400/// The layer to execute the pass on.
401///
402/// \return
403/// A new layer instance representing the merge of blocks in the
404/// previous layer
406
407} // namespace lldb_private
408
409#endif // LLDB_TARGET_TRACE_HTR_H
HTR layer composed of blocks of the trace.
Definition: TraceHTR.h:244
std::unordered_map< size_t, HTRBlock > m_block_defs
Maps a unique Block ID to the corresponding HTRBlock.
Definition: TraceHTR.h:293
HTRBlock const * GetBlockById(size_t block_id) const
Get an HTRBlock from its block id.
Definition: TraceHTR.cpp:92
size_t GetNumUnits() const override
Get the total number of units (instruction or block) in this layer.
Definition: TraceHTR.cpp:104
HTRBlockLayer(size_t id)
Construct new block layer.
Definition: TraceHTR.h:250
std::vector< size_t > m_block_id_trace
Reduce memory footprint by just storing a trace of block IDs and use m_block_defs to map a block_id t...
Definition: TraceHTR.h:296
void AppendRepeatedBlock(size_t block_id)
Appends a repeated block to the layer.
Definition: TraceHTR.cpp:75
llvm::ArrayRef< size_t > GetBlockIdTrace() const
Get the block ID trace for this layer.
Definition: TraceHTR.cpp:100
void AppendNewBlock(size_t block_id, HTRBlock &&block)
Appends a new block to the layer.
Definition: TraceHTR.cpp:70
HTRBlockMetadata GetMetadataByIndex(size_t index) const override
Get the metadata of a unit (instruction or block) in the layer.
Definition: TraceHTR.cpp:123
Metadata associated with an HTR block See lldb/docs/htr.rst for comprehensive HTR documentation.
Definition: TraceHTR.h:23
static void MergeMetadata(HTRBlockMetadata &merged_metadata, HTRBlockMetadata const &metadata_to_merge)
Merge two HTRBlockMetadata in place.
Definition: TraceHTR.cpp:189
size_t GetNumInstructions() const
Get the number of instructions in the block.
Definition: TraceHTR.cpp:22
lldb::addr_t m_first_instruction_load_address
Definition: TraceHTR.h:83
std::optional< llvm::StringRef > GetMostFrequentlyCalledFunction() const
Get the name of the most frequently called function from the block.
Definition: TraceHTR.cpp:27
llvm::DenseMap< ConstString, size_t > const & GetFunctionCalls() const
Get the function calls map for the block.
Definition: TraceHTR.cpp:42
lldb::addr_t GetFirstInstructionLoadAddress() const
Get the load address of the first instruction in the block.
Definition: TraceHTR.cpp:46
llvm::DenseMap< ConstString, size_t > m_func_calls
Definition: TraceHTR.h:85
HTRBlockMetadata(lldb::addr_t first_instruction_load_address, size_t num_instructions, llvm::DenseMap< ConstString, size_t > &&func_calls)
Constructor for a block's metadata.
Definition: TraceHTR.h:36
Block structure representing a sequence of trace "units" (ie instructions).
Definition: TraceHTR.h:91
size_t GetSize() const
Get the number of blocks/instructions that make up this block in the previous layer.
Definition: TraceHTR.cpp:52
size_t m_size
Number of blocks/instructions that make up this block in the previous layer.
Definition: TraceHTR.h:131
size_t GetOffset() const
Get the offset of the start of this block in the previous layer.
Definition: TraceHTR.cpp:50
HTRBlock(size_t offset, size_t size, HTRBlockMetadata metadata)
Constructor for a block of an HTR layer.
Definition: TraceHTR.h:104
size_t m_offset
Offset in the previous layer.
Definition: TraceHTR.h:128
HTRBlockMetadata m_metadata
General metadata for this block.
Definition: TraceHTR.h:133
HTRBlockMetadata const & GetMetadata() const
Get the metadata for this block.
Definition: TraceHTR.cpp:54
"Base" layer of HTR representing the dynamic instructions of the trace.
Definition: TraceHTR.h:193
size_t GetNumUnits() const override
Get the total number of units (instruction or block) in this layer.
Definition: TraceHTR.cpp:119
std::vector< lldb::addr_t > m_instruction_trace
Definition: TraceHTR.h:231
std::unordered_map< lldb::addr_t, std::optional< ConstString > > m_call_isns
Definition: TraceHTR.h:239
HTRBlockMetadata GetMetadataByIndex(size_t index) const override
Get the metadata of a unit (instruction or block) in the layer.
Definition: TraceHTR.cpp:106
void AppendInstruction(lldb::addr_t load_addr)
Append the load address of an instruction to the dynamic instruction trace.
Definition: TraceHTR.cpp:88
void AddCallInstructionMetadata(lldb::addr_t load_addr, std::optional< ConstString > func_name)
Add metadata for a 'call' instruction of the trace.
Definition: TraceHTR.cpp:83
llvm::ArrayRef< lldb::addr_t > GetInstructionTrace() const
Get the dynamic instruction trace.
Definition: TraceHTR.cpp:79
HTRInstructionLayer(size_t id)
Construct new instruction layer.
Definition: TraceHTR.h:199
HTR layer interface See lldb/docs/htr.rst for comprehensive HTR documentation.
Definition: TraceHTR.h:138
IHTRLayer(size_t id)
Construct new HTR layer.
Definition: TraceHTR.h:144
virtual size_t GetNumUnits() const =0
Get the total number of units (instruction or block) in this layer.
HTRBlock MergeUnits(size_t start_unit_index, size_t num_units)
Creates a new block from the result of merging a contiguous sequence of "units" (instructions or bloc...
Definition: TraceHTR.cpp:200
virtual ~IHTRLayer()=default
size_t m_layer_id
ID of the layer.
Definition: TraceHTR.h:188
size_t GetLayerId() const
Get the ID of the layer.
Definition: TraceHTR.cpp:68
virtual HTRBlockMetadata GetMetadataByIndex(size_t index) const =0
Get the metadata of a unit (instruction or block) in the layer.
Class used for iterating over the instructions of a thread's trace, among other kinds of information.
Definition: TraceCursor.h:94
Top-level HTR class See lldb/docs/htr.rst for comprehensive HTR documentation.
Definition: TraceHTR.h:305
std::vector< HTRBlockLayerUP > m_block_layer_ups
Definition: TraceHTR.h:352
llvm::ArrayRef< HTRBlockLayerUP > GetBlockLayers() const
Get the block layers of this HTR.
Definition: TraceHTR.cpp:56
HTRInstructionLayer const & GetInstructionLayer() const
Get the instruction layer of this HTR.
Definition: TraceHTR.cpp:60
llvm::Error Export(std::string outfile)
Export HTR layers to the specified format and outfile.
Definition: TraceHTR.cpp:233
void AddNewBlockLayer(HTRBlockLayerUP &&block_layer)
Add a new block layer to this HTR.
Definition: TraceHTR.cpp:64
void ExecutePasses()
Executes passes on the HTR layers until no further summarization/compression is achieved.
Definition: TraceHTR.cpp:211
HTRInstructionLayerUP m_instruction_layer_up
Definition: TraceHTR.h:350
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
std::unique_ptr< lldb_private::HTRInstructionLayer > HTRInstructionLayerUP
Definition: TraceHTR.h:301
HTRBlockLayerUP BasicSuperBlockMerge(IHTRLayer &layer)
The HTR passes are defined below:
Definition: TraceHTR.cpp:250
std::unique_ptr< lldb_private::HTRBlockLayer > HTRBlockLayerUP
Definition: TraceHTR.h:299
llvm::json::Value toJSON(const TraceSupportedResponse &packet)
uint64_t addr_t
Definition: lldb-types.h:79