14#include "llvm/Support/JSON.h"
26std::optional<llvm::StringRef>
28 size_t max_ncalls = 0;
29 std::optional<llvm::StringRef> max_name;
32 size_t ncalls = it.second;
33 if (ncalls > max_ncalls) {
41llvm::DenseMap<ConstString, size_t>
const &
84 lldb::addr_t load_addr, std::optional<ConstString> func_name) {
97 return &block_it->second;
108 llvm::DenseMap<ConstString, size_t> func_calls;
110 auto func_name_it =
m_call_isns.find(instruction_load_address);
112 if (std::optional<ConstString> func_name = func_name_it->second) {
113 func_calls[*func_name] = 1;
116 return {instruction_load_address, 1, std::move(func_calls)};
195 size_t num_calls = it.second;
204 for (
size_t i = start_unit_index + 1; i < start_unit_index + num_units; i++) {
208 return {start_unit_index, num_units, merged_metadata};
217 HTRBlockLayer ¤t_block_layer = *current_block_layer_up;
225 if (are_passes_done(current_block_layer, *new_block_layer_up))
228 current_block_layer = *new_block_layer_up;
235 llvm::raw_fd_ostream os(outfile, ec, llvm::sys::fs::OF_Text);
237 return llvm::make_error<llvm::StringError>(
238 "unable to open destination file: " + outfile, os.error());
242 if (os.has_error()) {
243 return llvm::make_error<llvm::StringError>(
244 "unable to write to destination file: " + outfile, os.error());
247 return llvm::Error::success();
251 std::unique_ptr<HTRBlockLayer> new_block_layer =
252 std::make_unique<HTRBlockLayer>(layer.
GetLayerId() + 1);
259 std::unordered_set<size_t> heads;
268 std::unordered_map<lldb::addr_t, std::unordered_set<lldb::addr_t>> head_map;
273 for (
size_t i = 1; i < num_units; i++) {
276 head_map[current_id].insert(prev_id);
277 prev_id = current_id;
279 for (
const auto &it : head_map) {
282 const std::unordered_set<lldb::addr_t> predecessor_set = it.second;
283 if (
id && predecessor_set.size() > 1)
290 std::unordered_set<lldb::addr_t> tails;
291 std::unordered_map<lldb::addr_t, std::unordered_set<lldb::addr_t>> tail_map;
294 for (
size_t i = 0; i < num_units - 1; i++) {
299 tail_map[current_id].insert(next_id);
305 tails.insert(last_id);
306 for (
const auto &it : tail_map) {
308 const std::unordered_set<lldb::addr_t> successor_set = it.second;
310 if (
id && successor_set.size() > 1)
316 size_t superblock_size = 0;
320 std::optional<size_t> superblock_head;
321 auto construct_next_layer = [&](
size_t merge_start,
size_t n) ->
void {
322 if (!superblock_head)
324 if (new_block_layer->GetBlockById(*superblock_head)) {
325 new_block_layer->AppendRepeatedBlock(*superblock_head);
328 new_block_layer->AppendNewBlock(*superblock_head, std::move(new_block));
332 for (
size_t i = 0; i < num_units; i++) {
335 auto isHead = heads.count(unit_id) > 0;
336 auto isTail = tails.count(unit_id) > 0;
338 if (isHead && isTail) {
340 if (superblock_size) {
344 construct_next_layer(i - superblock_size, superblock_size);
347 superblock_head = unit_id;
351 construct_next_layer(i - superblock_size + 1, superblock_size);
353 superblock_head = std::nullopt;
356 if (superblock_size) {
360 construct_next_layer(i - superblock_size, superblock_size);
363 superblock_head = unit_id;
366 if (!superblock_head)
367 superblock_head = unit_id;
371 construct_next_layer(i - superblock_size + 1, superblock_size);
373 superblock_head = std::nullopt;
376 if (!superblock_head)
377 superblock_head = unit_id;
382 return new_block_layer;
386 std::vector<llvm::json::Value> layers_as_json;
393 std::string display_name;
395 std::stringstream stream;
396 stream <<
"0x" << std::hex << load_address;
397 std::string load_address_hex_string(stream.str());
398 display_name.assign(load_address_hex_string);
423 layers_as_json.emplace_back(llvm::json::Object{
424 {
"name", display_name},
428 {
"pid", (int64_t)layer_id},
434 std::vector<size_t> block_id_trace = layer->GetBlockIdTrace();
435 for (
size_t i = 0; i < block_id_trace.size(); i++) {
436 size_t id = block_id_trace[i];
438 HTRBlock block = *layer->GetBlockById(
id);
439 llvm::json::Value block_json =
toJSON(block);
440 size_t layer_id = layer->GetLayerId();
444 std::optional<llvm::StringRef> most_freq_func =
446 std::stringstream stream;
448 std::string offset_hex_string(stream.str());
449 std::string display_name =
450 most_freq_func ? offset_hex_string +
": " + most_freq_func->str()
461 layers_as_json.emplace_back(llvm::json::Object{
462 {
"name", display_name},
464 {
"ts", (int64_t)start_ts},
465 {
"dur", (int64_t)duration},
466 {
"pid", (int64_t)layer_id},
467 {
"args", block_json},
469 start_ts += duration;
472 return layers_as_json;
476 return llvm::json::Value(
477 llvm::json::Object{{
"Metadata", block.
GetMetadata()}});
481 std::vector<llvm::json::Value> function_calls;
484 size_t n_calls = it.second;
485 function_calls.emplace_back(llvm::formatv(
"({0}: {1})", name, n_calls));
488 return llvm::json::Value(llvm::json::Object{
490 {
"Functions", function_calls}});
A uniqued constant string class.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
HTR layer composed of blocks of the trace.
std::unordered_map< size_t, HTRBlock > m_block_defs
Maps a unique Block ID to the corresponding HTRBlock.
HTRBlock const * GetBlockById(size_t block_id) const
Get an HTRBlock from its block id.
size_t GetNumUnits() const override
Get the total number of units (instruction or block) in this layer.
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...
void AppendRepeatedBlock(size_t block_id)
Appends a repeated block to the layer.
llvm::ArrayRef< size_t > GetBlockIdTrace() const
Get the block ID trace for this layer.
void AppendNewBlock(size_t block_id, HTRBlock &&block)
Appends a new block to the layer.
HTRBlockMetadata GetMetadataByIndex(size_t index) const override
Get the metadata of a unit (instruction or block) in the layer.
Block structure representing a sequence of trace "units" (ie instructions).
size_t GetSize() const
Get the number of blocks/instructions that make up this block in the previous layer.
size_t m_size
Number of blocks/instructions that make up this block in the previous layer.
size_t GetOffset() const
Get the offset of the start of this block in the previous layer.
size_t m_offset
Offset in the previous layer.
HTRBlockMetadata m_metadata
General metadata for this block.
HTRBlockMetadata const & GetMetadata() const
Get the metadata for this block.
"Base" layer of HTR representing the dynamic instructions of the trace.
size_t GetNumUnits() const override
Get the total number of units (instruction or block) in this layer.
std::vector< lldb::addr_t > m_instruction_trace
std::unordered_map< lldb::addr_t, std::optional< ConstString > > m_call_isns
HTRBlockMetadata GetMetadataByIndex(size_t index) const override
Get the metadata of a unit (instruction or block) in the layer.
void AppendInstruction(lldb::addr_t load_addr)
Append the load address of an instruction to the dynamic instruction trace.
void AddCallInstructionMetadata(lldb::addr_t load_addr, std::optional< ConstString > func_name)
Add metadata for a 'call' instruction of the trace.
llvm::ArrayRef< lldb::addr_t > GetInstructionTrace() const
Get the dynamic instruction trace.
HTR layer interface See lldb/docs/htr.rst for comprehensive HTR documentation.
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...
size_t m_layer_id
ID of the layer.
size_t GetLayerId() const
Get the ID of the layer.
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.
void SetForwards(bool forwards)
Set the direction to use in the TraceCursor::Next() method.
virtual bool Seek(int64_t offset, lldb::TraceCursorSeekType origin)=0
Make the cursor point to an item in the trace based on an origin point and an offset.
Top-level HTR class See lldb/docs/htr.rst for comprehensive HTR documentation.
std::vector< HTRBlockLayerUP > m_block_layer_ups
llvm::ArrayRef< HTRBlockLayerUP > GetBlockLayers() const
Get the block layers of this HTR.
HTRInstructionLayer const & GetInstructionLayer() const
Get the instruction layer of this HTR.
llvm::Error Export(std::string outfile)
Export HTR layers to the specified format and outfile.
void AddNewBlockLayer(HTRBlockLayerUP &&block_layer)
Add a new block layer to this HTR.
TraceHTR(Thread &thread, TraceCursor &cursor)
Constructor for a trace's HTR.
void ExecutePasses()
Executes passes on the HTR layers until no further summarization/compression is achieved.
HTRInstructionLayerUP m_instruction_layer_up
A class that represents a running process on the host machine.
HTRBlockLayerUP BasicSuperBlockMerge(IHTRLayer &layer)
The HTR passes are defined below:
std::unique_ptr< lldb_private::HTRBlockLayer > HTRBlockLayerUP
llvm::json::Value toJSON(const TraceSupportedResponse &packet)
@ eTraceCursorSeekTypeBeginning
The beginning of the trace, i.e the oldest item.