[PATCH/RFC 3/4] perf annotate: Fold or unfold partial disassembly lines on source code view

From: Taeung Song
Date: Tue Jun 27 2017 - 23:14:57 EST


Suggested-by: Namhyung Kim <namhyung@xxxxxxxxxx>
Cc: Milian Wolff <milian.wolff@xxxxxxxx>
Cc: Jiri Olsa <jolsa@xxxxxxxxxx>
Cc: Masami Hiramatsu <mhiramat@xxxxxxxxxx>
Cc: Adrian Hunter <adrian.hunter@xxxxxxxxx>
Cc: Wang Nan <wangnan0@xxxxxxxxxx>
Cc: Jin Yao <yao.jin@xxxxxxxxxxxxxxx>
Cc: Andi Kleen <ak@xxxxxxxxxxxxxxx>
Cc: Kim Phillips <kim.phillips@xxxxxxx>
Cc: David Ahern <dsahern@xxxxxxxxx>
Signed-off-by: Taeung Song <treeze.taeung@xxxxxxxxx>
---
tools/perf/ui/browser.h | 1 +
tools/perf/ui/browsers/annotate.c | 146 ++++++++++++++++++++++++++++++++++++--
tools/perf/util/annotate.h | 1 +
3 files changed, 141 insertions(+), 7 deletions(-)

diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index be3b70e..7637195 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -8,6 +8,7 @@
#define HE_COLORSET_NORMAL 52
#define HE_COLORSET_SELECTED 53
#define HE_COLORSET_JUMP_ARROWS 54
+#define HE_COLORSET_ASM 54
#define HE_COLORSET_ADDR 55
#define HE_COLORSET_ROOT 56

diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 028febe..200ee0c 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -47,11 +47,14 @@ struct annotate_browser {
struct ui_browser b, cb;
struct rb_root entries;
struct rb_node *curr_hot;
+ struct code_line *code_line_selection;
struct disasm_line *selection;
struct disasm_line **offsets;
struct arch *arch;
int nr_events;
u64 start;
+ int code_line_offset;
+ int nr_code_entries;
int nr_asm_entries;
int nr_entries;
int max_jump_sources;
@@ -67,6 +70,8 @@ struct annotate_browser {
char search_bf[128];
};

+static const char *help = "Press 'h' for help on key bindings";
+
static inline struct browser_disasm_line *disasm_line__browser(struct disasm_line *dl)
{
return (struct browser_disasm_line *)(dl + 1);
@@ -111,10 +116,10 @@ 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)
+static void annotate_code_browser__write(struct ui_browser *browser,
+ struct code_line *cl, 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;
@@ -147,11 +152,18 @@ static void annotate_code_browser__write(struct ui_browser *browser, void *entry

SLsmg_write_char(' ');

+ ui_browser__printf(browser, "%c ",
+ cl->nr_matched_dl ? (cl->show_asm ? '-' : '+') : ' ');
printed = scnprintf(line, sizeof(line), "%-*d ",
ab->addr_width + 2, cl->line_nr);

ui_browser__write_nstring(browser, line, printed);
ui_browser__write_nstring(browser, cl->line, browser->width);
+
+ if (current_entry) {
+ ab->code_line_selection = cl;
+ ab->code_line_offset = 0;
+ }
}

static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
@@ -348,15 +360,108 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
from, to);
}

+static int annotate_code_browser__show_matched_dl(struct ui_browser *browser,
+ struct code_line *cl, int row)
+{
+ struct annotate_browser *ab = container_of(browser, struct annotate_browser, cb);
+ int i;
+ char line[256];
+
+ for (i = 0; i < cl->nr_matched_dl; i++) {
+ int k;
+ bool current_entry;
+ struct disasm_line *dl = cl->matched_dl[i];
+ struct browser_disasm_line *bdl = disasm_line__browser(dl);
+
+ ui_browser__gotorc(browser, row, 0);
+ current_entry = ui_browser__is_current_entry(browser, row);
+
+ for (k = 0; k < ab->nr_events; k++) {
+ ui_browser__set_percent_color(browser, bdl->samples[k].percent,
+ current_entry);
+ if (bdl->samples[k].percent == 0.0) {
+ ui_browser__write_nstring(browser, " ", 7);
+ continue;
+ }
+
+ if (annotate_browser__opts.show_total_period) {
+ ui_browser__printf(browser, "%6" PRIu64 " ",
+ bdl->samples[k].nr);
+ } else {
+ ui_browser__printf(browser, "%6.2f ",
+ bdl->samples[k].percent);
+ }
+ }
+
+ SLsmg_write_char(' ');
+
+ if (current_entry) {
+ ab->code_line_selection = cl;
+ ab->code_line_offset = i + 1;
+ ui_browser__set_percent_color(browser, 0, current_entry);
+ } else
+ ui_browser__set_color(browser, HE_COLORSET_NORMAL);
+
+ ui_browser__printf(browser, " %*s - ", ab->addr_width + 4, " ");
+
+ disasm_line__scnprintf(dl, line, sizeof(line),
+ !annotate_browser__opts.use_offset);
+ if (!current_entry)
+ ui_browser__set_color(browser, HE_COLORSET_ASM);
+ ui_browser__write_nstring(browser, line, browser->width);
+
+ if (++row == browser->rows)
+ break;
+ }
+
+ return row;
+}
+
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);
+ struct list_head *pos, *head = browser->entries;
+ struct code_line *cl;
+ int row = 0, pcnt_width = annotate_browser__pcnt_width(ab);
+
+ if (browser->top == NULL)
+ browser->top = head->next;
+
+ /* Reset browser->top_idx considering folded partial disassembly lines */
+ if (browser->top_idx > 0) {
+ struct list_head *top = browser->top;
+ int top_idx = 0;
+
+ pos = head->next;
+ while (pos != top) {
+ top_idx++;
+
+ cl = list_entry(pos, struct code_line, node);
+ if (cl->show_asm)
+ top_idx += cl->nr_matched_dl;
+ pos = pos->next;
+ }
+
+ browser->top_idx = top_idx;
+ }
+
+ pos = browser->top;
+ list_for_each_from(pos, head) {
+ cl = list_entry(pos, struct code_line, node);
+
+ ui_browser__gotorc(browser, row, 0);
+ annotate_code_browser__write(browser, cl, row++);

+ if (cl->show_asm)
+ row = annotate_code_browser__show_matched_dl(browser, cl, row);
+
+ if (row == browser->rows)
+ break;
+ }
ui_browser__set_color(browser, HE_COLORSET_NORMAL);
__ui_browser__vline(browser, pcnt_width, 0, browser->height - 1);
- return ret;
+ ui_helpline__puts(help);
+ return row;
}

static unsigned int annotate_browser__refresh(struct ui_browser *browser)
@@ -796,6 +901,20 @@ static void annotate_browser__update_addr_width(struct annotate_browser *browser
browser->addr_width += browser->jumps_width + 1;
}

+static void annotate_code_browser__update_nr_entries(struct annotate_browser *browser)
+{
+ u32 nr_entries = browser->nr_code_entries;
+ struct ui_browser *cb = &browser->cb;
+ struct list_head *code_lines = cb->entries;
+ struct code_line *cl;
+
+ list_for_each_entry(cl, code_lines, node) {
+ if (cl->show_asm)
+ nr_entries += cl->nr_matched_dl;
+ }
+ ui_browser__update_nr_entries(cb, nr_entries);
+}
+
static int annotate_code_browser__run(struct annotate_browser *browser,
struct perf_evsel *evsel, int delay_secs)
{
@@ -818,8 +937,22 @@ static int annotate_code_browser__run(struct annotate_browser *browser,
"UP/DOWN/PGUP\n"
"PGDN/SPACE Navigate\n"
"q/ESC/CTRL+C Return to dissembly view\n\n"
+ "ENTER Toggle showing partial disassembly lines\n"
"t Toggle total period view\n");
continue;
+ case K_ENTER:
+ if (browser->code_line_selection == NULL ||
+ browser->code_line_selection->nr_matched_dl == 0)
+ ui_helpline__puts("No disassembly for the line");
+ else {
+ if (browser->code_line_selection->show_asm)
+ browser->cb.index -= browser->code_line_offset;
+
+ browser->code_line_selection->show_asm =
+ !browser->code_line_selection->show_asm;
+ annotate_code_browser__update_nr_entries(browser);
+ }
+ continue;
case 't':
annotate_browser__opts.show_total_period =
!annotate_browser__opts.show_total_period;
@@ -843,7 +976,6 @@ static int annotate_browser__run(struct annotate_browser *browser,
struct rb_node *nd = NULL;
struct map_symbol *ms = browser->b.priv;
struct symbol *sym = ms->sym;
- const char *help = "Press 'h' for help on key bindings";
int delay_secs = hbt ? hbt->refresh : 0;
int key;
char title[SYM_TITLE_MAX_SIZE];
@@ -1251,7 +1383,6 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
browser.has_src_code = true;
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;

@@ -1262,6 +1393,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
browser.cb.width = line_len;
browser.cb.nr_entries++;
}
+ browser.nr_code_entries = browser.cb.nr_entries;
}

if (annotate_browser__opts.hide_src_code)
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index fb352cf..97f35ba 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -104,6 +104,7 @@ struct code_line {
struct list_head node;
int line_nr;
char *line;
+ bool show_asm;
int nr_matched_dl;
struct disasm_line **matched_dl;
struct disasm_line_samples *samples_sum;
--
2.7.4