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"
8 #include "../../annotate.h"
11 static void ui__error_window(const char *fmt
, ...)
16 newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt
, ap
);
20 struct annotate_browser
{
22 struct rb_root entries
;
23 struct rb_node
*curr_hot
;
26 struct objdump_line_rb_node
{
27 struct rb_node rb_node
;
33 struct objdump_line_rb_node
*objdump_line__rb(struct objdump_line
*self
)
35 return (struct objdump_line_rb_node
*)(self
+ 1);
38 static void annotate_browser__write(struct ui_browser
*self
, void *entry
, int row
)
40 struct objdump_line
*ol
= rb_entry(entry
, struct objdump_line
, node
);
41 bool current_entry
= ui_browser__is_current_entry(self
, row
);
42 int width
= self
->width
;
44 if (ol
->offset
!= -1) {
45 struct objdump_line_rb_node
*olrb
= objdump_line__rb(ol
);
46 ui_browser__set_percent_color(self
, olrb
->percent
, current_entry
);
47 slsmg_printf(" %7.2f ", olrb
->percent
);
49 ui_browser__set_percent_color(self
, 0, current_entry
);
50 slsmg_write_nstring(" ", 9);
53 SLsmg_write_char(':');
54 slsmg_write_nstring(" ", 8);
56 slsmg_write_nstring(" ", width
- 18);
58 slsmg_write_nstring(ol
->line
, width
- 18);
61 ui_browser__set_color(self
, HE_COLORSET_CODE
);
64 static double objdump_line__calc_percent(struct objdump_line
*self
,
65 struct symbol
*sym
, int evidx
)
69 if (self
->offset
!= -1) {
70 int len
= sym
->end
- sym
->start
;
71 unsigned int hits
= 0;
72 struct annotation
*notes
= symbol__annotation(sym
);
73 struct source_line
*src_line
= notes
->src
->lines
;
74 struct sym_hist
*h
= annotation__histogram(notes
, evidx
);
75 s64 offset
= self
->offset
;
76 struct objdump_line
*next
;
78 next
= objdump__get_next_ip_line(¬es
->src
->source
, self
);
79 while (offset
< (s64
)len
&&
80 (next
== NULL
|| offset
< next
->offset
)) {
82 percent
+= src_line
[offset
].percent
;
84 hits
+= h
->addr
[offset
];
89 * If the percentage wasn't already calculated in
90 * symbol__get_source_line, do it now:
92 if (src_line
== NULL
&& h
->sum
)
93 percent
= 100.0 * hits
/ h
->sum
;
99 static void objdump__insert_line(struct rb_root
*self
,
100 struct objdump_line_rb_node
*line
)
102 struct rb_node
**p
= &self
->rb_node
;
103 struct rb_node
*parent
= NULL
;
104 struct objdump_line_rb_node
*l
;
108 l
= rb_entry(parent
, struct objdump_line_rb_node
, rb_node
);
109 if (line
->percent
< l
->percent
)
114 rb_link_node(&line
->rb_node
, parent
, p
);
115 rb_insert_color(&line
->rb_node
, self
);
118 static void annotate_browser__set_top(struct annotate_browser
*self
,
121 struct objdump_line_rb_node
*rbpos
;
122 struct objdump_line
*pos
;
125 ui_browser__refresh_dimensions(&self
->b
);
126 back
= self
->b
.height
/ 2;
127 rbpos
= rb_entry(nd
, struct objdump_line_rb_node
, rb_node
);
128 pos
= ((struct objdump_line
*)rbpos
) - 1;
129 self
->b
.top_idx
= self
->b
.index
= rbpos
->idx
;
131 while (self
->b
.top_idx
!= 0 && back
!= 0) {
132 pos
= list_entry(pos
->node
.prev
, struct objdump_line
, node
);
142 static void annotate_browser__calc_percent(struct annotate_browser
*browser
,
145 struct symbol
*sym
= browser
->b
.priv
;
146 struct annotation
*notes
= symbol__annotation(sym
);
147 struct objdump_line
*pos
;
149 browser
->entries
= RB_ROOT
;
151 pthread_mutex_lock(¬es
->lock
);
153 list_for_each_entry(pos
, ¬es
->src
->source
, node
) {
154 struct objdump_line_rb_node
*rbpos
= objdump_line__rb(pos
);
155 rbpos
->percent
= objdump_line__calc_percent(pos
, sym
, evidx
);
156 if (rbpos
->percent
< 0.01) {
157 RB_CLEAR_NODE(&rbpos
->rb_node
);
160 objdump__insert_line(&browser
->entries
, rbpos
);
162 pthread_mutex_unlock(¬es
->lock
);
164 browser
->curr_hot
= rb_last(&browser
->entries
);
167 static int annotate_browser__run(struct annotate_browser
*self
, int evidx
,
170 struct rb_node
*nd
= NULL
;
171 struct symbol
*sym
= self
->b
.priv
;
173 * RIGHT To allow builtin-annotate to cycle thru multiple symbols by
174 * examining the exit key for this function.
176 int exit_keys
[] = { 'H', NEWT_KEY_TAB
, NEWT_KEY_UNTAB
,
180 if (ui_browser__show(&self
->b
, sym
->name
,
181 "<-, -> or ESC: exit, TAB/shift+TAB: "
182 "cycle hottest lines, H: Hottest") < 0)
185 ui_browser__add_exit_keys(&self
->b
, exit_keys
);
186 annotate_browser__calc_percent(self
, evidx
);
189 annotate_browser__set_top(self
, self
->curr_hot
);
194 newtFormSetTimer(self
->b
.form
, refresh
);
197 key
= ui_browser__run(&self
->b
);
200 annotate_browser__calc_percent(self
, evidx
);
202 * Current line focus got out of the list of most active
203 * lines, NULL it so that if TAB|UNTAB is pressed, we
204 * move to curr_hot (current hottest line).
206 if (nd
!= NULL
&& RB_EMPTY_NODE(nd
))
213 * FIXME we need to check if it was
214 * es.reason == NEWT_EXIT_TIMER
217 symbol__annotate_decay_histogram(sym
, evidx
);
223 nd
= rb_last(&self
->entries
);
231 nd
= rb_first(&self
->entries
);
243 annotate_browser__set_top(self
, nd
);
246 ui_browser__hide(&self
->b
);
250 int hist_entry__tui_annotate(struct hist_entry
*he
, int evidx
)
252 return symbol__tui_annotate(he
->ms
.sym
, he
->ms
.map
, evidx
, 0);
255 int symbol__tui_annotate(struct symbol
*sym
, struct map
*map
, int evidx
,
258 struct objdump_line
*pos
, *n
;
259 struct annotation
*notes
;
260 struct annotate_browser browser
= {
262 .refresh
= ui_browser__list_head_refresh
,
263 .seek
= ui_browser__list_head_seek
,
264 .write
= annotate_browser__write
,
273 if (map
->dso
->annotate_warned
)
276 if (symbol__annotate(sym
, map
, sizeof(struct objdump_line_rb_node
)) < 0) {
277 ui__error_window(ui_helpline__last_msg
);
281 ui_helpline__push("Press <- or ESC to exit");
283 notes
= symbol__annotation(sym
);
285 list_for_each_entry(pos
, ¬es
->src
->source
, node
) {
286 struct objdump_line_rb_node
*rbpos
;
287 size_t line_len
= strlen(pos
->line
);
289 if (browser
.b
.width
< line_len
)
290 browser
.b
.width
= line_len
;
291 rbpos
= objdump_line__rb(pos
);
292 rbpos
->idx
= browser
.b
.nr_entries
++;
295 browser
.b
.entries
= ¬es
->src
->source
,
296 browser
.b
.width
+= 18; /* Percentage */
297 ret
= annotate_browser__run(&browser
, evidx
, refresh
);
298 list_for_each_entry_safe(pos
, n
, ¬es
->src
->source
, node
) {
299 list_del(&pos
->node
);
300 objdump_line__free(pos
);