14 #include "llvm/Support/JSON.h"
22 return m_num_instructions;
25 llvm::Optional<llvm::StringRef>
27 size_t max_ncalls = 0;
28 llvm::Optional<llvm::StringRef> max_name = llvm::None;
29 for (
const auto &it : m_func_calls) {
31 size_t ncalls = it.second;
32 if (ncalls > max_ncalls) {
40 llvm::DenseMap<ConstString, size_t>
const &
46 return m_first_instruction_load_address;
56 return m_block_layer_ups;
60 return *m_instruction_layer_up;
64 m_block_layer_ups.emplace_back(std::move(block_layer));
70 m_block_id_trace.emplace_back(block_id);
71 m_block_defs.emplace(block_id, block);
75 m_block_id_trace.emplace_back(block_id);
79 return m_instruction_trace;
83 lldb::addr_t load_addr, llvm::Optional<ConstString> func_name) {
84 m_call_isns.emplace(load_addr, func_name);
88 m_instruction_trace.emplace_back(load_addr);
92 auto block_it = m_block_defs.find(block_id);
93 if (block_it == m_block_defs.end())
96 return &block_it->second;
100 return m_block_id_trace;
106 lldb::addr_t instruction_load_address = m_instruction_trace[index];
107 llvm::DenseMap<ConstString, size_t> func_calls;
109 auto func_name_it = m_call_isns.find(instruction_load_address);
110 if (func_name_it != m_call_isns.end()) {
111 if (llvm::Optional<ConstString> func_name = func_name_it->second) {
112 func_calls[*func_name] = 1;
115 return {instruction_load_address, 1, std::move(func_calls)};
119 return m_instruction_trace.size();
123 size_t block_id = m_block_id_trace[index];
124 HTRBlock block = m_block_defs.find(block_id)->second;
194 size_t num_calls = it.second;
203 for (
size_t i = start_unit_index + 1; i < start_unit_index + num_units; i++) {
207 return {start_unit_index, num_units, merged_metadata};
216 HTRBlockLayer ¤t_block_layer = *current_block_layer_up;
224 if (are_passes_done(current_block_layer, *new_block_layer_up))
227 current_block_layer = *new_block_layer_up;
234 llvm::raw_fd_ostream os(outfile, ec, llvm::sys::fs::OF_Text);
236 return llvm::make_error<llvm::StringError>(
237 "unable to open destination file: " + outfile, os.error());
241 if (os.has_error()) {
242 return llvm::make_error<llvm::StringError>(
243 "unable to write to destination file: " + outfile, os.error());
246 return llvm::Error::success();
250 std::unique_ptr<HTRBlockLayer> new_block_layer =
251 std::make_unique<HTRBlockLayer>(layer.
GetLayerId() + 1);
258 std::unordered_set<size_t> heads;
267 std::unordered_map<lldb::addr_t, std::unordered_set<lldb::addr_t>> head_map;
272 for (
size_t i = 1; i < num_units; i++) {
275 head_map[current_id].insert(prev_id);
276 prev_id = current_id;
278 for (
const auto &it : head_map) {
281 const std::unordered_set<lldb::addr_t> predecessor_set = it.second;
282 if (
id && predecessor_set.size() > 1)
289 std::unordered_set<lldb::addr_t> tails;
290 std::unordered_map<lldb::addr_t, std::unordered_set<lldb::addr_t>> tail_map;
293 for (
size_t i = 0; i < num_units - 1; i++) {
298 tail_map[current_id].insert(next_id);
304 tails.insert(last_id);
305 for (
const auto &it : tail_map) {
307 const std::unordered_set<lldb::addr_t> successor_set = it.second;
309 if (
id && successor_set.size() > 1)
315 size_t superblock_size = 0;
319 llvm::Optional<size_t> superblock_head = llvm::None;
320 auto construct_next_layer = [&](
size_t merge_start,
size_t n) ->
void {
321 if (!superblock_head)
323 if (new_block_layer->GetBlockById(*superblock_head)) {
324 new_block_layer->AppendRepeatedBlock(*superblock_head);
327 new_block_layer->AppendNewBlock(*superblock_head, std::move(new_block));
331 for (
size_t i = 0; i < num_units; i++) {
334 auto isHead = heads.count(unit_id) > 0;
335 auto isTail = tails.count(unit_id) > 0;
337 if (isHead && isTail) {
339 if (superblock_size) {
343 construct_next_layer(i - superblock_size, superblock_size);
346 superblock_head = unit_id;
350 construct_next_layer(i - superblock_size + 1, superblock_size);
352 superblock_head = llvm::None;
355 if (superblock_size) {
359 construct_next_layer(i - superblock_size, superblock_size);
362 superblock_head = unit_id;
365 if (!superblock_head)
366 superblock_head = unit_id;
370 construct_next_layer(i - superblock_size + 1, superblock_size);
372 superblock_head = llvm::None;
375 if (!superblock_head)
376 superblock_head = unit_id;
381 return new_block_layer;
385 std::vector<llvm::json::Value> layers_as_json;
394 std::stringstream stream;
395 stream <<
"0x" << std::hex << load_address;
397 display_name.assign(load_address_hex_string);
422 layers_as_json.emplace_back(llvm::json::Object{
423 {
"name", display_name},
427 {
"pid", (int64_t)layer_id},
433 std::vector<size_t> block_id_trace = layer->GetBlockIdTrace();
434 for (
size_t i = 0; i < block_id_trace.size(); i++) {
435 size_t id = block_id_trace[i];
437 HTRBlock block = *layer->GetBlockById(
id);
438 llvm::json::Value block_json =
toJSON(block);
439 size_t layer_id = layer->GetLayerId();
443 llvm::Optional<llvm::StringRef> most_freq_func =
445 std::stringstream stream;
449 most_freq_func ? offset_hex_string +
": " + most_freq_func->str()
460 layers_as_json.emplace_back(llvm::json::Object{
461 {
"name", display_name},
463 {
"ts", (int64_t)start_ts},
464 {
"dur", (int64_t)duration},
465 {
"pid", (int64_t)layer_id},
466 {
"args", block_json},
468 start_ts += duration;
471 return layers_as_json;
475 return llvm::json::Value(
476 llvm::json::Object{{
"Metadata", block.
GetMetadata()}});
480 std::vector<llvm::json::Value> function_calls;
483 size_t n_calls = it.second;
484 function_calls.emplace_back(llvm::formatv(
"({0}: {1})", name, n_calls));
487 return llvm::json::Value(llvm::json::Object{
489 {
"Functions", function_calls}});