1 #include "../browser.h"
2 #include "../helpline.h"
3 #include "../libslang.h"
4 #include "../../hist.h"
5 #include "../../sort.h"
6 #include "../../symbol.h"
8 static void ui__error_window(const char *fmt
, ...)
13 newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt
, ap
);
17 struct annotate_browser
{
19 struct rb_root entries
;
20 struct rb_node
*curr_hot
;
23 struct objdump_line_rb_node
{
24 struct rb_node rb_node
;
30 struct objdump_line_rb_node
*objdump_line__rb(struct objdump_line
*self
)
32 return (struct objdump_line_rb_node
*)(self
+ 1);
35 static void annotate_browser__write(struct ui_browser
*self
, void *entry
, int row
)
37 struct objdump_line
*ol
= rb_entry(entry
, struct objdump_line
, node
);
38 bool current_entry
= ui_browser__is_current_entry(self
, row
);
39 int width
= self
->width
;
41 if (ol
->offset
!= -1) {
42 struct objdump_line_rb_node
*olrb
= objdump_line__rb(ol
);
43 int color
= ui_browser__percent_color(olrb
->percent
, current_entry
);
44 SLsmg_set_color(color
);
45 slsmg_printf(" %7.2f ", olrb
->percent
);
47 SLsmg_set_color(HE_COLORSET_CODE
);
49 int color
= ui_browser__percent_color(0, current_entry
);
50 SLsmg_set_color(color
);
51 slsmg_write_nstring(" ", 9);
54 SLsmg_write_char(':');
55 slsmg_write_nstring(" ", 8);
57 slsmg_write_nstring(" ", width
- 18);
59 slsmg_write_nstring(ol
->line
, width
- 18);
62 static double objdump_line__calc_percent(struct objdump_line
*self
,
63 struct list_head
*head
,
68 if (self
->offset
!= -1) {
69 int len
= sym
->end
- sym
->start
;
70 unsigned int hits
= 0;
71 struct sym_priv
*priv
= symbol__priv(sym
);
72 struct sym_ext
*sym_ext
= priv
->ext
;
73 struct sym_hist
*h
= priv
->hist
;
74 s64 offset
= self
->offset
;
75 struct objdump_line
*next
= objdump__get_next_ip_line(head
, self
);
78 while (offset
< (s64
)len
&&
79 (next
== NULL
|| offset
< next
->offset
)) {
81 percent
+= sym_ext
[offset
].percent
;
83 hits
+= h
->ip
[offset
];
88 if (sym_ext
== NULL
&& h
->sum
)
89 percent
= 100.0 * hits
/ h
->sum
;
95 static void objdump__insert_line(struct rb_root
*self
,
96 struct objdump_line_rb_node
*line
)
98 struct rb_node
**p
= &self
->rb_node
;
99 struct rb_node
*parent
= NULL
;
100 struct objdump_line_rb_node
*l
;
104 l
= rb_entry(parent
, struct objdump_line_rb_node
, rb_node
);
105 if (line
->percent
< l
->percent
)
110 rb_link_node(&line
->rb_node
, parent
, p
);
111 rb_insert_color(&line
->rb_node
, self
);
114 static void annotate_browser__set_top(struct annotate_browser
*self
,
117 struct objdump_line_rb_node
*rbpos
;
118 struct objdump_line
*pos
;
121 ui_browser__refresh_dimensions(&self
->b
);
122 back
= self
->b
.height
/ 2;
123 rbpos
= rb_entry(nd
, struct objdump_line_rb_node
, rb_node
);
124 pos
= ((struct objdump_line
*)rbpos
) - 1;
125 self
->b
.top_idx
= self
->b
.index
= rbpos
->idx
;
127 while (self
->b
.top_idx
!= 0 && back
!= 0) {
128 pos
= list_entry(pos
->node
.prev
, struct objdump_line
, node
);
138 static int annotate_browser__run(struct annotate_browser
*self
,
139 struct newtExitStruct
*es
)
142 struct hist_entry
*he
= self
->b
.priv
;
144 if (ui_browser__show(&self
->b
, he
->ms
.sym
->name
,
145 "<- or ESC: exit, TAB/shift+TAB: cycle thru samples") < 0)
148 newtFormAddHotKey(self
->b
.form
, NEWT_KEY_LEFT
);
149 newtFormAddHotKey(self
->b
.form
, NEWT_KEY_RIGHT
);
153 newtFormAddHotKey(self
->b
.form
, NEWT_KEY_TAB
);
154 newtFormAddHotKey(self
->b
.form
, NEWT_KEY_UNTAB
);
158 ui_browser__run(&self
->b
, es
);
160 if (es
->reason
!= NEWT_EXIT_HOTKEY
)
167 nd
= rb_last(&self
->entries
);
168 annotate_browser__set_top(self
, nd
);
173 nd
= rb_first(&self
->entries
);
174 annotate_browser__set_top(self
, nd
);
181 ui_browser__hide(&self
->b
);
185 int hist_entry__tui_annotate(struct hist_entry
*self
)
187 struct newtExitStruct es
;
188 struct objdump_line
*pos
, *n
;
189 struct objdump_line_rb_node
*rbpos
;
191 struct annotate_browser browser
= {
194 .refresh
= ui_browser__list_head_refresh
,
195 .seek
= ui_browser__list_head_seek
,
196 .write
= annotate_browser__write
,
202 if (self
->ms
.sym
== NULL
)
205 if (self
->ms
.map
->dso
->annotate_warned
)
208 if (hist_entry__annotate(self
, &head
, sizeof(*rbpos
)) < 0) {
209 ui__error_window(ui_helpline__last_msg
);
213 ui_helpline__push("Press <- or ESC to exit");
215 list_for_each_entry(pos
, &head
, node
) {
216 size_t line_len
= strlen(pos
->line
);
217 if (browser
.b
.width
< line_len
)
218 browser
.b
.width
= line_len
;
219 rbpos
= objdump_line__rb(pos
);
220 rbpos
->idx
= browser
.b
.nr_entries
++;
221 rbpos
->percent
= objdump_line__calc_percent(pos
, &head
, self
->ms
.sym
);
222 if (rbpos
->percent
< 0.01)
224 objdump__insert_line(&browser
.entries
, rbpos
);
228 * Position the browser at the hottest line.
230 browser
.curr_hot
= rb_last(&browser
.entries
);
231 if (browser
.curr_hot
)
232 annotate_browser__set_top(&browser
, browser
.curr_hot
);
234 browser
.b
.width
+= 18; /* Percentage */
235 ret
= annotate_browser__run(&browser
, &es
);
236 list_for_each_entry_safe(pos
, n
, &head
, node
) {
237 list_del(&pos
->node
);
238 objdump_line__free(pos
);