From: Arnaldo Carvalho de Melo Date: Tue, 24 Apr 2012 17:24:28 +0000 (-0300) Subject: perf annotate browser: Initial loop detection X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=a3f895be1f1ed17f66e6e71adeef0cc7f937512c;p=openwrt%2Fstaging%2Fblogic.git perf annotate browser: Initial loop detection Simple algorithm, just look for the next backward jump that points to before the cursor. Then draw an arrow connecting the jump to its target. Do this as you move the cursor, entering/exiting possible loops. Ex (graph chars replaced to avoid mail encoding woes): avc_has_perm_flags 0.00 | nopl 0x0(%rax) 5.36 |+-> 68: mov (%rax),%rax 5.15 || test %rax,%rax 0.00 || v je 130 2.96 || 74: cmp -0x20(%rax),%ebx 47.38 || lea -0x20(%rax),%rcx 0.28 || ^ jne 68 3.16 || cmp -0x18(%rax),%dx 0.00 |+------^ jne 68 4.92 | cmp 0x4(%rcx),%r13d 0.00 | v jne 68 1.15 | test %rcx,%rcx 0.00 | v je 130 Suggested-by: Linus Torvalds Cc: David Ahern Cc: Frederic Weisbecker Cc: Linus Torvalds Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-5gairf6or7dazlx3ocxwvftm@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index 973ff74e3640..32ac1165100d 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -600,6 +600,45 @@ void ui_browser__write_graph(struct ui_browser *browser __used, int graph) SLsmg_set_char_set(0); } +void __ui_browser__line_arrow_up(struct ui_browser *browser, unsigned int column, + u64 start, u64 end, int start_width) +{ + unsigned int row, end_row; + + SLsmg_set_char_set(1); + + if (start < browser->top_idx + browser->height) { + row = start - browser->top_idx; + ui_browser__gotorc(browser, row, column); + SLsmg_write_char(SLSMG_LLCORN_CHAR); + ui_browser__gotorc(browser, row, column + 1); + SLsmg_draw_hline(start_width); + + if (row-- == 0) + goto out; + } else + row = browser->height - 1; + + if (end > browser->top_idx) + end_row = end - browser->top_idx; + else + end_row = 0; + + ui_browser__gotorc(browser, end_row, column); + SLsmg_draw_vline(row - end_row + 1); + + ui_browser__gotorc(browser, end_row, column); + if (end >= browser->top_idx) { + SLsmg_write_char(SLSMG_ULCORN_CHAR); + ui_browser__gotorc(browser, end_row, column + 1); + SLsmg_write_char(SLSMG_HLINE_CHAR); + ui_browser__gotorc(browser, end_row, column + 2); + SLsmg_write_char(SLSMG_RARROW_CHAR); + } +out: + SLsmg_set_char_set(0); +} + void ui_browser__init(void) { int i = 0; diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h index ce20975419d2..2f226cb79f6a 100644 --- a/tools/perf/ui/browser.h +++ b/tools/perf/ui/browser.h @@ -38,6 +38,8 @@ void ui_browser__reset_index(struct ui_browser *self); void ui_browser__gotorc(struct ui_browser *self, int y, int x); void ui_browser__write_graph(struct ui_browser *browser, int graph); +void __ui_browser__line_arrow_up(struct ui_browser *browser, unsigned int column, + u64 start, u64 end, int start_width); void __ui_browser__show_title(struct ui_browser *browser, const char *title); void ui_browser__show_title(struct ui_browser *browser, const char *title); int ui_browser__show(struct ui_browser *self, const char *title, diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index c3fc6f39f901..9e3310cd02cd 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -94,13 +94,13 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro addr += ab->start; if (!ab->use_offset) { - printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ":", addr); + printed = scnprintf(bf, sizeof(bf), " %" PRIx64 ":", addr); } else { if (bdl->jump_target) { - printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ":", + printed = scnprintf(bf, sizeof(bf), " %*" PRIx64 ":", ab->offset_width, addr); } else { - printed = scnprintf(bf, sizeof(bf), "%*s ", + printed = scnprintf(bf, sizeof(bf), " %*s ", ab->offset_width, " "); } } @@ -141,6 +141,59 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro ab->selection = dl; } +static void annotate_browser__draw_current_loop(struct ui_browser *browser) +{ + struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); + struct map_symbol *ms = browser->priv; + struct symbol *sym = ms->sym; + struct annotation *notes = symbol__annotation(sym); + struct disasm_line *cursor = ab->selection, *pos = cursor, *target; + struct browser_disasm_line *bcursor = disasm_line__browser(cursor), + *btarget, *bpos; + unsigned int from, to, start_width = 2; + + list_for_each_entry_from(pos, ¬es->src->source, node) { + if (!pos->ins || !ins__is_jump(pos->ins)) + continue; + + target = ab->offsets[pos->ops.target]; + if (!target) + continue; + + btarget = disasm_line__browser(target); + if (btarget->idx <= bcursor->idx) + goto found; + } + + return; + +found: + bpos = disasm_line__browser(pos); + if (ab->hide_src_code) { + from = bpos->idx_asm; + to = btarget->idx_asm; + } else { + from = (u64)bpos->idx; + to = (u64)btarget->idx; + } + + ui_browser__set_color(browser, HE_COLORSET_CODE); + + if (!bpos->jump_target) + start_width += ab->offset_width + 1; + + __ui_browser__line_arrow_up(browser, 10, from, to, start_width); +} + +static unsigned int annotate_browser__refresh(struct ui_browser *browser) +{ + int ret = ui_browser__list_head_refresh(browser); + + annotate_browser__draw_current_loop(browser); + + return ret; +} + static double disasm_line__calc_percent(struct disasm_line *dl, struct symbol *sym, int evidx) { double percent = 0.0; @@ -666,7 +719,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, }; struct annotate_browser browser = { .b = { - .refresh = ui_browser__list_head_refresh, + .refresh = annotate_browser__refresh, .seek = ui_browser__list_head_seek, .write = annotate_browser__write, .filter = disasm_line__filter,