[PATCH v2 3/3] perf annotate: Support the new source code view for TUI
From: Taeung Song
Date: Tue Feb 28 2017 - 15:01:31 EST
Current source code view in TUI also has
problems showing wrong line number and
confusing mixed source code & dissambly view.
So fix it with the new source code view.
We can toggle the new source code view by a 's' key.
Before:
â11 void pack_knapsack(struct jewelry *jewelry)
â12 {
â push %rbp
â mov %rsp,%rbp
â sub $0x18,%rsp
â mov %rdi,-0x18(%rbp)
â17 * price per limited weight.
â18 */
â19 int wgt;
â20 unsigned int maxprice;
â
â22 if (limited_wgt < jewelry->wgt)
â mov -0x18(%rbp),%rax
â mov (%rax),%edx
â mov limited_wgt,%eax
â cmp %eax,%edx
â â ja 8d
â28 return;
â
â30 for (wgt = 0; wgt <= limited_wgt; wgt++) {
â movl $0x0,-0x8(%rbp)
â â jmp 7e
â33 if (jewelry->wgt <= wgt) {
4.88 â25: mov -0x18(%rbp),%rax
â mov (%rax),%edx
1.22 â mov -0x8(%rbp),%eax
1.22 â cmp %eax,%edx
2.44 â â ja 7a
â39 maxprice = get_cond_maxprice(wgt, jewelry);
After:
â46 void pack_knapsack(struct jewelry *jewelry)
â47 {
â48 /* Case by case pack knapsack following maximum
â49 * price per limited weight.
â50 */
â51 int wgt;
â52 unsigned int maxprice;
â53
â54 if (limited_wgt < jewelry->wgt)
â55 return;
â56
52.44 â57 for (wgt = 0; wgt <= limited_wgt; wgt++) {
9.76 â58 if (jewelry->wgt <= wgt) {
25.61 â59 maxprice = get_cond_maxprice(wgt, jewelry);
Cc: Namhyung Kim <namhyung@xxxxxxxxxx>
Cc: Jiri Olsa <jolsa@xxxxxxxxxx>
Signed-off-by: Taeung Song <treeze.taeung@xxxxxxxxx>
---
tools/perf/ui/browsers/annotate.c | 170 ++++++++++++++++++++++++++++----------
tools/perf/util/annotate.h | 1 +
2 files changed, 128 insertions(+), 43 deletions(-)
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 03b2012..d6d072b 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -39,7 +39,7 @@ static struct annotate_browser_opt {
};
struct annotate_browser {
- struct ui_browser b;
+ struct ui_browser b, cb;
struct rb_root entries;
struct rb_node *curr_hot;
struct disasm_line *selection;
@@ -52,6 +52,7 @@ struct annotate_browser {
int nr_jumps;
bool searching_backwards;
bool have_cycles;
+ bool has_src_code;
u8 addr_width;
u8 jumps_width;
u8 target_width;
@@ -104,6 +105,47 @@ static int annotate_browser__pcnt_width(struct annotate_browser *ab)
return w;
}
+static void annotate_code_browser__write(struct ui_browser *browser, void *entry, int row)
+{
+ struct annotate_browser *ab = container_of(browser, struct annotate_browser, cb);
+ struct code_line *cl = list_entry(entry, struct code_line, node);
+ bool current_entry = ui_browser__is_current_entry(browser, row);
+ int i, printed;
+ double percent, max_percent = 0.0;
+ char line[256];
+
+ for (i = 0; i < ab->nr_events; i++) {
+ percent = cl->samples_sum[i].percent;
+ ui_browser__set_percent_color(browser, percent, current_entry);
+ if (percent == 0.0) {
+ ui_browser__write_nstring(browser, " ", 7 * ab->nr_events);
+ continue;
+ }
+
+ if (annotate_browser__opts.show_total_period)
+ ui_browser__printf(browser, "%6" PRIu64 " ",
+ cl->samples_sum[i].nr);
+ else
+ ui_browser__printf(browser, "%6.2f ", percent);
+
+ if (max_percent < percent)
+ max_percent = percent;
+ }
+
+ SLsmg_write_char(' ');
+
+ if (annotate_browser__opts.show_linenr)
+ printed = scnprintf(line, sizeof(line), "%-*d ",
+ ab->addr_width + 2, cl->line_nr);
+ else
+ printed = scnprintf(line, sizeof(line), "%*s ",
+ ab->addr_width, " ");
+
+ ui_browser__set_percent_color(browser, percent, current_entry);
+ ui_browser__write_nstring(browser, line, printed);
+ ui_browser__write_nstring(browser, cl->line, browser->width);
+}
+
static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
{
struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
@@ -284,6 +326,17 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
from, to);
}
+static unsigned int annotate_code_browser__refresh(struct ui_browser *browser)
+{
+ struct annotate_browser *ab = container_of(browser, struct annotate_browser, cb);
+ int ret = ui_browser__list_head_refresh(browser);
+ int pcnt_width = annotate_browser__pcnt_width(ab);
+
+ ui_browser__set_color(browser, HE_COLORSET_NORMAL);
+ __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1);
+ return ret;
+}
+
static unsigned int annotate_browser__refresh(struct ui_browser *browser)
{
struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
@@ -394,6 +447,9 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
continue;
}
+ if (browser->has_src_code)
+ source_code__set_samples(pos, notes, evsel);
+
next = disasm__get_next_ip_line(¬es->src->source, pos);
for (i = 0; i < browser->nr_events; i++) {
@@ -422,45 +478,6 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
browser->curr_hot = rb_last(&browser->entries);
}
-static bool annotate_browser__toggle_source(struct annotate_browser *browser)
-{
- struct disasm_line *dl;
- struct browser_disasm_line *bdl;
- off_t offset = browser->b.index - browser->b.top_idx;
-
- browser->b.seek(&browser->b, offset, SEEK_CUR);
- dl = list_entry(browser->b.top, struct disasm_line, node);
- bdl = disasm_line__browser(dl);
-
- if (annotate_browser__opts.hide_src_code) {
- if (bdl->idx_asm < offset)
- offset = bdl->idx;
-
- browser->b.nr_entries = browser->nr_entries;
- annotate_browser__opts.hide_src_code = false;
- browser->b.seek(&browser->b, -offset, SEEK_CUR);
- browser->b.top_idx = bdl->idx - offset;
- browser->b.index = bdl->idx;
- } else {
- if (bdl->idx_asm < 0) {
- ui_helpline__puts("Only available for assembly lines.");
- browser->b.seek(&browser->b, -offset, SEEK_CUR);
- return false;
- }
-
- if (bdl->idx_asm < offset)
- offset = bdl->idx_asm;
-
- browser->b.nr_entries = browser->nr_asm_entries;
- annotate_browser__opts.hide_src_code = true;
- browser->b.seek(&browser->b, -offset, SEEK_CUR);
- browser->b.top_idx = bdl->idx_asm - offset;
- browser->b.index = bdl->idx_asm;
- }
-
- return true;
-}
-
static void annotate_browser__init_asm_mode(struct annotate_browser *browser)
{
ui_browser__reset_index(&browser->b);
@@ -696,6 +713,50 @@ static void annotate_browser__update_addr_width(struct annotate_browser *browser
browser->addr_width += browser->jumps_width + 1;
}
+static int annotate_code_browser__run(struct annotate_browser *browser,
+ char *title, const char *help)
+{
+ int key;
+
+ if (ui_browser__show(&browser->cb, title, help) < 0)
+ return -1;
+
+ while (1) {
+ key = ui_browser__run(&browser->cb, 0);
+
+ switch (key) {
+ case K_F1:
+ case 'h':
+ ui_browser__help_window(&browser->cb,
+ "UP/DOWN/PGUP\n"
+ "PGDN/SPACE Navigate\n"
+ "q/ESC/CTRL+C Return to dissembly view\n\n"
+ "ENTER Show \n"
+ "s Toggle source code view\n"
+ "t Toggle total period view\n"
+ "k Toggle line numbers\n");
+ continue;
+ case 't':
+ annotate_browser__opts.show_total_period =
+ !annotate_browser__opts.show_total_period;
+ continue;
+ case 'k':
+ annotate_browser__opts.show_linenr =
+ !annotate_browser__opts.show_linenr;
+ continue;
+ case 's':
+ case K_LEFT:
+ case K_ESC:
+ case 'q':
+ case CTRL('c'):
+ return 0;
+ default:
+ continue;
+ }
+ }
+ return 0;
+}
+
static int annotate_browser__run(struct annotate_browser *browser,
struct perf_evsel *evsel,
struct hist_browser_timer *hbt)
@@ -775,7 +836,6 @@ static int annotate_browser__run(struct annotate_browser *browser,
"s Toggle source code view\n"
"t Toggle total period view\n"
"/ Search string\n"
- "k Toggle line numbers\n"
"r Run available scripts\n"
"? Search string backwards\n");
continue;
@@ -792,8 +852,10 @@ static int annotate_browser__run(struct annotate_browser *browser,
nd = browser->curr_hot;
break;
case 's':
- if (annotate_browser__toggle_source(browser))
- ui_helpline__puts(help);
+ if (browser->has_src_code)
+ annotate_code_browser__run(browser, title, help);
+ else
+ ui_helpline__puts("No source code for the symbol");
continue;
case 'o':
annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset;
@@ -1095,6 +1157,27 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
browser.b.entries = ¬es->src->source,
browser.b.width += 18; /* Percentage */
+ browser.has_src_code = symbol__has_source_code(sym, map);
+ if (browser.has_src_code &&
+ symbol__get_source_code(sym, map, evsel) != -1) {
+ struct source_code *code = notes->src->code;
+ struct code_line *cl;
+
+ browser.cb.refresh = annotate_code_browser__refresh;
+ browser.cb.seek = ui_browser__list_head_seek;
+ browser.cb.write = annotate_code_browser__write;
+ browser.cb.use_navkeypressed = true;
+ browser.cb.entries = &code->lines;
+
+ list_for_each_entry(cl, &code->lines, node) {
+ size_t line_len = strlen(cl->line);
+
+ if (browser.cb.width < line_len)
+ browser.cb.width = line_len;
+ browser.cb.nr_entries++;
+ }
+ }
+
if (annotate_browser__opts.hide_src_code)
annotate_browser__init_asm_mode(&browser);
@@ -1105,6 +1188,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
list_del(&pos->node);
disasm_line__free(pos);
}
+ symbol__free_source_code(sym);
out_free_offsets:
free(browser.offsets);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 6375012..c4e4c08 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -146,6 +146,7 @@ struct annotated_source {
struct list_head source;
struct source_code *code;
struct source_line *lines;
+ bool has_src_code;
int nr_histograms;
size_t sizeof_sym_hist;
struct cyc_hist *cycles_hist;
--
2.7.4