1 #include "../browser.h"
2 #include "../helpline.h"
3 #include "../libslang.h"
4 #include "../../annotate.h"
5 #include "../../hist.h"
6 #include "../../sort.h"
7 #include "../../symbol.h"
10 static void ui__error_window(const char *fmt
, ...)
15 newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt
, ap
);
19 struct annotate_browser
{
21 struct rb_root entries
;
22 struct rb_node
*curr_hot
;
25 struct objdump_line_rb_node
{
26 struct rb_node rb_node
;
32 struct objdump_line_rb_node
*objdump_line__rb(struct objdump_line
*self
)
34 return (struct objdump_line_rb_node
*)(self
+ 1);
37 static void annotate_browser__write(struct ui_browser
*self
, void *entry
, int row
)
39 struct objdump_line
*ol
= rb_entry(entry
, struct objdump_line
, node
);
40 bool current_entry
= ui_browser__is_current_entry(self
, row
);
41 int width
= self
->width
;
43 if (ol
->offset
!= -1) {
44 struct objdump_line_rb_node
*olrb
= objdump_line__rb(ol
);
45 ui_browser__set_percent_color(self
, olrb
->percent
, current_entry
);
46 slsmg_printf(" %7.2f ", olrb
->percent
);
48 ui_browser__set_percent_color(self
, 0, current_entry
);
49 slsmg_write_nstring(" ", 9);
52 SLsmg_write_char(':');
53 slsmg_write_nstring(" ", 8);
55 slsmg_write_nstring(" ", width
- 18);
57 slsmg_write_nstring(ol
->line
, width
- 18);
60 ui_browser__set_color(self
, HE_COLORSET_CODE
);
63 static double objdump_line__calc_percent(struct objdump_line
*self
,
64 struct symbol
*sym
, int evidx
)
68 if (self
->offset
!= -1) {
69 int len
= sym
->end
- sym
->start
;
70 unsigned int hits
= 0;
71 struct annotation
*notes
= symbol__annotation(sym
);
72 struct source_line
*src_line
= notes
->src
->lines
;
73 struct sym_hist
*h
= annotation__histogram(notes
, evidx
);
74 s64 offset
= self
->offset
;
75 struct objdump_line
*next
;
77 next
= objdump__get_next_ip_line(¬es
->src
->source
, self
);
78 while (offset
< (s64
)len
&&
79 (next
== NULL
|| offset
< next
->offset
)) {
81 percent
+= src_line
[offset
].percent
;
83 hits
+= h
->addr
[offset
];
88 * If the percentage wasn't already calculated in
89 * symbol__get_source_line, do it now:
91 if (src_line
== NULL
&& h
->sum
)
92 percent
= 100.0 * hits
/ h
->sum
;
98 static void objdump__insert_line(struct rb_root
*self
,
99 struct objdump_line_rb_node
*line
)
101 struct rb_node
**p
= &self
->rb_node
;
102 struct rb_node
*parent
= NULL
;
103 struct objdump_line_rb_node
*l
;
107 l
= rb_entry(parent
, struct objdump_line_rb_node
, rb_node
);
108 if (line
->percent
< l
->percent
)
113 rb_link_node(&line
->rb_node
, parent
, p
);
114 rb_insert_color(&line
->rb_node
, self
);
117 static void annotate_browser__set_top(struct annotate_browser
*self
,
120 struct objdump_line_rb_node
*rbpos
;
121 struct objdump_line
*pos
;
124 ui_browser__refresh_dimensions(&self
->b
);
125 back
= self
->b
.height
/ 2;
126 rbpos
= rb_entry(nd
, struct objdump_line_rb_node
, rb_node
);
127 pos
= ((struct objdump_line
*)rbpos
) - 1;
128 self
->b
.top_idx
= self
->b
.index
= rbpos
->idx
;
130 while (self
->b
.top_idx
!= 0 && back
!= 0) {
131 pos
= list_entry(pos
->node
.prev
, struct objdump_line
, node
);
141 static void annotate_browser__calc_percent(struct annotate_browser
*browser
,
144 struct symbol
*sym
= browser
->b
.priv
;
145 struct annotation
*notes
= symbol__annotation(sym
);
146 struct objdump_line
*pos
;
148 browser
->entries
= RB_ROOT
;
150 pthread_mutex_lock(¬es
->lock
);
152 list_for_each_entry(pos
, ¬es
->src
->source
, node
) {
153 struct objdump_line_rb_node
*rbpos
= objdump_line__rb(pos
);
154 rbpos
->percent
= objdump_line__calc_percent(pos
, sym
, evidx
);
155 if (rbpos
->percent
< 0.01) {
156 RB_CLEAR_NODE(&rbpos
->rb_node
);
159 objdump__insert_line(&browser
->entries
, rbpos
);
161 pthread_mutex_unlock(¬es
->lock
);
163 browser
->curr_hot
= rb_last(&browser
->entries
);
166 static int annotate_browser__run(struct annotate_browser
*self
, int evidx
,
169 struct rb_node
*nd
= NULL
;
170 struct symbol
*sym
= self
->b
.priv
;
172 * RIGHT To allow builtin-annotate to cycle thru multiple symbols by
173 * examining the exit key for this function.
175 int exit_keys
[] = { 'H', NEWT_KEY_TAB
, NEWT_KEY_UNTAB
,
179 if (ui_browser__show(&self
->b
, sym
->name
,
180 "<-, -> or ESC: exit, TAB/shift+TAB: "
181 "cycle hottest lines, H: Hottest") < 0)
184 ui_browser__add_exit_keys(&self
->b
, exit_keys
);
185 annotate_browser__calc_percent(self
, evidx
);
188 annotate_browser__set_top(self
, self
->curr_hot
);
193 newtFormSetTimer(self
->b
.form
, refresh
);
196 key
= ui_browser__run(&self
->b
);
199 annotate_browser__calc_percent(self
, evidx
);
201 * Current line focus got out of the list of most active
202 * lines, NULL it so that if TAB|UNTAB is pressed, we
203 * move to curr_hot (current hottest line).
205 if (nd
!= NULL
&& RB_EMPTY_NODE(nd
))
212 * FIXME we need to check if it was
213 * es.reason == NEWT_EXIT_TIMER
216 symbol__annotate_decay_histogram(sym
, evidx
);
222 nd
= rb_last(&self
->entries
);
230 nd
= rb_first(&self
->entries
);
242 annotate_browser__set_top(self
, nd
);
245 ui_browser__hide(&self
->b
);
249 int hist_entry__tui_annotate(struct hist_entry
*he
, int evidx
)
251 return symbol__tui_annotate(he
->ms
.sym
, he
->ms
.map
, evidx
, 0);
254 int symbol__tui_annotate(struct symbol
*sym
, struct map
*map
, int evidx
,
257 struct objdump_line
*pos
, *n
;
258 struct annotation
*notes
;
259 struct annotate_browser browser
= {
261 .refresh
= ui_browser__list_head_refresh
,
262 .seek
= ui_browser__list_head_seek
,
263 .write
= annotate_browser__write
,
272 if (map
->dso
->annotate_warned
)
275 if (symbol__annotate(sym
, map
, sizeof(struct objdump_line_rb_node
)) < 0) {
276 ui__error_window(ui_helpline__last_msg
);
280 ui_helpline__push("Press <- or ESC to exit");
282 notes
= symbol__annotation(sym
);
284 list_for_each_entry(pos
, ¬es
->src
->source
, node
) {
285 struct objdump_line_rb_node
*rbpos
;
286 size_t line_len
= strlen(pos
->line
);
288 if (browser
.b
.width
< line_len
)
289 browser
.b
.width
= line_len
;
290 rbpos
= objdump_line__rb(pos
);
291 rbpos
->idx
= browser
.b
.nr_entries
++;
294 browser
.b
.entries
= ¬es
->src
->source
,
295 browser
.b
.width
+= 18; /* Percentage */
296 ret
= annotate_browser__run(&browser
, evidx
, refresh
);
297 list_for_each_entry_safe(pos
, n
, ¬es
->src
->source
, node
) {
298 list_del(&pos
->node
);
299 objdump_line__free(pos
);