1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2 Contributed by Oracle.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
20
21 #include "config.h"
22 #include "util.h"
23 #include "Application.h"
24 #include "DbeSession.h"
25 #include "CallStack.h"
26 #include "Command.h"
27 #include "DataObject.h"
28 #include "Experiment.h"
29 #include "ExpGroup.h"
30 #include "FilterExp.h"
31 #include "FilterSet.h"
32 #include "Function.h"
33 #include "DbeView.h"
34 #include "PathTree.h"
35 #include "DataSpace.h"
36 #include "MemorySpace.h"
37 #include "IOActivity.h"
38 #include "HeapActivity.h"
39 #include "Print.h"
40 #include "MetricList.h"
41 #include "Module.h"
42 #include "Filter.h"
43 #include "LoadObject.h"
44 #include "dbe_types.h"
45 #include "StringBuilder.h"
46
DbeView(Application * _app,Settings * _settings,int _vindex)47 DbeView::DbeView (Application *_app, Settings *_settings, int _vindex)
48 {
49 init ();
50 phaseIdx = 0;
51 settings = new Settings (_settings);
52 ptree = new PathTree (this);
53 dspace = new DataSpace (this);
54 memspaces = new Vector<MemorySpace*>;
55 iospace = new IOActivity (this);
56 heapspace = new HeapActivity (this);
57 filters = new Vector<FilterSet*>;
58 lo_expands = new Vector<enum LibExpand>;
59 cur_filter_str = NULL;
60 prev_filter_str = NULL;
61 cur_filter_expr = NULL;
62 filter_active = false;
63 noParFilter = false;
64 dataViews = new Vector<Vector<DataView*>*>;
65 names_src[0] = NULL;
66 names_src[1] = NULL;
67 names_src[2] = NULL;
68 names_dis[0] = NULL;
69 names_dis[1] = NULL;
70 names_dis[2] = NULL;
71 marks = new Vector<int>;
72 marks2dsrc = new Vector<int_pair_t>;
73 marks2dsrc_inc = new Vector<int_pair_t>;
74 marks2ddis = new Vector<int_pair_t>;
75 marks2ddis_inc = new Vector<int_pair_t>;
76 app = _app;
77
78 // set the view's index
79 vindex = _vindex;
80
81 // clear the precomputed data
82 func_data = NULL;
83 line_data = NULL;
84 pc_data = NULL;
85 src_data = NULL;
86 dis_data = NULL;
87 fitem_data = NULL;
88 callers = NULL;
89 callees = NULL;
90 dobj_data = NULL;
91 dlay_data = NULL;
92 iofile_data = NULL;
93 iovfd_data = NULL;
94 iocs_data = NULL;
95 heapcs_data = NULL;
96
97 // and clear the selections
98 sel_obj = NULL;
99 sel_dobj = NULL;
100 sel_binctx = NULL;
101 func_scope = false;
102 lastSelInstr = NULL;
103 lastSelFunc = NULL;
104
105 // Initialize index spaces
106 int sz = settings->get_IndxTabState ()->size ();
107 indxspaces = new Vector<PathTree*>(sz);
108 indx_data = new Vector<Hist_data*>(sz);
109 sel_idxobj = new Vector<Histable*>(sz);
110 for (int i = 0; i < sz; i++)
111 {
112 PathTree *is = new PathTree (this, i);
113 indxspaces->store (i, is);
114 indx_data->store (i, NULL);
115 sel_idxobj->store (i, NULL);
116 }
117 reset ();
118
119 lobjectsNoJava = NULL;
120
121 // set lo_expands for already existing LoadObjects
122 int idx;
123 LoadObject *lo;
124 Vector<LoadObject*> *lobjs = dbeSession->get_text_segments ();
125 Vec_loop (LoadObject*, lobjs, idx, lo)
126 {
127 lo_expands->store (lo->seg_idx, LIBEX_SHOW);
128 set_lo_expand (lo->seg_idx, LIBEX_SHOW);
129 }
130 delete lobjs;
131 }
132
DbeView(DbeView * dbev,int _vindex)133 DbeView::DbeView (DbeView *dbev, int _vindex)
134 {
135 init ();
136 phaseIdx = 0;
137 settings = new Settings (dbev->settings);
138 ptree = new PathTree (this);
139 dspace = new DataSpace (this);
140 iospace = new IOActivity (this);
141 heapspace = new HeapActivity (this);
142 memspaces = new Vector<MemorySpace*>;
143 filters = new Vector<FilterSet*>;
144 lo_expands = new Vector<enum LibExpand>;
145 cur_filter_str = NULL;
146 prev_filter_str = NULL;
147 cur_filter_expr = NULL;
148 noParFilter = false;
149 dataViews = new Vector<Vector<DataView*>*>;
150 names_src[0] = NULL;
151 names_src[1] = NULL;
152 names_src[2] = NULL;
153 names_dis[0] = NULL;
154 names_dis[1] = NULL;
155 names_dis[2] = NULL;
156 marks = new Vector<int>;
157 marks2dsrc = new Vector<int_pair_t>;
158 marks2dsrc_inc = new Vector<int_pair_t>;
159 marks2ddis = new Vector<int_pair_t>;
160 marks2ddis_inc = new Vector<int_pair_t>;
161 app = dbev->app;
162
163 // set the view's index
164 vindex = _vindex;
165
166 // clear the precomputed data
167 func_data = NULL;
168 line_data = NULL;
169 pc_data = NULL;
170 src_data = NULL;
171 dis_data = NULL;
172 fitem_data = NULL;
173 callers = NULL;
174 callees = NULL;
175 dobj_data = NULL;
176 dlay_data = NULL;
177 iofile_data = NULL;
178 iovfd_data = NULL;
179 iocs_data = NULL;
180 heapcs_data = NULL;
181
182 // and clear the selections
183 sel_obj = NULL;
184 sel_dobj = NULL;
185 sel_binctx = NULL;
186 func_scope = false;
187 lastSelInstr = NULL;
188 lastSelFunc = NULL;
189
190 // create the vector of IndexSpaces
191 int sz = dbev->indxspaces->size ();
192 indxspaces = new Vector<PathTree*>(sz);
193 indx_data = new Vector<Hist_data*>(sz);
194 sel_idxobj = new Vector<Histable*>(sz);
195 for (int i = 0; i < sz; i++)
196 {
197 PathTree *is = new PathTree (this, i);
198 indxspaces->store (i, is);
199 indx_data->store (i, NULL);
200 sel_idxobj->store (i, NULL);
201 }
202 reset ();
203
204 // now copy the relevant information from the original view
205 for (int i = 0; i < dbeSession->nexps (); i++)
206 add_experiment (i, dbev->get_exp_enable (i));
207 update_advanced_filter ();
208 delete lo_expands;
209 lo_expands = dbev->lo_expands->copy ();
210 lobjectsNoJava = NULL;
211 }
212
~DbeView()213 DbeView::~DbeView ()
214 {
215 delete settings;
216 delete ptree;
217 delete dspace;
218 delete iospace;
219 delete heapspace;
220 Destroy (memspaces);
221 Destroy (filters);
222 delete lo_expands;
223 free (cur_filter_str);
224 free (prev_filter_str);
225 delete cur_filter_expr;
226 for (int exp_id = 0; exp_id < dataViews->size (); ++exp_id)
227 {
228 Vector<DataView*> *expDataViewList = dataViews->fetch (exp_id);
229 Destroy (expDataViewList);
230 }
231 delete dataViews;
232 delete reg_metrics;
233 metrics_lists->destroy ();
234 delete metrics_lists;
235 metrics_ref_lists->destroy ();
236 delete metrics_ref_lists;
237 delete derived_metrics;
238 delete marks;
239 delete marks2dsrc;
240 delete marks2dsrc_inc;
241 delete marks2ddis;
242 delete marks2ddis_inc;
243
244 // Index spaces
245 indxspaces->destroy ();
246 delete indxspaces;
247
248 indx_data->destroy ();
249 delete indx_data;
250 delete sel_idxobj;
251 delete lobjectsNoJava;
252 }
253
254 void
init()255 DbeView::init ()
256 {
257 phaseIdx = 0;
258 reg_metrics = new Vector<BaseMetric*>;
259 metrics_lists = new Vector<MetricList*>;
260 metrics_ref_lists = new Vector<MetricList*>;
261 for (int i = 0; i <= MET_HEAP; i++)
262 {
263 metrics_lists->append (NULL);
264 metrics_ref_lists->append (NULL);
265 }
266 derived_metrics = new DerivedMetrics;
267 derived_metrics->add_definition (GTXT ("CPI"), GTXT ("Cycles Per Instruction"), GTXT ("cycles/insts"));
268 derived_metrics->add_definition (GTXT ("IPC"), GTXT ("Instructions Per Cycle"), GTXT ("insts/cycles"));
269 derived_metrics->add_definition (GTXT ("K_CPI"), GTXT ("Kernel Cycles Per Instruction"), GTXT ("K_cycles/K_insts"));
270 derived_metrics->add_definition (GTXT ("K_IPC"), GTXT ("Kernel Instructions Per Cycle"), GTXT ("K_insts/K_cycles"));
271 }
272
273 bool
set_libexpand(char * liblist,enum LibExpand flag)274 DbeView::set_libexpand (char *liblist, enum LibExpand flag)
275 {
276 bool changed = settings->set_libexpand (liblist, flag, false);
277 // Show/hide performance optimization:
278 // No need to call update_lo_expand for every library because dbev->set_libexpand()
279 // is called from a loop in Dbe.cc SetLoadObjectState for every load object.
280 // It is sufficient to call update_lo_expand() just once at the end of the loop.
281 // At all other places such as er_print.cc which calls specific set_libexpand()
282 // explicitly call update_lo_expands();
283 return changed;
284 }
285
286 bool
set_libdefaults()287 DbeView::set_libdefaults ()
288 {
289 bool changed = settings->set_libdefaults ();
290 if (changed == true)
291 update_lo_expands ();
292 return changed;
293 }
294
295 void
update_lo_expands()296 DbeView::update_lo_expands ()
297 {
298 int index;
299 LoadObject *lo;
300
301 // search all load objects
302 Vector<LoadObject*> *lobjs = dbeSession->get_text_segments ();
303 Vec_loop (LoadObject*, lobjs, index, lo)
304 {
305 // now search the settings list for this one
306 enum LibExpand flag = settings->get_lo_setting (lo->get_pathname ());
307 set_lo_expand (lo->seg_idx, flag);
308 }
309 delete lobjs;
310 }
311
312 enum LibExpand
get_lo_expand(int idx)313 DbeView::get_lo_expand (int idx)
314 {
315 if (idx < lo_expands->size ())
316 return lo_expands->get (idx);
317 return LIBEX_SHOW;
318 }
319
320 bool
set_lo_expand(int idx,enum LibExpand flag)321 DbeView::set_lo_expand (int idx, enum LibExpand flag)
322 {
323 // LIBRARY_VISIBILITY
324 if (flag == LIBEX_HIDE)
325 {
326 resetShowAll ();
327 dbeSession->set_lib_visibility_used ();
328 }
329 // if no change
330 if (idx < lo_expands->size () && flag == get_lo_expand (idx))
331 return false;
332 setShowHideChanged (); // this is necessary if called from er_print
333
334 // change the flag
335 lo_expands->store (idx, flag);
336
337 // and reset the data
338 fflush (stderr);
339 purge_events ();
340 reset_data (true);
341 return true;
342 }
343
344 void
reset()345 DbeView::reset ()
346 {
347 phaseIdx++;
348
349 // reset all the per-experiment arrays
350 filters->destroy ();
351 lo_expands->reset ();
352 free (cur_filter_str);
353 cur_filter_str = NULL;
354 free (prev_filter_str);
355 prev_filter_str = NULL;
356 delete cur_filter_expr;
357 cur_filter_expr = NULL;
358 noParFilter = false;
359 for (int exp_id = 0; exp_id < dataViews->size (); ++exp_id)
360 {
361 Vector<DataView*> *expDataViewList = dataViews->fetch (exp_id);
362 if (expDataViewList)
363 expDataViewList->destroy ();
364 }
365 dataViews->destroy ();
366 reset_metrics ();
367
368 // now reset any cached data
369 reset_data (true);
370 ompDisMode = false;
371 showAll = true;
372 showHideChanged = false;
373 newViewMode = false;
374 }
375
376 void
reset_data(bool all)377 DbeView::reset_data (bool all)
378 {
379 // clear the precomputed data
380 if (func_data != NULL)
381 {
382 delete func_data;
383 func_data = NULL;
384 }
385 if (line_data != NULL)
386 {
387 delete line_data;
388 line_data = NULL;
389 }
390 if (pc_data != NULL)
391 {
392 delete pc_data;
393 pc_data = NULL;
394 }
395 if (src_data != NULL)
396 {
397 delete src_data;
398 src_data = NULL;
399 }
400 if (dis_data != NULL)
401 {
402 delete dis_data;
403 dis_data = NULL;
404 }
405 if (fitem_data != NULL)
406 {
407 delete fitem_data;
408 fitem_data = NULL;
409 }
410 if (callers != NULL)
411 {
412 delete callers;
413 callers = NULL;
414 }
415 if (callees != NULL)
416 {
417 delete callees;
418 callees = NULL;
419 }
420 if (dobj_data != NULL)
421 {
422 delete dobj_data;
423 dobj_data = NULL;
424 }
425 if (dlay_data != NULL)
426 {
427 delete dlay_data;
428 dlay_data = NULL;
429 }
430 if (iofile_data != NULL)
431 {
432 delete iofile_data;
433 iofile_data = NULL;
434 }
435 if (iovfd_data != NULL)
436 {
437 delete iovfd_data;
438 iovfd_data = NULL;
439 }
440 if (iocs_data != NULL)
441 {
442 delete iocs_data;
443 iocs_data = NULL;
444 }
445 if (heapcs_data != NULL)
446 {
447 delete heapcs_data;
448 heapcs_data = NULL;
449 }
450
451 // and reset the selections
452 if (all)
453 {
454 sel_obj = NULL;
455 sel_dobj = NULL;
456 lastSelInstr = NULL;
457 lastSelFunc = NULL;
458 // Set selected object <Total> if possible
459 Function * ft = dbeSession->get_Total_Function ();
460 set_sel_obj (ft);
461 }
462 sel_binctx = NULL;
463
464 dspace->reset ();
465 iospace->reset ();
466 heapspace->reset ();
467
468 // loop over MemorySpaces, resetting each one
469 for (long i = 0, sz = VecSize (memspaces); i < sz; i++)
470 {
471 MemorySpace *ms = memspaces->get (i);
472 ms->reset ();
473 }
474
475 // loop over IndexSpaces, resetting cached data
476 indx_data->destroy ();
477 for (long i = 0, sz = VecSize (indxspaces); i < sz; i++)
478 {
479 indx_data->store (i, NULL);
480 sel_idxobj->store (i, NULL);
481 }
482 }
483
484 Vector<BaseMetric*> *
get_all_reg_metrics()485 DbeView::get_all_reg_metrics ()
486 {
487 Vector<BaseMetric*> *mlist = dbeSession->get_all_reg_metrics ();
488 return mlist;
489 }
490
491 BaseMetric *
register_metric_expr(BaseMetric::Type type,char * cmd,char * expr_spec)492 DbeView::register_metric_expr (BaseMetric::Type type, char *cmd, char *expr_spec)
493 {
494 BaseMetric *bm = dbeSession->register_metric_expr (type, cmd, expr_spec);
495 return bm;
496 }
497
498 Metric *
get_compare_metric(Metric * mtr,int groupNum)499 DbeView::get_compare_metric (Metric *mtr, int groupNum)
500 {
501 if (groupNum == 0 || !mtr->comparable ())
502 return new Metric (*mtr);
503 ExpGroup *gr = dbeSession->expGroups->get (groupNum - 1);
504 char buf[128];
505 snprintf (buf, sizeof (buf), NTXT ("EXPGRID==%d"), gr->groupId);
506 BaseMetric *bm = register_metric_expr (mtr->get_type (), mtr->get_cmd (), buf);
507 Metric *m = new Metric (bm, mtr->get_subtype ());
508 m->set_raw_visbits (mtr->get_visbits ());
509 if (m->legend == NULL)
510 m->legend = dbe_strdup (get_basename (gr->name));
511 return m;
512 }
513
514 MetricList *
get_metric_ref(MetricType mtype)515 DbeView::get_metric_ref (MetricType mtype)
516 {
517 if (metrics_ref_lists->fetch (MET_COMMON) == NULL)
518 {
519 Vector<BaseMetric*> *base_metrics = dbeSession->get_base_reg_metrics ();
520 metrics_ref_lists->store (MET_SRCDIS, new MetricList (base_metrics, MET_SRCDIS));
521 metrics_ref_lists->store (MET_COMMON, new MetricList (base_metrics, MET_COMMON));
522 metrics_ref_lists->store (MET_NORMAL, new MetricList (base_metrics, MET_NORMAL));
523 metrics_ref_lists->store (MET_CALL, new MetricList (base_metrics, MET_CALL));
524 metrics_ref_lists->store (MET_CALL_AGR, new MetricList (base_metrics, MET_CALL_AGR));
525 metrics_ref_lists->store (MET_DATA, new MetricList (base_metrics, MET_DATA));
526 metrics_ref_lists->store (MET_INDX, new MetricList (base_metrics, MET_INDX));
527 metrics_ref_lists->store (MET_IO, new MetricList (base_metrics, MET_IO));
528 metrics_ref_lists->store (MET_HEAP, new MetricList (base_metrics, MET_HEAP));
529 delete base_metrics;
530 }
531 return metrics_ref_lists->fetch (mtype);
532 }
533
534 // logically, the function list must be created first, and it
535 // will create the other two;
536 MetricList *
get_metric_list(MetricType mtype)537 DbeView::get_metric_list (MetricType mtype)
538 {
539 if (metrics_lists->fetch (MET_COMMON) == NULL)
540 {
541 Vector<BaseMetric*> *base_metrics = dbeSession->get_base_reg_metrics ();
542 metrics_lists->store (MET_SRCDIS, new MetricList (base_metrics, MET_SRCDIS));
543 metrics_lists->store (MET_COMMON, new MetricList (base_metrics, MET_COMMON));
544 metrics_lists->store (MET_NORMAL, new MetricList (base_metrics, MET_NORMAL));
545 metrics_lists->store (MET_CALL, new MetricList (base_metrics, MET_CALL));
546 metrics_lists->store (MET_CALL_AGR, new MetricList (base_metrics, MET_CALL_AGR));
547 metrics_lists->store (MET_DATA, new MetricList (base_metrics, MET_DATA));
548 metrics_lists->store (MET_INDX, new MetricList (base_metrics, MET_INDX));
549 metrics_lists->store (MET_IO, new MetricList (base_metrics, MET_IO));
550 metrics_lists->store (MET_HEAP, new MetricList (base_metrics, MET_HEAP));
551 delete base_metrics;
552
553 // set the defaults
554 if (settings->str_dmetrics == NULL)
555 settings->str_dmetrics = strdup (Command::DEFAULT_METRICS);
556 char *status = setMetrics (settings->str_dmetrics, true);
557 if (status != NULL)
558 {
559 fprintf (stderr, "XXX setMetrics(\"%s\") failed: %s\n", settings->str_dmetrics, status);
560 abort ();
561 }
562
563 // set the default sort
564 setSort (settings->str_dsort, MET_NORMAL, true);
565 }
566 return metrics_lists->fetch (mtype);
567 }
568
569 MetricList *
get_metric_list(int dsptype,int subtype)570 DbeView::get_metric_list (int dsptype, int subtype)
571 {
572 MetricList *mlist;
573 switch (dsptype)
574 {
575 case DSP_DISASM:
576 case DSP_SOURCE:
577 case DSP_SOURCE_DISASM:
578 mlist = get_metric_list (MET_COMMON);
579 mlist = new MetricList (mlist);
580 if (subtype != 0)
581 {
582 for (long i = 0, sz = mlist->size (); i < sz; i++)
583 {
584 Metric *m = mlist->get (i);
585 if (m->comparable ())
586 {
587 Metric *m1 = get_compare_metric (m, subtype);
588 mlist->put (i, m1);
589 delete m;
590 }
591 }
592 }
593 break;
594 default:
595 mlist = get_metric_list (MET_NORMAL);
596 mlist = new MetricList (mlist);
597 break;
598 }
599 return mlist;
600 }
601
602 void
reset_metrics()603 DbeView::reset_metrics ()
604 {
605 for (int i = 0, sz = metrics_lists->size (); i < sz; i++)
606 {
607 delete metrics_lists->fetch (i);
608 metrics_lists->store (i, NULL);
609 }
610 for (int i = 0, sz = metrics_ref_lists->size (); i < sz; i++)
611 {
612 delete metrics_ref_lists->fetch (i);
613 metrics_ref_lists->store (i, NULL);
614 }
615 }
616
617 bool
comparingExperiments()618 DbeView::comparingExperiments ()
619 {
620 if (dbeSession->expGroups->size () <= 1)
621 return false;
622 return 0 != (settings->get_compare_mode () & (CMP_DELTA | CMP_ENABLE | CMP_RATIO));
623 }
624
625 void
set_compare_mode(int mode)626 DbeView::set_compare_mode (int mode)
627 {
628 if (mode == get_compare_mode ())
629 return;
630 settings->set_compare_mode (mode);
631 if (comparingExperiments ())
632 {
633 Vector<BaseMetric*> *bm_list = dbeSession->get_base_reg_metrics ();
634 for (int i = 0, sz = bm_list->size (); i < sz; i++)
635 {
636 BaseMetric *m = bm_list->fetch (i);
637 if (m->get_expr_spec () || !m->comparable ())
638 continue;
639 for (int i1 = 0, sz1 = dbeSession->expGroups->size (); i1 < sz1; i1++)
640 {
641 ExpGroup *gr = dbeSession->expGroups->fetch (i1);
642 char buf[128];
643 snprintf (buf, sizeof (buf), NTXT ("EXPGRID==%d"), gr->groupId);
644 register_metric_expr (m->get_type (), m->get_cmd (), buf);
645 }
646 }
647 }
648 MetricList *mlist = get_metric_list (MET_NORMAL);
649 MetricList *gmlist = get_metric_list (MET_CALL);
650 MetricList *dmlist = get_metric_list (MET_DATA);
651 MetricList *imlist = get_metric_list (MET_INDX);
652 if (comparingExperiments ())
653 {
654 add_compare_metrics (mlist);
655 add_compare_metrics (gmlist);
656 add_compare_metrics (dmlist);
657 add_compare_metrics (imlist);
658 }
659 else
660 {
661 remove_compare_metrics (mlist);
662 remove_compare_metrics (gmlist);
663 remove_compare_metrics (dmlist);
664 remove_compare_metrics (imlist);
665 }
666 }
667
668 void
ifreq(FILE * outfile)669 DbeView::ifreq (FILE *outfile)
670 {
671 if (!dbeSession->is_ifreq_available ())
672 {
673 fprintf (outfile, GTXT ("No instruction frequency data available\n"));
674 return;
675 }
676 for (int index = 0; index < filters->size (); index++)
677 {
678 Experiment *exp = dbeSession->get_exp (index);
679 if (exp->broken || !get_exp_enable (index) || !exp->ifreqavail)
680 continue;
681
682 // this experiment has the data; print it
683 fprintf (outfile,
684 GTXT ("Instruction frequency data from experiment %s\n\n"),
685 exp->get_expt_name ());
686 fprintf (outfile, NTXT ("%s"), pr_mesgs (exp->fetch_ifreq (), "", ""));
687 }
688 }
689
690 // When adding multiple sub-experiments of an experiment, it is
691 // not necessary to do the following every-time. It is sufficient to call reset_metrics()
692 // and call get_metric_ref() and get_metric_list() in the end after all the sub-experiments
693 // have been added
694 void
add_experiment_epilogue()695 DbeView::add_experiment_epilogue ()
696 {
697 bool flag_LIBEX_HIDE = false;
698 bool flag_ShowHideChanged = false;
699 Vector<LoadObject*> *lobjs = dbeSession->get_LoadObjects ();
700 for (long i = lo_expands->size (), sz = lobjs ? lobjs->size () : 0; i < sz; i++)
701 {
702 flag_ShowHideChanged = true;
703 LoadObject *lo = lobjs->get (i);
704 enum LibExpand flag = settings->get_lo_setting (lo->get_pathname ());
705 if (flag == LIBEX_HIDE)
706 flag_LIBEX_HIDE = true;
707 lo_expands->store (lo->seg_idx, flag);
708 }
709 if (flag_LIBEX_HIDE)
710 {
711 resetShowAll ();
712 dbeSession->set_lib_visibility_used ();
713 }
714 if (flag_ShowHideChanged)
715 {
716 setShowHideChanged (); // this is necessary if called from er_print
717 purge_events ();
718 reset_data (true);
719 }
720 reset_metrics ();
721 (void) get_metric_ref (MET_NORMAL);
722 (void) get_metric_ref (MET_CALL);
723 (void) get_metric_ref (MET_CALL_AGR);
724 (void) get_metric_ref (MET_DATA);
725 (void) get_metric_ref (MET_INDX);
726 (void) get_metric_ref (MET_IO);
727 (void) get_metric_ref (MET_HEAP);
728 (void) get_metric_list (MET_NORMAL);
729 (void) get_metric_list (MET_CALL);
730 (void) get_metric_list (MET_CALL_AGR);
731 (void) get_metric_list (MET_DATA);
732 (void) get_metric_list (MET_INDX);
733 (void) get_metric_list (MET_IO);
734 (void) get_metric_list (MET_HEAP);
735 }
736
737 // When adding multiple sub-experiments of an experiment, avoid invoking the steps in
738 // add_experiment_epilogue() every time and instead call it separately in the end
739 // after all sub-experiments have been added
740 void
add_subexperiment(int index,bool enabled)741 DbeView::add_subexperiment (int index, bool enabled)
742 {
743 // phaseIdx doesn't change, PathTree can handle adding
744 // new experiments without reset
745
746 // Set up the FilterSet for the experiments
747 Experiment *exp = dbeSession->get_exp (index);
748 FilterSet *filterset = new FilterSet (this, exp);
749 filterset->set_enabled (enabled);
750 filters->store (index, filterset);
751
752 assert (index == dataViews->size ());
753 Vector<DataView*> *expDataViewList = new Vector<DataView*>;
754 for (int data_id = 0; data_id < DATA_LAST; ++data_id)
755 expDataViewList->append (NULL); //experiment data_id's are not known yet
756 dataViews->store (index, expDataViewList);
757 }
758
759 void
add_experiment(int index,bool enabled)760 DbeView::add_experiment (int index, bool enabled)
761 {
762 // phaseIdx doesn't change, PathTree can handle adding
763 // new experiments without reset
764
765 // delete any cached data
766 reset_data (true);
767
768 // Set up the FilterSet for the experiments
769 Experiment *exp = dbeSession->get_exp (index);
770 FilterSet *filterset = new FilterSet (this, exp);
771 filterset->set_enabled (enabled);
772 filters->store (index, filterset);
773
774 assert (index == dataViews->size ());
775 Vector<DataView*> *expDataViewList = new Vector<DataView*>;
776 for (int data_id = 0; data_id < DATA_LAST; ++data_id)
777 expDataViewList->append (NULL); //experiment data_id's are not known yet
778 dataViews->store (index, expDataViewList);
779
780 reset_metrics ();
781 (void) get_metric_ref (MET_NORMAL);
782 (void) get_metric_ref (MET_CALL);
783 (void) get_metric_ref (MET_CALL_AGR);
784 (void) get_metric_ref (MET_DATA);
785 (void) get_metric_ref (MET_INDX);
786 (void) get_metric_ref (MET_IO);
787 (void) get_metric_ref (MET_HEAP);
788 (void) get_metric_list (MET_NORMAL);
789 (void) get_metric_list (MET_CALL);
790 (void) get_metric_list (MET_CALL_AGR);
791 (void) get_metric_list (MET_DATA);
792 (void) get_metric_list (MET_INDX);
793 (void) get_metric_list (MET_IO);
794 (void) get_metric_list (MET_HEAP);
795 }
796
797 void
drop_experiment(int index)798 DbeView::drop_experiment (int index)
799 {
800 phaseIdx++;
801 filters->remove (index);
802
803 // reset any cached data
804 reset_data (true);
805
806 Vector<DataView*> *expDataViewList = dataViews->remove (index);
807 if (expDataViewList)
808 {
809 expDataViewList->destroy ();
810 delete expDataViewList;
811 }
812 }
813
814 bool
get_exp_enable(int n)815 DbeView::get_exp_enable (int n)
816 {
817 return filters ? filters->fetch (n)->get_enabled () : true;
818 }
819
820 void
set_exp_enable(int n,bool e)821 DbeView::set_exp_enable (int n, bool e)
822 {
823 FilterSet *fs = filters->fetch (n);
824 if (fs->get_enabled () != e)
825 {
826 fs->set_enabled (e);
827 purge_events (n);
828 phaseIdx++;
829 }
830 }
831
832 void
reset_metric_list(MetricList * mlist,int cmp_mode)833 DbeView::reset_metric_list (MetricList *mlist, int cmp_mode)
834 {
835 MetricType mtype = mlist->get_type ();
836 switch (mtype)
837 {
838 case MET_NORMAL:
839 case MET_COMMON:
840 delete metrics_lists->fetch (MET_COMMON);
841 metrics_lists->store (MET_COMMON, new MetricList (mlist));
842 remove_compare_metrics (metrics_lists->fetch (MET_COMMON));
843 break;
844 // ignoring the following cases (why?)
845 case MET_SRCDIS:
846 case MET_CALL:
847 case MET_DATA:
848 case MET_INDX:
849 case MET_CALL_AGR:
850 case MET_IO:
851 case MET_HEAP:
852 break;
853 }
854
855 if (cmp_mode != -1)
856 {
857 settings->set_compare_mode (cmp_mode);
858 if (comparingExperiments ())
859 add_compare_metrics (mlist);
860 }
861
862 switch (mtype)
863 {
864 case MET_NORMAL:
865 delete metrics_lists->fetch (mtype);
866 metrics_lists->store (mtype, mlist);
867 // fall through to next case
868 case MET_COMMON:
869 metrics_lists->fetch (MET_SRCDIS)->set_metrics (mlist);
870 metrics_lists->fetch (MET_CALL)->set_metrics (mlist);
871 metrics_lists->fetch (MET_CALL_AGR)->set_metrics (mlist);
872 remove_compare_metrics (metrics_lists->fetch (MET_CALL_AGR));
873 metrics_lists->fetch (MET_DATA)->set_metrics (mlist);
874 metrics_lists->fetch (MET_INDX)->set_metrics (mlist);
875 metrics_lists->fetch (MET_IO)->set_metrics (mlist);
876 metrics_lists->fetch (MET_HEAP)->set_metrics (mlist);
877 break;
878 case MET_CALL_AGR:
879 delete metrics_lists->fetch (MET_CALL_AGR);
880 metrics_lists->store (MET_CALL_AGR, mlist);
881 remove_compare_metrics (mlist);
882 break;
883 case MET_SRCDIS:
884 case MET_CALL:
885 case MET_DATA:
886 case MET_INDX:
887 case MET_IO:
888 case MET_HEAP:
889 delete metrics_lists->fetch (mtype);
890 metrics_lists->store (mtype, mlist);
891 break;
892 default:
893 abort ();
894 }
895 reset_data (false);
896 }
897
898 void
add_compare_metrics(MetricList * mlist)899 DbeView::add_compare_metrics (MetricList *mlist)
900 {
901 if (mlist == NULL || !comparingExperiments ())
902 return;
903 int sort_ref_index = mlist->get_sort_ref_index ();
904 Vector<Metric*> *items = mlist->get_items ();
905 Vector<Metric*> *newItems = new Vector<Metric*>();
906 int mode = get_compare_mode ();
907 int cmp_vbits = 0;
908 if ((mode & CMP_DELTA) != 0)
909 cmp_vbits = VAL_DELTA;
910 else if ((mode & CMP_RATIO) != 0)
911 cmp_vbits = VAL_RATIO;
912 for (long i = 0, sz = items->size (); i < sz; i++)
913 {
914 Metric *mtr = items->get (i);
915 if (sort_ref_index == i)
916 mlist->set_sort_ref_index (newItems->size ());
917 int vbits = mtr->get_visbits () & ~(VAL_DELTA | VAL_RATIO);
918 mtr->set_raw_visbits (vbits);
919 if (!mtr->comparable ())
920 {
921 newItems->append (mtr);
922 continue;
923 }
924 if (mtr->get_expr_spec ())
925 {
926 if (strcmp (mtr->get_expr_spec (), NTXT ("EXPGRID==1")) != 0)
927 {
928 if ((cmp_vbits & VAL_RATIO) != 0)
929 // for ratios, make sure VAL_TIMEVAL is off and VAL_VALUE is on
930 mtr->set_raw_visbits ((vbits | VAL_VALUE | cmp_vbits) & ~VAL_TIMEVAL);
931 else
932 {
933 int ind = mlist->get_listorder (mtr->get_cmd (), mtr->get_subtype (), NTXT ("EXPGRID==1"));
934 if (ind >= 0)
935 // take VAL_VALUE and VAL_TIMEVAL from base experiment
936 mtr->set_raw_visbits (cmp_vbits
937 | (vbits & ~(VAL_VALUE | VAL_TIMEVAL))
938 | (mlist->get (ind)->get_visbits ()
939 & (VAL_VALUE | VAL_TIMEVAL)));
940 else
941 mtr->set_raw_visbits (cmp_vbits | vbits);
942 }
943 }
944 newItems->append (mtr);
945 continue;
946 }
947 for (long i1 = 0, sz1 = dbeSession->expGroups->size (); i1 < sz1; i1++)
948 {
949 Metric *m = get_compare_metric (mtr, i1 + 1);
950 switch (m->get_vtype ())
951 {
952 case VT_LABEL:
953 case VT_ADDRESS:
954 case VT_OFFSET:
955 m->set_raw_visbits (vbits);
956 break;
957 default:
958 if (i1 == 0)
959 m->set_raw_visbits (vbits);
960 else if (cmp_vbits == VAL_RATIO
961 && ((vbits & (VAL_VALUE | VAL_TIMEVAL))
962 == (VAL_VALUE | VAL_TIMEVAL)))
963 // make ratios for VAL_VALUE only
964 m->set_raw_visbits ((vbits | VAL_VALUE | cmp_vbits) & ~VAL_TIMEVAL);
965 else
966 m->set_raw_visbits (vbits | cmp_vbits);
967 break;
968 }
969 newItems->append (m);
970 }
971 }
972 items->reset ();
973 items->addAll (newItems);
974 delete newItems;
975 phaseIdx++;
976 reset_data (false);
977 }
978
979 MetricList *
get_compare_mlist(MetricList * met_list,int grInd)980 DbeView::get_compare_mlist (MetricList *met_list, int grInd)
981 {
982 MetricList *mlist = new MetricList (met_list->get_type ());
983 mlist->set_sort_ref_index (met_list->get_sort_ref_index ());
984 mlist->set_sort_rev (met_list->get_sort_rev ());
985
986 Vector<Metric*> *items_old = met_list->get_items ();
987 for (int i = 0, sz = items_old->size (); i < sz; i++)
988 {
989 Metric *m = get_compare_metric (items_old->get (i), grInd + 1);
990 mlist->append (m);
991 }
992 return mlist;
993 }
994
995 void
remove_compare_metrics(MetricList * mlist)996 DbeView::remove_compare_metrics (MetricList *mlist)
997 {
998 Vector<Metric*> *items = mlist->get_items ();
999 Vector<Metric*> *items_old = items->copy ();
1000 items->reset ();
1001 int sort_index = mlist->get_sort_ref_index ();
1002 mlist->set_sort_ref_index (0);
1003 for (int i = 0, sz = items_old->size (); i < sz; i++)
1004 {
1005 Metric *m = items_old->fetch (i);
1006 if (m->get_expr_spec () == NULL)
1007 {
1008 // this is a 'non-compare' metric; add it
1009 items->append (m);
1010 if (sort_index == i)
1011 mlist->set_sort_ref_index (items->size () - 1);
1012 continue;
1013 }
1014 // is the 'non-compare' version of the metric already in the list?
1015 int ind = mlist->get_listorder (m->get_cmd (), m->get_subtype ());
1016 if (ind == -1)
1017 {
1018 // not in the list; add it
1019 BaseMetric *bm = dbeSession->find_metric (m->get_type (), m->get_cmd (), NULL);
1020 Metric *new_met = new Metric (bm, m->get_subtype ());
1021 new_met->set_raw_visbits (m->get_visbits () & ~(CMP_DELTA | CMP_RATIO));
1022 items->append (new_met);
1023 if (sort_index == i)
1024 mlist->set_sort_ref_index (items->size () - 1);
1025 }
1026 delete m;
1027 }
1028 delete items_old;
1029 reset_data (false);
1030 }
1031
1032 // setMetrics -- set the metric list according to specification
1033 // The previous sort is preserved, if possible
1034 // Otherwise, the default sort setting is used
1035 // Returns NULL if OK, or an error string if not
1036 //YXXX only MET_NORMAL appears to be used... code could be simplified
1037 char *
setMetrics(char * mspec,bool fromRcFile)1038 DbeView::setMetrics (char *mspec, bool fromRcFile)
1039 {
1040 char *ret;
1041 MetricType mtype = MET_NORMAL;
1042 // note that setting the default is done here, while all else is in MetricList
1043 if (mspec == NULL) abort ();
1044 if (strcasecmp (mspec, Command::DEFAULT_CMD) == 0)
1045 {
1046 mspec = settings->get_default_metrics ();
1047 fromRcFile = true;
1048 }
1049 MetricList *mlist = get_metric_list (mtype);
1050 mlist = new MetricList (mlist);
1051 ret = mlist->set_metrics (mspec, fromRcFile, derived_metrics);
1052 if (ret == NULL)
1053 {
1054 switch (mtype)
1055 {
1056 case MET_NORMAL:
1057 case MET_COMMON:
1058 delete metrics_lists->fetch (MET_COMMON);
1059 metrics_lists->store (MET_COMMON, new MetricList (mlist));
1060 break;
1061 // ignoring the following cases (why?)
1062 case MET_SRCDIS:
1063 case MET_CALL:
1064 case MET_DATA:
1065 case MET_INDX:
1066 case MET_CALL_AGR:
1067 case MET_IO:
1068 case MET_HEAP:
1069 break;
1070 }
1071 add_compare_metrics (mlist);
1072
1073 //YXXX looks like cut/paste code here, see reset_metric_list()
1074 switch (mtype)
1075 {
1076 case MET_NORMAL:
1077 delete metrics_lists->fetch (mtype);
1078 metrics_lists->store (mtype, mlist);
1079 //YXXX is lack of break intentional? If so, add comment...
1080 case MET_COMMON:
1081 metrics_lists->fetch (MET_SRCDIS)->set_metrics (mlist);
1082 metrics_lists->fetch (MET_CALL)->set_metrics (mlist);
1083 metrics_lists->fetch (MET_CALL_AGR)->set_metrics (mlist);
1084 remove_compare_metrics (metrics_lists->fetch (MET_CALL_AGR));
1085 metrics_lists->fetch (MET_DATA)->set_metrics (mlist);
1086 metrics_lists->fetch (MET_INDX)->set_metrics (mlist);
1087 metrics_lists->fetch (MET_IO)->set_metrics (mlist);
1088 metrics_lists->fetch (MET_HEAP)->set_metrics (mlist);
1089 break;
1090 case MET_CALL_AGR:
1091 delete metrics_lists->fetch (MET_CALL_AGR);
1092 metrics_lists->store (MET_CALL_AGR, mlist);
1093 remove_compare_metrics (mlist);
1094 break;
1095 case MET_SRCDIS:
1096 case MET_CALL:
1097 case MET_DATA:
1098 case MET_INDX:
1099 case MET_IO:
1100 case MET_HEAP:
1101 delete metrics_lists->fetch (mtype);
1102 metrics_lists->store (mtype, mlist);
1103 break;
1104 default:
1105 abort ();
1106 }
1107 reset_data (false);
1108 }
1109 else
1110 delete mlist;
1111 return ret;
1112 }
1113
1114
1115 // Set Sort by name (er_print)
1116 char *
setSort(char * sort_list,MetricType mtype,bool fromRcFile)1117 DbeView::setSort (char * sort_list, MetricType mtype, bool fromRcFile)
1118 {
1119 MetricList *mlist = NULL;
1120
1121 // note that setting the default is done here, while all else is in MetricList
1122 if ((sort_list == NULL) || (strcmp (sort_list, Command::DEFAULT_CMD) == 0))
1123 {
1124 if (settings->str_dsort == NULL)
1125 settings->str_dsort = strdup (Command::DEFAULT_METRICS);
1126 sort_list = settings->get_default_sort ();
1127 }
1128 mlist = get_metric_list (mtype);
1129
1130 if (mlist == NULL)
1131 abort ();
1132
1133 // set the new sort
1134 char *ret = mlist->set_sort (sort_list, fromRcFile);
1135 if (ret != NULL)
1136 return ret;
1137
1138 // now resort all cached data
1139 resortData (mtype);
1140 return NULL;
1141 }
1142
1143 // Set sort from the visible index (Analyzer)
1144 void
setSort(int visindex,MetricType mtype,bool reverse)1145 DbeView::setSort (int visindex, MetricType mtype, bool reverse)
1146 {
1147 MetricList *mlist = get_metric_list (mtype);
1148 Vector<Metric*> *items = mlist->get_items ();
1149 if (visindex >= items->size ())
1150 return;
1151 mlist->set_sort (visindex, reverse);
1152 resortData (mtype);
1153 if (mtype == MET_NORMAL)
1154 {
1155 int idx_cc = -1;
1156 MetricList *mlist_cc = get_metric_list (MET_CALL);
1157 Vector<Metric*> *items_cc = mlist_cc->get_items ();
1158 for (int i = 0; i < items_cc->size (); i++)
1159 {
1160 char * name_cc = items_cc->fetch (i)->get_username ();
1161 char * name_normal = items->fetch (visindex)->get_username ();
1162 if (0 == strncmp (name_cc, name_normal, strlen (name_cc)))
1163 {
1164 idx_cc = i;
1165 break;
1166 }
1167 }
1168 if (idx_cc != -1)
1169 {
1170 mlist_cc->set_sort (idx_cc, reverse);
1171 resortData (MET_CALL);
1172 // Change a sort metric for MET_CALL_AGR
1173 Metric *m = items_cc->fetch (idx_cc);
1174 MetricList *cList = get_metric_list (MET_CALL_AGR);
1175 Metric *m1 = cList->find_metric (m->get_cmd (), m->get_subtype ());
1176 if (m1)
1177 cList->set_sort_metric (m1->get_cmd (), m1->get_subtype (), reverse);
1178 }
1179 }
1180 if (mtype == MET_CALL)
1181 {
1182 int idx_norm = -1;
1183 MetricList *mlist_norm = get_metric_list (MET_NORMAL);
1184 Vector<Metric*> *items_norm = mlist_norm->get_items ();
1185 for (int i = 0; i < items_norm->size (); i++)
1186 {
1187 char * name_norm = items_norm->fetch (i)->get_username ();
1188 char * name_cc = items->fetch (visindex)->get_username ();
1189 if (mlist_norm->get_sort_ref_index () == i
1190 && 0 == strncmp (name_norm, name_cc, strlen (name_norm)))
1191 {
1192 idx_norm = i;
1193 break;
1194 }
1195 }
1196 if (idx_norm == -1)
1197 {
1198 for (int i = 0; i < items_norm->size (); i++)
1199 {
1200 char * name_norm = items_norm->fetch (i)->get_username ();
1201 char * name_cc = items->fetch (visindex)->get_username ();
1202 if (0 == strncmp (name_norm, name_cc, strlen (name_norm)))
1203 {
1204 idx_norm = i;
1205 break;
1206 }
1207 }
1208 }
1209 if (idx_norm != -1)
1210 {
1211 mlist_norm->set_sort (idx_norm, reverse);
1212 resortData (MET_NORMAL);
1213 }
1214 // Change a sort metric for MET_CALL_AGR
1215 Metric *m = items->fetch (visindex);
1216 MetricList *cList = get_metric_list (MET_CALL_AGR);
1217 Metric *m1 = cList->find_metric (m->get_cmd (), m->get_subtype ());
1218 if (m1)
1219 cList->set_sort_metric (m1->get_cmd (), m1->get_subtype (), reverse);
1220 }
1221 }
1222
1223 void
resortData(MetricType mtype)1224 DbeView::resortData (MetricType mtype)
1225 {
1226 int idx;
1227 Hist_data *data;
1228
1229 MetricList *mlist = get_metric_list (mtype);
1230 switch (mtype)
1231 {
1232 case MET_NORMAL:
1233 if (func_data != NULL)
1234 func_data->resort (mlist);
1235 if (line_data != NULL)
1236 line_data->resort (mlist);
1237 if (pc_data != NULL)
1238 pc_data->resort (mlist);
1239 break;
1240 case MET_CALL:
1241 case MET_CALL_AGR:
1242 if (fitem_data != NULL)
1243 fitem_data->resort (mlist);
1244 if (callers != NULL)
1245 callers->resort (mlist);
1246 if (callees != NULL)
1247 callees->resort (mlist);
1248 break;
1249 case MET_DATA:
1250 if (dobj_data != NULL)
1251 dobj_data->resort (mlist);
1252 if (dlay_data != NULL)
1253 {
1254 delete dlay_data;
1255 dlay_data = NULL;
1256 }
1257 break;
1258 case MET_INDX:
1259 Vec_loop (Hist_data*, indx_data, idx, data)
1260 {
1261 if (data)
1262 data->resort (mlist);
1263 }
1264 break;
1265 case MET_IO:
1266 if (iofile_data != NULL)
1267 iofile_data->resort (mlist);
1268 if (iovfd_data != NULL)
1269 iovfd_data->resort (mlist);
1270 if (iocs_data != NULL)
1271 iocs_data->resort (mlist);
1272 break;
1273 case MET_HEAP:
1274 if (heapcs_data != NULL)
1275 heapcs_data->resort (mlist);
1276 break;
1277 case MET_COMMON:
1278 case MET_SRCDIS:
1279 break;
1280 }
1281 }
1282
1283 // Get the sort metric name
1284 char *
getSort(MetricType mtype)1285 DbeView::getSort (MetricType mtype)
1286 {
1287 MetricList *mlist = get_metric_list (mtype);
1288 return mlist->get_sort_name ();
1289 }
1290
1291 // Get the sort command (to use for resetting)
1292 char *
getSortCmd(MetricType mtype)1293 DbeView::getSortCmd (MetricType mtype)
1294 {
1295 MetricList *mlist = get_metric_list (mtype);
1296 return mlist->get_sort_cmd ();
1297 }
1298
1299 int
get_sel_ind(Histable * selObj,int type,int subtype)1300 DbeView::get_sel_ind (Histable *selObj, int type, int subtype)
1301 {
1302 Hist_data *data;
1303 switch (type)
1304 {
1305 case DSP_FUNCTION:
1306 data = func_data;
1307 break;
1308 case DSP_LINE:
1309 data = line_data;
1310 break;
1311 case DSP_PC:
1312 data = pc_data;
1313 break;
1314 case DSP_SOURCE:
1315 case DSP_SOURCE_V2:
1316 data = src_data;
1317 break;
1318 case DSP_DISASM:
1319 case DSP_DISASM_V2:
1320 data = dis_data;
1321 break;
1322 case DSP_DLAYOUT:
1323 data = dlay_data;
1324 break;
1325 case DSP_DATAOBJ:
1326 data = dobj_data;
1327 break;
1328 case DSP_IOACTIVITY:
1329 data = iofile_data;
1330 break;
1331 case DSP_IOVFD:
1332 data = iovfd_data;
1333 break;
1334 case DSP_IOCALLSTACK:
1335 data = iocs_data;
1336 break;
1337 case DSP_HEAPCALLSTACK:
1338 data = heapcs_data;
1339 break;
1340 case DSP_MEMOBJ:
1341 case DSP_INDXOBJ:
1342 data = get_indxobj_data (subtype);
1343 break;
1344 default:
1345 data = NULL;
1346 break;
1347 }
1348 if (data == NULL || data->get_status () != Hist_data::SUCCESS)
1349 return -1;
1350 Vector<Hist_data::HistItem*> *hi_data = data->get_hist_items ();
1351 for (int i = 0, sz = hi_data->size (); i < sz; i++)
1352 {
1353 Hist_data::HistItem *hi = hi_data->fetch (i);
1354 if (hi->obj == selObj)
1355 return i;
1356 }
1357 return -1;
1358 }
1359
1360 MetricList *
get_metric_list(MetricType mtype,bool compare,int gr_num)1361 DbeView::get_metric_list (MetricType mtype, bool compare, int gr_num)
1362 {
1363 MetricList *mlist;
1364 switch (mtype)
1365 {
1366 case MET_COMMON:// comparison mode, src & disasm views
1367 if (gr_num == 0)
1368 {// signifies same src file (or load obj) used by all groups
1369 // show compare metrics in columns (not in separate source panels)
1370 mlist = get_metric_list (MET_NORMAL);
1371 break;
1372 }
1373 // once source panel per group; get metrics for this group
1374 mlist = get_metric_list (mtype);
1375 if (compare)
1376 {
1377 mlist = get_compare_mlist (mlist, gr_num - 1);
1378 int mode = get_compare_mode ();
1379 if ((mode & (CMP_DELTA | CMP_RATIO)) != 0)
1380 {
1381 for (long i = 0, sz = mlist->size (); i < sz; i++)
1382 {
1383 Metric *m = mlist->get (i);
1384 char *expr_spec = m->get_expr_spec ();
1385 if (expr_spec && (strcmp (expr_spec, NTXT ("EXPGRID==1")) != 0))
1386 {
1387 int vbits = m->get_visbits () & ~(VAL_DELTA | VAL_RATIO);
1388 if ((mode & CMP_RATIO) != 0)
1389 vbits |= VAL_RATIO;
1390 else if ((mode & CMP_DELTA) != 0)
1391 vbits |= VAL_DELTA;
1392 m->set_raw_visbits (vbits);
1393 }
1394 }
1395 }
1396 }
1397 break;
1398 default:
1399 mlist = get_metric_list (mtype);
1400 break;
1401 }
1402 return mlist;
1403 }
1404
1405 Hist_data *
get_data(MetricList * mlist,Histable * selObj,int type,int subtype)1406 DbeView::get_data (MetricList *mlist, Histable *selObj, int type, int subtype)
1407 {
1408 Hist_data *data;
1409 switch (type)
1410 {
1411 case DSP_FUNCTION:
1412 delete func_data;
1413 mlist = new MetricList (mlist);
1414 func_data = get_hist_data (mlist, Histable::FUNCTION, subtype, Hist_data::ALL);
1415 return func_data;
1416 case DSP_LINE:
1417 delete line_data;
1418 mlist = new MetricList (mlist);
1419 line_data = get_hist_data (mlist, Histable::LINE, subtype, Hist_data::ALL);
1420 return line_data;
1421 case DSP_PC:
1422 delete pc_data;
1423 mlist = new MetricList (mlist);
1424 pc_data = get_hist_data (mlist, Histable::INSTR, subtype, Hist_data::ALL);
1425 return pc_data;
1426 case DSP_DATAOBJ:
1427 delete dobj_data;
1428 dobj_data = get_hist_data (mlist, Histable::DOBJECT, subtype,
1429 Hist_data::ALL);
1430 break;
1431 case DSP_MEMOBJ:
1432 return get_hist_data (mlist, Histable::MEMOBJ, subtype, Hist_data::ALL);
1433 case DSP_INDXOBJ:
1434 data = get_hist_data (mlist, Histable::INDEXOBJ, subtype, Hist_data::ALL);
1435 indx_data->store (subtype, data);
1436 return data;
1437 case DSP_DLAYOUT:
1438 delete dlay_data;
1439 marks->reset ();
1440 data = get_hist_data (mlist, Histable::DOBJECT, subtype,
1441 Hist_data::LAYOUT);
1442 // .. provides metric data for layout
1443 dlay_data = get_data_space ()->get_layout_data (data, marks,
1444 get_thresh_dis ());
1445 return dlay_data;
1446 case DSP_CALLER:
1447 delete callers;
1448 callers = get_hist_data (mlist, Histable::FUNCTION, subtype,
1449 Hist_data::CALLERS, selObj);
1450 return callers;
1451 case DSP_CALLEE:
1452 delete callees;
1453 callees = get_hist_data (mlist, Histable::FUNCTION, subtype,
1454 Hist_data::CALLEES, selObj);
1455 return callees;
1456 case DSP_SELF:
1457 // Center Function item
1458 delete fitem_data;
1459 fitem_data = get_hist_data (mlist, Histable::FUNCTION, subtype,
1460 Hist_data::SELF, selObj);
1461 return fitem_data;
1462 case DSP_SOURCE_V2:
1463 case DSP_DISASM_V2:
1464 case DSP_SOURCE:
1465 case DSP_DISASM:
1466 {
1467 // Source or disassembly
1468 if (selObj == NULL)
1469 {
1470 error_msg = status_str (DBEVIEW_NO_SEL_OBJ);
1471 return NULL;
1472 }
1473 Function *func = (Function *) selObj->convertto (Histable::FUNCTION);
1474 if (func == NULL)
1475 {
1476 error_msg = dbe_strdup (GTXT ("Not a real function; no source or disassembly available."));
1477 return NULL;
1478 }
1479 if (func->flags & FUNC_FLAG_SIMULATED)
1480 {
1481 error_msg = dbe_strdup (GTXT ("Not a real function; no source or disassembly available."));
1482 return NULL;
1483 }
1484 if (func->get_name () == NULL)
1485 {
1486 error_msg = dbe_strdup (GTXT ("Source location not recorded in experiment"));
1487 return NULL;
1488 }
1489 Module *module = func->module;
1490 if (module == NULL || module->get_name () == NULL)
1491 {
1492 error_msg = dbe_strdup (GTXT ("Object name not recorded in experiment"));
1493 return NULL;
1494 }
1495 marks->reset ();
1496 SourceFile *srcContext = (SourceFile *) selObj->convertto (Histable::SOURCEFILE);
1497 sel_binctx = func;
1498
1499 if (func_data == NULL)
1500 func_data = get_hist_data (mlist, Histable::FUNCTION, subtype, Hist_data::ALL);
1501
1502 // for source and disassembly the name needs to be invisible,
1503 // but that's handled in the module code
1504 if (type == DSP_SOURCE || type == DSP_SOURCE_V2)
1505 {
1506 marks2dsrc->reset ();
1507 marks2dsrc_inc->reset ();
1508 delete src_data;
1509 data = src_data = module->get_data (this, mlist, Histable::LINE,
1510 func_data->get_totals ()->value, srcContext, func,
1511 marks, get_thresh_src (), get_src_compcom (),
1512 get_src_visible (), get_hex_visible (),
1513 false, false, marks2dsrc, marks2dsrc_inc);
1514 }
1515 else
1516 { /* type == DSP_DISASM */
1517 marks2ddis->reset ();
1518 marks2ddis_inc->reset ();
1519 delete dis_data;
1520 data = dis_data = module->get_data (this, mlist, Histable::INSTR,
1521 func_data->get_totals ()->value, srcContext, func,
1522 marks, get_thresh_dis (), get_dis_compcom (),
1523 get_src_visible (), get_hex_visible (),
1524 get_func_scope (), false, marks2ddis,
1525 marks2ddis_inc);
1526 }
1527 return data;
1528 }
1529 default:
1530 abort ();
1531 }
1532 return NULL;
1533 }
1534
1535 Histable *
get_compare_obj(Histable * obj)1536 DbeView::get_compare_obj (Histable *obj)
1537 {
1538 char *nm;
1539 switch (obj->get_type ())
1540 {
1541 case Histable::LINE:
1542 nm = obj->get_name ();
1543 if (nm == NULL)
1544 break;
1545 if (dbeSession->comp_dbelines == NULL)
1546 dbeSession->comp_dbelines = new HashMap<char*, DbeLine*>;
1547 return dbeSession->comp_dbelines->get (nm, (DbeLine*) obj);
1548 case Histable::SOURCEFILE:
1549 nm = obj->get_name ();
1550 if (nm == NULL)
1551 break;
1552 nm = get_basename (nm);
1553 if (dbeSession->comp_sources == NULL)
1554 dbeSession->comp_sources = new HashMap<char*, SourceFile*>;
1555 return dbeSession->comp_sources->get (nm, (SourceFile*) obj);
1556 default:
1557 return obj->get_compare_obj ();
1558 }
1559 return obj;
1560 }
1561
1562 //
1563 // get_hist_data() creates a new Hist_data object;
1564 // it's caller's responsibility to delete it.
1565 Hist_data *
get_hist_data(MetricList * mlist_orig,Histable::Type type,int subtype,Hist_data::Mode mode,Histable * obj,Histable * context,Vector<Histable * > * sel_objs,PathTree::PtreeComputeOption flag)1566 DbeView::get_hist_data (MetricList *mlist_orig, Histable::Type type,
1567 int subtype, Hist_data::Mode mode, Histable *obj,
1568 Histable *context, Vector<Histable*> *sel_objs,
1569 PathTree::PtreeComputeOption flag)
1570 {
1571 Vector<Histable*> *objs = NULL;
1572 if (obj != NULL)
1573 {
1574 objs = new Vector<Histable*>();
1575 objs->append (obj);
1576 }
1577 Hist_data *res = get_hist_data (mlist_orig, type, subtype, mode, objs, context, sel_objs, flag);
1578 delete objs;
1579 return res;
1580 }
1581
1582 Hist_data *
get_hist_data(MetricList * mlist_orig,Histable::Type type,int subtype,Hist_data::Mode mode,Vector<Histable * > * objs,Histable * context,Vector<Histable * > * sel_objs,PathTree::PtreeComputeOption flag)1583 DbeView::get_hist_data (MetricList *mlist_orig, Histable::Type type,
1584 int subtype, Hist_data::Mode mode,
1585 Vector<Histable*> *objs,
1586 Histable *context, Vector<Histable*> *sel_objs,
1587 PathTree::PtreeComputeOption flag)
1588 {
1589 MetricList *mlist = new MetricList (mlist_orig);
1590 /*
1591 * mlist differs from mlist_orig in two ways:
1592 * - extra metrics have been added as needed to compute derived metrics
1593 * - extra metrics have been added as needed to compute time for HWC (time converted) metrics
1594 * (We don't drop those extra metrics but we don't display they to user.)
1595 * - visibility bits have been added for compare mode (e.g., VAL_DELTA or VAL_RATIO)
1596 * (We want to preserve those visbits.)
1597 */
1598 // loop over mlist to add missing dependencies for derived metrics
1599 for (long i = 0, sz = mlist->get_items ()->size (); i < sz; i++)
1600 {
1601 Metric *m = mlist->get_items ()->fetch (i);
1602 char *expr_spec = m->get_expr_spec ();
1603 if (expr_spec && (strcmp (expr_spec, NTXT ("EXPGRID==1")) != 0))
1604 {
1605 int ind = mlist->get_listorder (m->get_cmd (), m->get_subtype (), NTXT ("EXPGRID==1"));
1606 if (ind < 0)
1607 {
1608 BaseMetric *bm1 = dbeSession->find_metric (m->get_type (), m->get_cmd (), NTXT ("EXPGRID==1"));
1609 Metric *m1 = new Metric (bm1, m->get_subtype ());
1610 m1->set_dmetrics_visbits (VAL_VALUE);
1611 mlist->append (m1);
1612 }
1613 }
1614 }
1615
1616 for (long i = 0, sz = mlist->get_items ()->size (); i < sz; i++)
1617 {
1618 Metric *m = mlist->get_items ()->fetch (i);
1619 if (m->get_type () == BaseMetric::DERIVED)
1620 {
1621 Definition *def = m->get_definition ();
1622 Vector<BaseMetric*> *dependencies = def->get_dependencies ();
1623 long *map = def->get_map ();
1624 for (long i1 = 0, sz1 = dependencies ? dependencies->size () : 0; i1 < sz1; i1++)
1625 {
1626 BaseMetric *bm = dependencies->fetch (i1);
1627 int ind = mlist->get_listorder (bm->get_cmd (), m->get_subtype (), m->get_expr_spec ());
1628 if (ind < 0)
1629 {
1630 BaseMetric *bm1 = dbeSession->find_metric (bm->get_type (), bm->get_cmd (), m->get_expr_spec ());
1631 assert (bm1 != NULL);
1632 Metric *m1 = new Metric (bm1, m->get_subtype ());
1633 m1->set_dmetrics_visbits (VAL_VALUE);
1634 ind = mlist->size ();
1635 mlist->append (m1);
1636 }
1637 map[i1] = ind;
1638 }
1639 }
1640 else if (m->get_type () == BaseMetric::HWCNTR)
1641 {
1642 if (m->is_tvisible () && m->get_dependent_bm ())
1643 {
1644 int ii = mlist->get_listorder (m->get_dependent_bm ()->get_cmd (),
1645 m->get_subtype (), m->get_expr_spec ());
1646 if (ii < 0)
1647 {
1648 BaseMetric *bm1 = dbeSession->find_metric (m->get_type (),
1649 m->get_dependent_bm ()->get_cmd (),
1650 m->get_expr_spec ());
1651 assert (bm1 != NULL);
1652 Metric *m1 = new Metric (bm1, m->get_subtype ());
1653 m1->set_dmetrics_visbits ((m->get_visbits ()
1654 & ~VAL_VALUE) | VAL_TIMEVAL);
1655 mlist->append (m1);
1656 }
1657 }
1658 }
1659 }
1660
1661 // compute Hist_data
1662 Hist_data *data;
1663 switch (type)
1664 {
1665 case Histable::INSTR:
1666 case Histable::LINE:
1667 data = ptree->compute_metrics (mlist, type, mode, objs, context, sel_objs);
1668 break;
1669 case Histable::FUNCTION:
1670 case Histable::MODULE:
1671 case Histable::LOADOBJECT:
1672 data = ptree->compute_metrics (mlist, type, mode, objs, NULL,
1673 sel_objs, flag);
1674 break;
1675 case Histable::DOBJECT:
1676 data = dspace->compute_metrics (mlist, type, mode,
1677 objs ? objs->fetch (0) : NULL);
1678 break;
1679 case Histable::MEMOBJ:
1680 case Histable::INDEXOBJ:
1681 data = indxspaces->get (subtype)->compute_metrics (mlist, type, mode,
1682 objs, NULL);
1683 break;
1684 case Histable::IOACTFILE:
1685 if (objs == NULL)
1686 {
1687 data = iofile_data = iospace->compute_metrics (mlist, type, mode,
1688 NULL);
1689 break;
1690 }
1691 else
1692 {
1693 data = iospace->compute_metrics (mlist, type, mode, objs->fetch (0));
1694 break;
1695 }
1696 case Histable::IOACTVFD:
1697 if (objs == NULL)
1698 data = iovfd_data = iospace->compute_metrics (mlist, type, mode, NULL);
1699 else
1700 data = iospace->compute_metrics (mlist, type, mode, objs->fetch (0));
1701 break;
1702 case Histable::IOCALLSTACK:
1703 if (objs == NULL)
1704 data = iocs_data = iospace->compute_metrics (mlist, type, mode, NULL);
1705 else
1706 data = iospace->compute_metrics (mlist, type, mode, objs->fetch (0));
1707 break;
1708 case Histable::HEAPCALLSTACK:
1709 if (objs == NULL)
1710 data = heapcs_data = heapspace->compute_metrics (mlist, type, mode, NULL);
1711 else
1712 data = heapspace->compute_metrics (mlist, type, mode, objs->fetch (0));
1713 break;
1714 default:
1715 data = NULL;
1716 break;
1717 }
1718 for (long i = mlist_orig->get_items ()->size (),
1719 sz = mlist->get_items ()->size (); i < sz; i++)
1720 {
1721 Metric *m = mlist->get_items ()->get (i);
1722 m->set_dmetrics_visbits (VAL_HIDE_ALL | m->get_visbits ());
1723 }
1724 if (data)
1725 data->nmetrics = mlist_orig->size ();
1726 return data;
1727 }
1728
1729 char *
get_mobj_name(int subtype)1730 DbeView::get_mobj_name (int subtype)
1731 {
1732 MemorySpace *ms = getMemorySpace (subtype);
1733 if (ms == NULL)
1734 ms = addMemorySpace (subtype);
1735 return ms->getMemObjTypeName ();
1736 }
1737
1738 MemorySpace *
getMemorySpace(int subtype)1739 DbeView::getMemorySpace (int subtype)
1740 {
1741 for (long i = 0, sz = VecSize (memspaces); i < sz; i++)
1742 {
1743 MemorySpace *ms = memspaces->get (i);
1744 if (subtype == ms->getMemObjType ())
1745 return ms;
1746 }
1747 return NULL;
1748 }
1749
1750 MemorySpace *
addMemorySpace(int subtype)1751 DbeView::addMemorySpace (int subtype)
1752 {
1753 MemorySpace *ms = new MemorySpace (this, subtype);
1754 memspaces->append (ms);
1755 return ms;
1756 }
1757
1758 Hist_data *
get_indxobj_data(int subtype)1759 DbeView::get_indxobj_data (int subtype)
1760 {
1761 if (subtype < 0 || subtype >= indx_data->size ())
1762 return NULL;
1763 return indx_data->fetch (subtype);
1764 }
1765
1766 void
set_indxobj_sel(int subtype,int sel_ind)1767 DbeView::set_indxobj_sel (int subtype, int sel_ind)
1768 {
1769 Hist_data *data = get_indxobj_data (subtype);
1770 if (data == NULL)
1771 return;
1772 if (sel_ind >= 0 && sel_ind < data->size ())
1773 {
1774 Histable *obj = data->fetch (sel_ind)->obj;
1775 sel_idxobj->store (subtype, obj);
1776 }
1777 }
1778
1779 Histable *
get_indxobj_sel(int subtype)1780 DbeView::get_indxobj_sel (int subtype)
1781 {
1782 return sel_idxobj->fetch (subtype);
1783 }
1784
1785 void
addIndexSpace(int subtype)1786 DbeView::addIndexSpace (int subtype)
1787 {
1788 PathTree *is = new PathTree (this, subtype);
1789 indxspaces->store (subtype, is);
1790 indx_data->store (subtype, NULL);
1791 sel_idxobj->store (subtype, NULL);
1792 settings->indxobj_define (subtype, false);
1793 }
1794
1795 Histable *
get_sel_obj_io(uint64_t id,Histable::Type type)1796 DbeView::get_sel_obj_io (uint64_t id, Histable::Type type)
1797 {
1798 if (iospace == NULL)
1799 return NULL;
1800 Histable *obj = NULL;
1801 Hist_data *data = NULL;
1802 switch (type)
1803 {
1804 case Histable::IOACTFILE:
1805 data = iofile_data;
1806 break;
1807 case Histable::IOACTVFD:
1808 data = iovfd_data;
1809 break;
1810 case Histable::IOCALLSTACK:
1811 data = iocs_data;
1812 break;
1813 default:
1814 break;
1815 }
1816 if (data == NULL)
1817 return NULL;
1818
1819 Vector<Hist_data::HistItem*> *hi_data = data->get_hist_items ();
1820 int size = hi_data->size ();
1821 for (int i = 0; i < size; i++)
1822 {
1823 Hist_data::HistItem *hi = hi_data->fetch (i);
1824 if (hi->obj != NULL && (uint64_t) hi->obj->id == id)
1825 {
1826 obj = hi->obj;
1827 break;
1828 }
1829 }
1830 return obj;
1831 }
1832
1833 Histable *
get_sel_obj_heap(uint64_t id)1834 DbeView::get_sel_obj_heap (uint64_t id)
1835 {
1836 if (heapspace == NULL || heapcs_data == NULL)
1837 return NULL;
1838 Histable *obj = NULL;
1839 Hist_data *data = heapcs_data;
1840 Vector<Hist_data::HistItem*> *hi_data = data->get_hist_items ();
1841 int size = hi_data->size ();
1842 for (int i = 0; i < size; i++)
1843 {
1844 Hist_data::HistItem *hi = hi_data->fetch (i);
1845 if ((hi->obj != NULL) && ((uint64_t) hi->obj->id) == id)
1846 {
1847 obj = hi->obj;
1848 break;
1849 }
1850 }
1851 return obj;
1852 }
1853
1854 CStack_data *
get_cstack_data(MetricList * mlist)1855 DbeView::get_cstack_data (MetricList *mlist)
1856 {
1857 return ptree->get_cstack_data (mlist);
1858 }
1859
1860 Stats_data *
get_stats_data(int index)1861 DbeView::get_stats_data (int index)
1862 {
1863 DataView *packets = get_filtered_events (index, DATA_SAMPLE);
1864 if (packets == NULL)
1865 return NULL;
1866 return new Stats_data (packets);
1867 }
1868
1869 Ovw_data *
get_ovw_data(int index)1870 DbeView::get_ovw_data (int index)
1871 {
1872 DataView *packets = get_filtered_events (index, DATA_SAMPLE);
1873 Experiment* exp = dbeSession->get_exp (index);
1874 hrtime_t starttime = 0;
1875 if (exp != NULL)
1876 starttime = exp->getStartTime ();
1877 if (packets == NULL)
1878 return NULL;
1879 return new Ovw_data (packets, starttime);
1880 }
1881
1882 char *
set_filter(const char * filter_spec)1883 DbeView::set_filter (const char *filter_spec)
1884 {
1885 if (dbe_strcmp (filter_spec, cur_filter_str) == 0) // Nothing was changed
1886 return NULL;
1887
1888 // if string is NULL, delete the filter
1889 if (filter_spec == NULL)
1890 {
1891 if (cur_filter_str)
1892 {
1893 free (cur_filter_str);
1894 cur_filter_str = NULL;
1895 }
1896 if (cur_filter_expr)
1897 {
1898 delete cur_filter_expr;
1899 cur_filter_expr = NULL;
1900 }
1901 noParFilter = false;
1902 purge_events ();
1903 reset_data (false);
1904 return NULL;
1905 }
1906
1907 // process the filter
1908 Expression *expr = dbeSession->ql_parse (filter_spec);
1909 if (expr == NULL)
1910 return dbe_sprintf (GTXT ("Invalid filter specification `%s'\n"), filter_spec);
1911
1912 if (dbe_strcmp (filter_spec, "1") == 0)
1913 noParFilter = false;
1914 else if (sel_obj != NULL)
1915 if (sel_obj->get_type () == Histable::LINE)
1916 if (expr->verifyObjectInExpr (sel_obj))
1917 noParFilter = true;
1918
1919 // valid new filter
1920 if (cur_filter_str != NULL)
1921 {
1922 free (prev_filter_str);
1923 prev_filter_str = dbe_strdup (cur_filter_str);
1924 }
1925 free (cur_filter_str);
1926 cur_filter_str = dbe_strdup (filter_spec);
1927 delete cur_filter_expr;
1928 cur_filter_expr = expr;
1929 purge_events ();
1930 reset_data (false);
1931 return NULL;
1932 }
1933
1934 FilterExp *
get_FilterExp(Experiment * exp)1935 DbeView::get_FilterExp (Experiment *exp)
1936 {
1937 if (cur_filter_expr == NULL)
1938 return NULL;
1939 Expression::Context *ctx = new Expression::Context (this, exp);
1940 return new FilterExp (cur_filter_expr, ctx, noParFilter);
1941 }
1942
1943 char *
get_filter()1944 DbeView::get_filter ()
1945 {
1946 return dbe_strdup (cur_filter_str);
1947 }
1948
1949 FilterSet *
get_filter_set(int n)1950 DbeView::get_filter_set (int n)
1951 {
1952 fflush (stderr);
1953 if (n >= filters->size ())
1954 return NULL;
1955 return ( filters->fetch (n));
1956 }
1957
1958 Vector<FilterNumeric*> *
get_all_filters(int nexp)1959 DbeView::get_all_filters (int nexp)
1960 {
1961 FilterSet *fs = get_filter_set (nexp);
1962 return fs ? fs->get_all_filters () : NULL;
1963 }
1964
1965 FilterNumeric *
get_FilterNumeric(int nexp,int idx)1966 DbeView::get_FilterNumeric (int nexp, int idx)
1967 {
1968 FilterSet *fs = get_filter_set (nexp);
1969 return fs ? fs->get_filter (idx) : NULL;
1970 }
1971
1972 void
backtrack_filter()1973 DbeView::backtrack_filter()
1974 {
1975 if (prev_filter_str != NULL)
1976 set_filter(prev_filter_str);
1977 else set_filter("1"); // reset
1978
1979 }
1980
1981 void
update_advanced_filter()1982 DbeView::update_advanced_filter ()
1983 {
1984 char *s = get_advanced_filter ();
1985 if (dbe_strcmp (s, cur_filter_str))
1986 {
1987 phaseIdx++;
1988 char *err_msg = set_filter (s);
1989 if (err_msg)
1990 {
1991 #ifdef DEBUG
1992 fprintf (stderr, NTXT ("ERROR: Advanced Filter: '%s'\n"), err_msg);
1993 #endif
1994 }
1995 }
1996 free (s);
1997 }
1998
1999 bool
set_pattern(int n,Vector<char * > * pattern_str,bool * error)2000 DbeView::set_pattern (int n, Vector<char *> *pattern_str, bool *error)
2001 {
2002 Vector<FilterNumeric*> *filts = get_all_filters (n);
2003
2004 bool ret = false;
2005 *error = false;
2006 int imax = pattern_str->size ();
2007 if (imax > filts->size ())
2008 imax = filts->size ();
2009 for (int i = 0; i < imax; i++)
2010 {
2011 FilterNumeric *f = filts->fetch (i);
2012 char *s = pattern_str->fetch (i);
2013 if (s == NULL)
2014 continue;
2015 if (f->set_pattern (s, error))
2016 ret = true;
2017 }
2018
2019 if (ret || cur_filter_expr)
2020 {
2021 update_advanced_filter ();
2022 filter_active = true;
2023 }
2024 return ret;
2025 }
2026
2027 static void
append_experiments(StringBuilder * sb,int first,int last)2028 append_experiments (StringBuilder *sb, int first, int last)
2029 {
2030 if (first == -1)
2031 return;
2032 if (sb->length () != 0)
2033 sb->append (NTXT (" || "));
2034 sb->append ('(');
2035 if (first == last)
2036 {
2037 sb->append (NTXT ("EXPID=="));
2038 sb->append (first);
2039 }
2040 else
2041 {
2042 sb->append (NTXT ("EXPID>="));
2043 sb->append (first);
2044 sb->append (NTXT (" && EXPID<="));
2045 sb->append (last);
2046 }
2047 sb->append (')');
2048 }
2049
2050 char *
get_advanced_filter()2051 DbeView::get_advanced_filter ()
2052 {
2053 StringBuilder sb;
2054 bool wasFalse = false;
2055 int first = -1, last = -1;
2056 for (int n = 0, nexps = dbeSession->nexps (); n < nexps; n++)
2057 {
2058 FilterSet *fs = get_filter_set (n);
2059 char *s = fs->get_advanced_filter ();
2060 if (s)
2061 {
2062 if (streq (s, NTXT ("1")))
2063 {
2064 last = n + 1;
2065 if (first == -1)
2066 first = last;
2067 continue;
2068 }
2069 append_experiments (&sb, first, last);
2070 first = -1;
2071 if (streq (s, NTXT ("0")))
2072 {
2073 wasFalse = true;
2074 continue;
2075 }
2076 if (sb.length () != 0)
2077 sb.append (NTXT (" || "));
2078 sb.append (NTXT ("(EXPID=="));
2079 sb.append (n + 1);
2080 sb.append (NTXT (" && ("));
2081 sb.append (s);
2082 free (s);
2083 sb.append (NTXT ("))"));
2084 }
2085 else
2086 {
2087 last = n + 1;
2088 if (first == -1)
2089 first = last;
2090 }
2091 }
2092 if (first != 1)
2093 {
2094 append_experiments (&sb, first, last);
2095 first = -1;
2096 }
2097 if (sb.length () == 0)
2098 sb.append (wasFalse ? '0' : '1');
2099 else
2100 append_experiments (&sb, first, last);
2101 return sb.toString ();
2102 }
2103
2104 bool
set_pattern(int m,char * pattern)2105 DbeView::set_pattern (int m, char *pattern)
2106 {
2107 bool error = false;
2108
2109 // Store original setting in case of error
2110 int nexps = dbeSession->nexps ();
2111 int orig_phaseIdx = phaseIdx;
2112 bool *orig_enable = new bool[nexps];
2113 char **orig_pattern = new char*[nexps];
2114 for (int i = 0; i < nexps; i++)
2115 {
2116 orig_pattern[i] = get_FilterNumeric (i, m)->get_pattern ();
2117 orig_enable[i] = get_exp_enable (i);
2118 set_exp_enable (i, false);
2119 }
2120
2121 // Copy the pattern so that we could safely modify it
2122 char *buf = dbe_strdup (pattern);
2123 FilterNumeric *fexp = NULL;
2124 char *pb, *pe;
2125 pb = pe = buf;
2126 for (bool done = false; !done; pe++)
2127 {
2128 if (*pe == ':')
2129 {
2130 // experiment filter;
2131 *pe = '\0';
2132 fexp = new FilterNumeric (NULL, NULL, NULL);
2133 fexp->set_range (1, nexps, nexps);
2134 fexp->set_pattern (pb, &error);
2135 if (error)
2136 break;
2137 pb = pe + 1;
2138 }
2139 else if (*pe == '+' || *pe == '\0')
2140 {
2141 // entity filter
2142 if (*pe == '\0')
2143 done = true;
2144 else
2145 *pe = '\0';
2146 for (int i = 0; i < nexps; i++)
2147 {
2148 if (!fexp || fexp->is_selected (i + 1))
2149 {
2150 FilterNumeric *f = get_FilterNumeric (i, m);
2151 f->set_pattern (pb, &error);
2152 if (error)
2153 break;
2154 set_exp_enable (i, true);
2155 }
2156 }
2157 if (error)
2158 break;
2159 delete fexp;
2160 fexp = NULL;
2161 pb = pe + 1;
2162 }
2163 }
2164
2165 if (error)
2166 {
2167 for (int i = 0; i < nexps; i++)
2168 {
2169 bool err;
2170 set_exp_enable (i, orig_enable[i]);
2171 FilterNumeric *f = get_FilterNumeric (i, m);
2172 f->set_pattern (orig_pattern[i], &err);
2173 free (orig_pattern[i]);
2174 }
2175 phaseIdx = orig_phaseIdx;
2176 }
2177 else
2178 {
2179 update_advanced_filter ();
2180 filter_active = true;
2181 }
2182 delete[] orig_enable;
2183 delete[] orig_pattern;
2184 delete fexp;
2185 free (buf);
2186 return !error;
2187 }
2188
2189 void
set_view_mode(VMode newmode)2190 DbeView::set_view_mode (VMode newmode)
2191 {
2192 if (newmode != settings->get_view_mode ())
2193 {
2194
2195 // For OpenMP, the expert mode path-tree is already present with the user mode
2196 // No need to increase the phaseIdx to trigger recomputation of path-tree
2197 // if we toggle between user and expert modes
2198 if (!(dbeSession->is_omp_available ()
2199 && ((newmode == VMODE_EXPERT
2200 && settings->get_view_mode () == VMODE_USER)
2201 || (newmode == VMODE_USER
2202 && settings->get_view_mode () == VMODE_EXPERT))))
2203 phaseIdx++; // For all other cases
2204 setNewViewMode ();
2205 settings->set_view_mode (newmode);
2206 }
2207 }
2208
2209 Cmd_status
set_view_mode(char * str,bool fromRC)2210 DbeView::set_view_mode (char *str, bool fromRC)
2211 {
2212 VMode old = settings->get_view_mode ();
2213 Cmd_status ret = settings->set_view_mode (str, fromRC);
2214 if (old != settings->get_view_mode ())
2215 phaseIdx++;
2216 return ret;
2217 }
2218
2219 Cmd_status
set_en_desc(char * str,bool fromRC)2220 DbeView::set_en_desc (char *str, bool fromRC)
2221 {
2222 // Tell the session
2223 Settings *s = dbeSession->get_settings ();
2224 s->set_en_desc (str, fromRC);
2225
2226 // and tell our settings
2227 return settings->set_en_desc (str, fromRC);
2228 }
2229
2230 // Get processor stats messages
2231 char *
get_processor_msg(int type)2232 DbeView::get_processor_msg (int type)
2233 {
2234 if (ptree == NULL) // if no PathTree, no messages
2235 return NULL;
2236
2237 StringBuilder sb;
2238 Emsg *m = (type == PSTAT_MSG) ? ptree->fetch_stats () : ptree->fetch_warnings ();
2239 for (; m != NULL; m = m->next)
2240 {
2241 char* newmsg = m->get_msg ();
2242 sb.append (newmsg);
2243 sb.append ("\n");
2244 }
2245
2246 if (type == PSTAT_MSG)
2247 ptree->delete_stats ();
2248 else
2249 ptree->delete_warnings ();
2250 return (sb.length () > 0) ? sb.toString () : NULL;
2251 }
2252
2253 void
dump_nodes(FILE * outfile)2254 DbeView::dump_nodes (FILE *outfile)
2255 {
2256 FILE *f = (outfile == NULL ? stderr : outfile);
2257 ptree->print (f);
2258 }
2259
2260 // Dump the clock profile events
2261 void
dump_profile(FILE * out_file)2262 DbeView::dump_profile (FILE *out_file)
2263 {
2264 for (int idx = 0; idx < dbeSession->nexps (); idx++)
2265 {
2266 Experiment *exp = dbeSession->get_exp (idx);
2267 VMode view_mode = get_view_mode ();
2268 char * stateNames [/*LMS_NUM_STATES*/] = LMS_STATE_STRINGS;
2269
2270 // Process clock profile date
2271 DataView *packets = get_filtered_events (idx, DATA_CLOCK);
2272 if (packets && packets->getSize () != 0)
2273 {
2274 hrtime_t start = exp->getStartTime ();
2275 fprintf (out_file,
2276 GTXT ("\nTotal Clock Profiling Packets: %d Experiment: %s\n"),
2277 (int) packets->getSize (), exp->get_expt_name ());
2278 for (long i = 0; i < packets->getSize (); i++)
2279 {
2280 hrtime_t expr_ts = (hrtime_t) packets->getLongValue (PROP_TSTAMP, i);
2281 hrtime_t ts = expr_ts - start;
2282
2283 // get the properties from the packet
2284 uint32_t thrid = (uint32_t) packets->getIntValue (PROP_THRID, i);
2285 uint32_t cpuid = (uint32_t) packets->getIntValue (PROP_CPUID, i);
2286 int mstate = (int) packets->getIntValue (PROP_MSTATE, i);
2287 int nticks = (int) packets->getIntValue (PROP_NTICK, i);
2288
2289 char *sname;
2290 char buf[1024];
2291 if (mstate >= 0 && mstate < LMS_NUM_STATES)
2292 sname = stateNames[mstate];
2293 else
2294 {
2295 snprintf (buf, sizeof (buf), NTXT ("Unexpected mstate = %d"), mstate);
2296 sname = buf;
2297 }
2298
2299 // get the stack IGNORE HIDE
2300 Vector<Histable*> *stack = getStackPCs (view_mode, packets, i);
2301 int stack_size = stack->size ();
2302
2303 // print the packet header with the count of stack frames
2304 fprintf (out_file,
2305 GTXT ("#%6ld: %lld, %3lld.%09lld (%4lld.%09lld) t = %d, cpu = %d, frames = %d\n"),
2306 i, expr_ts, ts / NANOSEC, ts % NANOSEC,
2307 expr_ts / NANOSEC, expr_ts % NANOSEC,
2308 thrid, cpuid, stack_size);
2309 fprintf (out_file,
2310 GTXT (" mstate = %d (%s), nticks = %d\n"),
2311 mstate, sname, nticks);
2312
2313 // dump the callstack
2314 for (int j = stack_size - 1; j >= 0; j--)
2315 {
2316 Histable *frame = stack->fetch (j);
2317 fprintf (out_file, GTXT (" %s [0x%016llx]\n"), frame->get_name (), (long long) frame);
2318 }
2319 fprintf (out_file, "\n");
2320 }
2321 }
2322 else
2323 fprintf (out_file,
2324 GTXT ("\nNo Clock Profiling Packets in Experiment: %s\n"),
2325 exp->get_expt_name ());
2326 }
2327 }
2328
2329 // Dump the sync trace events
2330 void
dump_sync(FILE * out_file)2331 DbeView::dump_sync (FILE *out_file)
2332 {
2333 for (int idx = 0; idx < dbeSession->nexps (); idx++)
2334 {
2335 Experiment *exp = dbeSession->get_exp (idx);
2336 VMode view_mode = get_view_mode ();
2337
2338 // Process heap trace date
2339 DataView *packets = get_filtered_events (idx, DATA_SYNCH);
2340 if (packets && packets->getSize () != 0)
2341 {
2342 hrtime_t start = exp->getStartTime ();
2343 fprintf (out_file,
2344 GTXT ("\nTotal Synctrace Packets: %d Experiment: %s\n"),
2345 (int) packets->getSize (), exp->get_expt_name ());
2346
2347 for (long i = 0; i < packets->getSize (); i++)
2348 {
2349 hrtime_t expr_ts = (hrtime_t) packets->getLongValue (PROP_TSTAMP, i);
2350 hrtime_t ts = expr_ts - start;
2351
2352 // get the properties from the packet
2353 uint32_t thrid = (uint32_t) packets->getIntValue (PROP_THRID, i);
2354 uint32_t cpuid = (uint32_t) packets->getIntValue (PROP_CPUID, i);
2355 uint64_t syncobj = (uint64_t) packets->getLongValue (PROP_SOBJ, i);
2356 hrtime_t syncrtime = (uint64_t) packets->getLongValue (PROP_SRQST, i);
2357 hrtime_t syncdelay = expr_ts - syncrtime;
2358
2359 // get the stack IGNORE HIDE
2360 Vector<Histable*> *stack = getStackPCs (view_mode, packets, i);
2361 int stack_size = stack->size ();
2362
2363 // print the packet header with the count of stack frames
2364 fprintf (out_file,
2365 GTXT ("#%6ld: %lld, %3lld.%09lld (%4lld.%09lld) t = %d, cpu = %d, frames = %d\n"),
2366 i, expr_ts, ts / NANOSEC, ts % NANOSEC,
2367 expr_ts / NANOSEC, expr_ts % NANOSEC, thrid,
2368 cpuid, stack_size);
2369 fprintf (stderr,
2370 GTXT (" synchronization object @ 0x%016llx; synchronization delay %3lld.%09lld\n"),
2371 (unsigned long long) syncobj, (long long) (syncdelay / NANOSEC), (long long) (syncdelay % NANOSEC));
2372
2373 // dump the callstack
2374 for (int j = stack_size - 1; j >= 0; j--)
2375 {
2376 Histable *frame = stack->fetch (j);
2377 fprintf (out_file, GTXT (" %s [0x%016llx]\n"), frame->get_name (), (long long) frame);
2378 }
2379 fprintf (out_file, "\n");
2380 }
2381 }
2382 else
2383 fprintf (out_file, GTXT ("\nNo Synctrace Packets in Experiment: %s\n"),
2384 exp->get_expt_name ());
2385 }
2386 }
2387
2388 // Dump the IO trace events
2389 void
dump_iotrace(FILE * out_file)2390 DbeView::dump_iotrace (FILE *out_file)
2391 {
2392 for (int idx = 0; idx < dbeSession->nexps (); idx++)
2393 {
2394 Experiment *exp = dbeSession->get_exp (idx);
2395 VMode view_mode = get_view_mode ();
2396
2397 // Process IO trace date
2398 DataView *packets = get_filtered_events (idx, DATA_IOTRACE);
2399 if (packets && packets->getSize () != 0)
2400 {
2401 hrtime_t start = exp->getStartTime ();
2402 fprintf (out_file,
2403 GTXT ("\nTotal IO trace Packets: %d Experiment: %s\n"),
2404 (int) packets->getSize (), exp->get_expt_name ());
2405 for (long i = 0; i < packets->getSize (); i++)
2406 {
2407 hrtime_t expr_ts = (hrtime_t) packets->getLongValue (PROP_TSTAMP, i);
2408 hrtime_t ts = expr_ts - start;
2409
2410 // get the properties from the packet
2411 uint32_t thrid = (uint32_t) packets->getIntValue (PROP_THRID, i);
2412 uint32_t cpuid = (uint32_t) packets->getIntValue (PROP_CPUID, i);
2413 IOTrace_type iotrtype = (IOTrace_type) packets->getIntValue (PROP_IOTYPE, i);
2414 uint32_t iofd = (uint32_t) packets->getIntValue (PROP_IOFD, i);
2415 uint64_t ionbyte = (uint64_t) packets->getIntValue (PROP_IONBYTE, i);
2416 hrtime_t iorqst = (hrtime_t) packets->getLongValue (PROP_IORQST, i);
2417 uint32_t ioofd = (uint32_t) packets->getIntValue (PROP_IOOFD, i);
2418 FileSystem_type iofstype = (FileSystem_type) packets->getIntValue (PROP_CPUID, i);
2419 int64_t iovfd = (int64_t) packets->getIntValue (PROP_IOVFD, i);
2420
2421 char *fName = NULL;
2422 StringBuilder *sb = (StringBuilder*) packets->getObjValue (PROP_IOFNAME, i);
2423 if (sb != NULL && sb->length () > 0)
2424 fName = sb->toString ();
2425
2426 // get the stack IGNORE HIDE
2427 Vector<Histable*> *stack = getStackPCs (view_mode, packets, i);
2428 int stack_size = stack->size ();
2429 const char *iotrname;
2430 switch (iotrtype)
2431 {
2432 case READ_TRACE:
2433 iotrname = "ReadTrace";
2434 break;
2435 case WRITE_TRACE:
2436 iotrname = "WriteTrace";
2437 break;
2438 case OPEN_TRACE:
2439 iotrname = "OpenTrace";
2440 break;
2441 case CLOSE_TRACE:
2442 iotrname = "CloseTrace";
2443 break;
2444 case OTHERIO_TRACE:
2445 iotrname = "OtherIOTrace";
2446 break;
2447 case READ_TRACE_ERROR:
2448 iotrname = "ReadTraceError";
2449 break;
2450 case WRITE_TRACE_ERROR:
2451 iotrname = "WriteTraceError";
2452 break;
2453 case OPEN_TRACE_ERROR:
2454 iotrname = "OpenTraceError";
2455 break;
2456 case CLOSE_TRACE_ERROR:
2457 iotrname = "CloseTraceError";
2458 break;
2459 case OTHERIO_TRACE_ERROR:
2460 iotrname = "OtherIOTraceError";
2461 break;
2462 default:
2463 iotrname = "UnknownIOTraceType";
2464 break;
2465 }
2466
2467 // print the packet header with the count of stack frames
2468 fprintf (out_file,
2469 GTXT ("#%6ld: %lld, %3lld.%09lld (%4lld.%09lld) t = %d, cpu = %d, frames = %d\n"),
2470 i, expr_ts, ts / NANOSEC, ts % NANOSEC,
2471 expr_ts / NANOSEC, expr_ts % NANOSEC,
2472 thrid, cpuid, stack_size);
2473 fprintf (out_file,
2474 GTXT (" %s: fd = %d, ofd = %d, vfd = %lld, fstype = %d, rqst = %3lld.%09lld\n"),
2475 iotrname, (int) iofd, (int) ioofd, (long long) iovfd,
2476 (int) iofstype, (long long) (iorqst / NANOSEC),
2477 (long long) (iorqst % NANOSEC));
2478 fprintf (out_file, GTXT (" filename = `%s', nbytes = %d\n"),
2479 STR (fName), (int) ionbyte);
2480 free (fName);
2481
2482 // dump the callstack
2483 for (int j = stack_size - 1; j >= 0; j--)
2484 {
2485 Histable *frame = stack->fetch (j);
2486 fprintf (out_file, GTXT (" %s [0x%016llx]\n"), frame->get_name (), (long long) frame);
2487 }
2488 fprintf (out_file, "\n");
2489 }
2490 }
2491 else
2492 fprintf (out_file, GTXT ("\nNo IO trace Packets in Experiment: %s\n"),
2493 exp->get_expt_name ());
2494 }
2495 }
2496
2497 // Dump the HWC Profiling events
2498 void
dump_hwc(FILE * out_file)2499 DbeView::dump_hwc (FILE *out_file)
2500 {
2501 for (int idx = 0; idx < dbeSession->nexps (); idx++)
2502 {
2503 Experiment *exp = dbeSession->get_exp (idx);
2504 VMode view_mode = get_view_mode ();
2505
2506 // Dump HWC profiling data
2507 DataView *packets = get_filtered_events (idx, DATA_HWC);
2508 if (packets && packets->getSize () != 0)
2509 {
2510 hrtime_t start = exp->getStartTime ();
2511 fprintf (out_file,
2512 GTXT ("\nTotal HW Counter Profiling Packets: %d Experiment: %s\n"),
2513 (int) packets->getSize (), exp->get_expt_name ());
2514 for (long i = 0; i < packets->getSize (); i++)
2515 {
2516 const char * hwc_name;
2517 hrtime_t expr_ts = (hrtime_t) packets->getLongValue (PROP_TSTAMP, i);
2518 hrtime_t ts = expr_ts - start;
2519 uint32_t tag = (uint32_t) packets->getIntValue (PROP_HWCTAG, i);
2520 uint32_t thrid = (uint32_t) packets->getIntValue (PROP_THRID, i);
2521 uint32_t cpuid = (uint32_t) packets->getIntValue (PROP_CPUID, i);
2522
2523 // This will work even with a different counter in every packet.
2524 if (tag < 0 || tag >= MAX_HWCOUNT
2525 || !exp->coll_params.hw_aux_name[tag])
2526 // if the packet has an invalid tag, use <invalid> as its name
2527 hwc_name = "<invalid>";
2528 else
2529 hwc_name = exp->coll_params.hw_aux_name[tag];
2530 int64_t mval = packets->getLongValue (PROP_HWCINT, i);
2531 const char *err = HWCVAL_HAS_ERR (mval) ? " $$" : "";
2532
2533 // get the stack IGNORE HIDE
2534 Vector<Histable*> *stack = getStackPCs (view_mode, packets, i);
2535 int stack_size = stack->size ();
2536
2537 // print the packet header with the count of stack frames
2538 fprintf (out_file,
2539 GTXT ("#%6ld: %lld, %3lld.%09lld (%4lld.%09lld) t = %d, cpu = %d, frames = %d\n count = %10lld (0x%016llx), tag = %d (%s)%s\n"),
2540 (long) i, (long long) expr_ts,
2541 (long long) (ts / NANOSEC), (long long) (ts % NANOSEC),
2542 (long long) (expr_ts / NANOSEC), (long long) (expr_ts % NANOSEC),
2543 (int) thrid, (int) cpuid, (int) stack_size,
2544 (long long) (HWCVAL_CLR_ERR (mval)), (long long) mval,
2545 (int) tag, hwc_name, err);
2546
2547 // dump extended HWC packets values
2548 uint64_t va = (uint64_t) packets->getLongValue (PROP_VADDR, i);
2549 uint64_t pa = (uint64_t) packets->getLongValue (PROP_PADDR, i);
2550 fprintf (out_file, GTXT (" va = 0x%016llx, pa = 0x%016llx\n"),
2551 (unsigned long long) va, (unsigned long long) pa);
2552
2553 // dump the callstack
2554 for (int j = stack_size - 1; j >= 0; j--)
2555 {
2556 Histable *frame = stack->fetch (j);
2557 fprintf (out_file, GTXT (" %s [0x%016llx]\n"), frame->get_name (), (long long) frame);
2558 }
2559 fprintf (out_file, "\n");
2560 }
2561 }
2562 else
2563 fprintf (out_file,
2564 GTXT ("\nNo HWC Profiling Packets in Experiment: %s\n"),
2565 exp->get_expt_name ());
2566 }
2567 }
2568
2569 // Dump the Heap events
2570 void
dump_heap(FILE * out_file)2571 DbeView::dump_heap (FILE *out_file)
2572 {
2573 char *heapstrings[] = HEAPTYPE_STATE_USTRINGS;
2574 for (int idx = 0; idx < dbeSession->nexps (); idx++)
2575 {
2576 Experiment *exp = dbeSession->get_exp (idx);
2577 VMode view_mode = get_view_mode ();
2578
2579 // Process heap trace date
2580 DataView *packets = get_filtered_events (idx, DATA_HEAP);
2581 if (packets && packets->getSize () != 0)
2582 {
2583 hrtime_t start = exp->getStartTime ();
2584 fprintf (out_file, GTXT ("\nTotal Heaptrace Packets: %d Experiment: %s\n"),
2585 (int) packets->getSize (), exp->get_expt_name ());
2586 for (long i = 0; i < packets->getSize (); i++)
2587 {
2588 hrtime_t expr_ts = (hrtime_t) packets->getLongValue (PROP_TSTAMP, i);
2589 hrtime_t ts = expr_ts - start;
2590
2591 // get the properties from the packet
2592 uint32_t thrid = (uint32_t) packets->getIntValue (PROP_THRID, i);
2593 uint32_t cpuid = (uint32_t) packets->getIntValue (PROP_CPUID, i);
2594 uint32_t heaptype = (uint32_t) packets->getIntValue (PROP_HTYPE, i);
2595 uint64_t heapsize = (uint64_t) packets->getULongValue (PROP_HSIZE, i);
2596 uint64_t heapvaddr = (uint64_t) packets->getULongValue (PROP_HVADDR, i);
2597 uint64_t heapovaddr = (uint64_t) packets->getULongValue (PROP_HOVADDR, i);
2598 if (heaptype == MUNMAP_TRACE)
2599 {
2600 heapsize = (uint64_t) packets->getULongValue (PROP_HOVADDR, i);
2601 heapovaddr = 0;
2602 }
2603
2604 // get the stack IGNORE HIDE
2605 Vector<Histable*> *stack = getStackPCs (view_mode, packets, i);
2606 int stack_size = stack->size ();
2607
2608 // print the packet header with the count of stack frames
2609 fprintf (out_file,
2610 GTXT ("#%6ld: %lld, %3lld.%09lld (%4lld.%09lld) t = %d, cpu = %d, frames = %d\n"),
2611 i, expr_ts, ts / NANOSEC, ts % NANOSEC,
2612 expr_ts / NANOSEC, expr_ts % NANOSEC,
2613 thrid, cpuid, stack_size);
2614 char *typestr = heapstrings[heaptype];
2615 fprintf (out_file,
2616 GTXT (" type = %d (%s), size = %llu (0x%llx), VADDR = 0x%016llx, OVADDR = 0x%016llx\n"),
2617 (int) heaptype, typestr, (long long unsigned int) heapsize,
2618 (long long unsigned int) heapsize,
2619 (long long unsigned int) heapvaddr,
2620 (long long unsigned int) heapovaddr);
2621
2622 // dump the callstack
2623 for (int j = stack_size - 1; j >= 0; j--)
2624 {
2625 Histable *frame = stack->fetch (j);
2626 fprintf (out_file, GTXT (" %s [0x%016llx]\n"), frame->get_name (), (long long) frame);
2627 }
2628 fprintf (out_file, "\n");
2629 }
2630 }
2631 else
2632 fprintf (out_file, GTXT ("\nNo Heaptrace Packets in Experiment: %s\n"),
2633 exp->get_expt_name ());
2634 }
2635 }
2636
2637 // Dump the Java garbage collector events
2638 void
dump_gc_events(FILE * out_file)2639 DbeView::dump_gc_events (FILE *out_file)
2640 {
2641 for (int idx = 0; idx < dbeSession->nexps (); idx++)
2642 {
2643 Experiment *exp = dbeSession->get_exp (idx);
2644 if (!exp->has_java)
2645 fprintf (out_file,
2646 GTXT ("# No GC events in experiment %d, %s (PID %d, %s)\n"),
2647 idx, exp->get_expt_name (), exp->getPID (), exp->utargname);
2648 else
2649 {
2650 Vector<GCEvent*> *gce = exp->get_gcevents ();
2651 GCEvent *this_event;
2652 int index;
2653 fprintf (out_file,
2654 GTXT ("# %li events in experiment %d: %s (PID %d, %s)\n"),
2655 gce->size (), idx,
2656 exp->get_expt_name (), exp->getPID (), exp->utargname);
2657 fprintf (out_file,
2658 GTXT ("# exp:idx GC_start, GC_end, GC_duration\n"));
2659 Vec_loop (GCEvent*, gce, index, this_event)
2660 {
2661 hrtime_t start = this_event->start - exp->getStartTime ();
2662 hrtime_t end = this_event->end - exp->getStartTime ();
2663 hrtime_t delta = this_event->end - this_event->start;
2664 fprintf (out_file,
2665 "%5d:%d, %3lld.%09lld, %3lld.%09lld, %3lld.%09lld\n",
2666 idx, index,
2667 (long long) (start / NANOSEC), (long long) (start % NANOSEC),
2668 (long long) (end / NANOSEC), (long long) (end % NANOSEC),
2669 (long long) (delta / NANOSEC), (long long) (delta % NANOSEC));
2670 }
2671 }
2672 }
2673 }
2674
2675 void
purge_events(int n)2676 DbeView::purge_events (int n)
2677 {
2678 phaseIdx++;
2679 int lst;
2680 if (n == -1)
2681 lst = filters->size ();
2682 else
2683 lst = n > filters->size () ? filters->size () : n + 1;
2684 for (int i = n == -1 ? 0 : n; i < lst; i++)
2685 {
2686 Vector<DataView*> *expDataViewList = dataViews->fetch (i);
2687 if (expDataViewList)
2688 {
2689 // clear out all the data_ids, but don't change the vector size
2690 for (int data_id = 0; data_id < expDataViewList->size (); ++data_id)
2691 {
2692 delete expDataViewList->fetch (data_id);
2693 expDataViewList->store (data_id, NULL);
2694 }
2695 }
2696 }
2697 filter_active = false;
2698 }
2699
2700
2701 // LIBRARY_VISIBILITY
2702 void
resetAndConstructShowHideStacks()2703 DbeView::resetAndConstructShowHideStacks ()
2704 {
2705 for (int n = 0, nexps = dbeSession->nexps (); n < nexps; n++)
2706 {
2707 Experiment *exp = dbeSession->get_exp (n);
2708 if (exp != NULL)
2709 resetAndConstructShowHideStack (exp);
2710 }
2711 }
2712
2713 // LIBRARY_VISIBILITY
2714 void
resetAndConstructShowHideStack(Experiment * exp)2715 DbeView::resetAndConstructShowHideStack (Experiment *exp)
2716 {
2717 exp->resetShowHideStack ();
2718 /* Vector<DataDescriptor*> *dDscrs = */ exp->getDataDescriptors ();
2719
2720 DataDescriptor *dd;
2721 // Construct show hide stack only for objects which have call stacks
2722 // list below similar to path tree. What about HEAP_SZ? (DBFIXME)
2723 dd = exp->get_raw_events (DATA_CLOCK);
2724 if (dd != NULL)
2725 constructShowHideStack (dd, exp);
2726 dd = exp->get_raw_events (DATA_SYNCH);
2727 if (dd != NULL)
2728 constructShowHideStack (dd, exp);
2729 dd = exp->get_raw_events (DATA_IOTRACE);
2730 if (dd != NULL)
2731 constructShowHideStack (dd, exp);
2732 dd = exp->get_raw_events (DATA_HWC);
2733 if (dd != NULL)
2734 constructShowHideStack (dd, exp);
2735 dd = exp->get_raw_events (DATA_HEAP);
2736 if (dd != NULL)
2737 constructShowHideStack (dd, exp);
2738 dd = exp->get_raw_events (DATA_RACE);
2739 if (dd != NULL)
2740 constructShowHideStack (dd, exp);
2741 dd = exp->get_raw_events (DATA_DLCK);
2742 if (dd != NULL)
2743 constructShowHideStack (dd, exp);
2744 }
2745
2746 // LIBRARY_VISIBILITY
2747 void
constructShowHideStack(DataDescriptor * dDscr,Experiment * exp)2748 DbeView::constructShowHideStack (DataDescriptor *dDscr, Experiment *exp)
2749 {
2750 if (dDscr == NULL)
2751 return;
2752 int stack_prop = PROP_NONE;
2753 VMode view_mode = get_view_mode ();
2754 if (view_mode == VMODE_MACHINE)
2755 stack_prop = PROP_MSTACK;
2756 else if (view_mode == VMODE_EXPERT)
2757 stack_prop = PROP_XSTACK;
2758 else if (view_mode == VMODE_USER)
2759 stack_prop = PROP_USTACK;
2760
2761 for (long j = 0, sz = dDscr->getSize (); j < sz; j++)
2762 {
2763 void *stackId = dDscr->getObjValue (stack_prop, j);
2764 Vector<Histable*> *stack = (Vector<Histable*>*)CallStack::getStackPCs (stackId);
2765 int stack_size = stack->size ();
2766 bool hide_on = false;
2767 LoadObject *hide_lo = NULL;
2768 Histable *last_addr = NULL;
2769 Histable *api_addr = NULL;
2770 DbeInstr *h_instr;
2771
2772 Vector<Histable*> *hidepcs = new Vector<Histable*>;
2773 for (int i = stack_size - 1; i >= 0; i--)
2774 {
2775 bool leaf = (i == 0);
2776 Histable *cur_addr = stack->fetch (i);
2777 Function *func = (Function*) cur_addr->convertto (Histable::FUNCTION);
2778 if (func != NULL)
2779 {
2780 Module *mod = func->module;
2781 LoadObject *lo = mod->loadobject;
2782 int segx = lo->seg_idx;
2783 if ((get_lo_expand (segx) == LIBEX_API) && (i != (stack_size - 1)))
2784 {
2785 leaf = true;
2786 api_addr = cur_addr;
2787 }
2788 else if (get_lo_expand (segx) == LIBEX_HIDE)
2789 {
2790 if (hide_on)
2791 {
2792 if (lo != hide_lo)
2793 {
2794 // Changed hidden loadobject
2795 if (last_addr != NULL)
2796 {
2797 h_instr = hide_lo->get_hide_instr ((DbeInstr*) last_addr);
2798 hidepcs->append (h_instr);
2799 last_addr = cur_addr;
2800 }
2801 hide_lo = lo;
2802 }
2803 }
2804 else
2805 {
2806 // Start hide
2807 hide_on = true;
2808 last_addr = cur_addr;
2809 hide_lo = lo;
2810 }
2811 if (!leaf)
2812 continue;
2813 }
2814 else
2815 {
2816 hide_on = false;
2817 if (last_addr != NULL)
2818 {
2819 h_instr = hide_lo->get_hide_instr ((DbeInstr*) last_addr);
2820 hidepcs->append (h_instr);
2821 last_addr = NULL;
2822 }
2823 }
2824 }
2825 if (last_addr != NULL && leaf) cur_addr = last_addr;
2826 if (hide_on)
2827 {
2828 h_instr = hide_lo->get_hide_instr ((DbeInstr*) cur_addr);
2829 hidepcs->append (h_instr);
2830 if (api_addr != NULL)
2831 hidepcs->append (api_addr);
2832 }
2833 else
2834 hidepcs->append (cur_addr);
2835 if (leaf)
2836 break;
2837 }
2838 for (int i = 0, k = hidepcs->size () - 1; i < k; ++i, --k)
2839 hidepcs->swap (i, k);
2840
2841 CallStack *cstkSH = exp->callTreeShowHide ();
2842 CallStackNode *hstack = (CallStackNode *) cstkSH->add_stack (hidepcs);
2843 dDscr->setObjValue (PROP_HSTACK, j, hstack);
2844 CallStack::setHideStack (stackId, hstack);
2845 delete hidepcs;
2846 delete stack;
2847 }
2848 }
2849
2850 DataView *
get_filtered_events(int idx,int data_id)2851 DbeView::get_filtered_events (int idx, int data_id)
2852 {
2853 if (idx < 0 || idx >= dataViews->size ())
2854 return NULL;
2855 Vector<DataView*> *expDataViewList = dataViews->fetch (idx);
2856 if (!expDataViewList)
2857 return NULL; // Weird
2858
2859 DataView *dview = expDataViewList->fetch (data_id);
2860 Experiment *exp = dbeSession->get_exp (idx);
2861 if (dview)
2862 {
2863 // if show-hide is on force a reconstruction of hide stacks
2864 // LIBRARY_VISIBILITY
2865 if (!showAll && (showHideChanged || newViewMode))
2866 {
2867 DataDescriptor *dDscr = exp->get_raw_events (data_id);
2868 constructShowHideStack (dDscr, exp);
2869 }
2870 return dview;
2871 }
2872
2873 int orig_data_id = data_id;
2874 data_id = exp->base_data_id (data_id);
2875 if (orig_data_id != data_id)
2876 // orig_data_id is a derived DataView. Get the master DataView:
2877 dview = expDataViewList->fetch (data_id);
2878 if (dview == NULL)
2879 {
2880 Expression *saved = cur_filter_expr;
2881 if (!adjust_filter (exp))
2882 return NULL;
2883
2884 DataDescriptor *dDscr = exp->get_raw_events (data_id);
2885 if (!showAll && (showHideChanged || newViewMode))
2886 constructShowHideStack (dDscr, exp);
2887
2888 Emsg *m = exp->fetch_warnings ();
2889 if (m != NULL)
2890 this->warning_msg = m->get_msg ();
2891
2892 if (dDscr != NULL)
2893 {
2894 FilterExp *filter = get_FilterExp (exp);
2895 dview = dDscr->createView ();
2896 dview->setFilter (filter);
2897 if (dview->getSize () < dDscr->getSize ())
2898 filter_active = true;
2899 }
2900 expDataViewList->store (data_id, dview);
2901
2902 if (saved)
2903 {
2904 delete cur_filter_expr;
2905 cur_filter_expr = saved;
2906 }
2907 }
2908 if (orig_data_id != data_id)
2909 {
2910 // create the derived DataView:
2911 dview = exp->create_derived_data_view (orig_data_id, dview);
2912 expDataViewList->store (orig_data_id, dview);
2913 }
2914 return dview;
2915 }
2916
2917 DataView *
get_filtered_events(int idx,int data_id,const int sortprops[],int sortprop_count)2918 DbeView::get_filtered_events (int idx, int data_id,
2919 const int sortprops[], int sortprop_count)
2920 {
2921 DataView *packets = get_filtered_events (idx, data_id);
2922 if (packets)
2923 packets->sort (sortprops, sortprop_count);
2924 return packets;
2925 }
2926
2927 bool
adjust_filter(Experiment * exp)2928 DbeView::adjust_filter (Experiment *exp)
2929 {
2930 if (cur_filter_expr)
2931 {
2932 Expression::Context ctx (this, exp);
2933 resetFilterHideMode ();
2934 Expression *fltr = cur_filter_expr->pEval (&ctx);
2935 if (fltr->complete ())
2936 { // Filter is a constant
2937 if (fltr->eval (NULL) == 0)
2938 return false;
2939 delete fltr;
2940 fltr = NULL;
2941 }
2942 cur_filter_expr = fltr;
2943 }
2944 return true;
2945 }
2946
2947 // Moved from Cacheable.cc:
2948 char *
status_str(DbeView_status status)2949 DbeView::status_str (DbeView_status status)
2950 {
2951 switch (status)
2952 {
2953 case DBEVIEW_SUCCESS:
2954 return NULL;
2955 case DBEVIEW_NO_DATA:
2956 return dbe_strdup (GTXT ("Data not available for this filter selection"));
2957 case DBEVIEW_IO_ERROR:
2958 return dbe_strdup (GTXT ("Unable to open file"));
2959 case DBEVIEW_BAD_DATA:
2960 return dbe_strdup (GTXT ("Data corrupted"));
2961 case DBEVIEW_BAD_SYMBOL_DATA:
2962 return dbe_strdup (GTXT ("Functions/Modules information corrupted"));
2963 case DBEVIEW_NO_SEL_OBJ:
2964 return dbe_strdup (GTXT ("No selected object, bring up Functions Tab"));
2965 }
2966 return NULL;
2967 }
2968
2969 Histable *
set_sel_obj(Histable * obj)2970 DbeView::set_sel_obj (Histable *obj)
2971 {
2972 if (obj)
2973 {
2974 switch (obj->get_type ())
2975 {
2976 case Histable::INSTR:
2977 lastSelInstr = (DbeInstr *) obj;
2978 lastSelFunc = lastSelInstr->func;
2979 this->sel_binctx = lastSelFunc;
2980 break;
2981 case Histable::FUNCTION:
2982 if (lastSelInstr && lastSelInstr->func != obj)
2983 lastSelInstr = NULL;
2984 lastSelFunc = (Function *) obj;
2985 break;
2986 case Histable::LINE:
2987 {
2988 DbeLine *dbeLine = (DbeLine *) obj;
2989 if (dbeLine->func)
2990 {
2991 // remember previous DbeInstr and DbeFunc
2992 lastSelFunc = dbeLine->func;
2993 if (lastSelInstr && lastSelInstr->func != lastSelFunc)
2994 lastSelInstr = NULL;
2995 this->sel_binctx = lastSelFunc;
2996 }
2997 else
2998 this->sel_binctx = dbeLine->convertto (Histable::FUNCTION);
2999 break;
3000 }
3001 case Histable::MODULE:
3002 case Histable::LOADOBJECT:
3003 case Histable::EADDR:
3004 case Histable::MEMOBJ:
3005 case Histable::INDEXOBJ:
3006 case Histable::PAGE:
3007 case Histable::DOBJECT:
3008 case Histable::SOURCEFILE:
3009 case Histable::IOACTFILE:
3010 case Histable::IOACTVFD:
3011 case Histable::IOCALLSTACK:
3012 case Histable::HEAPCALLSTACK:
3013 case Histable::EXPERIMENT:
3014 case Histable::OTHER:
3015 break;
3016 }
3017 }
3018 sel_obj = obj;
3019 Dprintf (DEBUG_DBE, NTXT ("### set_sel_obj: DbeView.cc:%d obj %s\n"),
3020 __LINE__, obj ? obj->dump () : "NULL");
3021 Dprintf (DEBUG_DBE, NTXT ("### set_sel_obj: DbeView.cc:%d sel_obj %s\n"),
3022 __LINE__, sel_obj ? sel_obj->dump () : "NULL");
3023 Dprintf (DEBUG_DBE, NTXT ("### set_sel_obj: DbeView.cc:%d lastSelFunc %s\n"),
3024 __LINE__, lastSelFunc ? lastSelFunc->dump () : "NULL");
3025 Dprintf (DEBUG_DBE, NTXT ("### set_sel_obj: DbeView.cc:%d lastSelInstr %s\n"),
3026 __LINE__, lastSelInstr ? lastSelInstr->dump () : "NULL");
3027 return sel_obj;
3028 }
3029
3030 DbeInstr *
convert_line_to_instr(DbeLine * dbeLine)3031 DbeView::convert_line_to_instr (DbeLine *dbeLine)
3032 {
3033 Dprintf (DEBUG_DBE, "### convert_line_to_instr DbeView::%d dbeLine=%s\n", __LINE__, dbeLine->dump ());
3034 Function *func = convert_line_to_func (dbeLine);
3035 if (func)
3036 {
3037 Dprintf (DEBUG_DBE, "### convert_line_to_instr DbeView::%d func=%s\n", __LINE__, func->dump ());
3038 DbeInstr *dbeInstr = func->mapLineToPc (dbeLine);
3039 Dprintf (DEBUG_DBE && dbeInstr, "### convert_line_to_instr DbeView::%d dbeInstr=%s\n", __LINE__, dbeInstr->dump ());
3040 return dbeInstr;
3041 }
3042 Dprintf (DEBUG_DBE && lastSelInstr, "### convert_line_to_instr DbeView::%d lastSelInstr=%s\n", __LINE__, lastSelInstr->dump ());
3043 return lastSelInstr;
3044 }
3045
3046 DbeInstr *
convert_func_to_instr(Function * func)3047 DbeView::convert_func_to_instr (Function *func)
3048 {
3049 return (lastSelInstr && lastSelInstr->func == func) ?
3050 lastSelInstr : (DbeInstr *) func->convertto (Histable::INSTR);
3051 }
3052
3053 Function *
convert_line_to_func(DbeLine * dbeLine)3054 DbeView::convert_line_to_func (DbeLine *dbeLine)
3055 {
3056 Function *func = dbeLine->func;
3057 if (func)
3058 return func;
3059 if (lastSelFunc != NULL)
3060 // Can be mapped to the same function ?
3061 for (DbeLine *dl = dbeLine->dbeline_base; dl; dl = dl->dbeline_func_next)
3062 if (dl->func == lastSelFunc)
3063 return lastSelFunc;
3064
3065 PathTree *pathTree = NULL;
3066 Function *firstFunc = NULL;
3067 for (DbeLine *dl = dbeLine->dbeline_base; dl; dl = dl->dbeline_func_next)
3068 {
3069 // Find a first function with non-zero metrics
3070 if (dl->func)
3071 {
3072 if (pathTree == NULL)
3073 pathTree = get_path_tree ();
3074 if (pathTree->get_func_nodeidx (dl->func))
3075 return dl->func;
3076 if (firstFunc == NULL)
3077 firstFunc = dl->func;
3078 }
3079 }
3080 // Take a first function
3081 return firstFunc;
3082 }
3083
3084 Histable *
get_sel_obj(Histable::Type type)3085 DbeView::get_sel_obj (Histable::Type type)
3086 {
3087 Histable *lastSelObj = sel_obj;
3088 Dprintf (DEBUG_DBE, NTXT ("### get_sel_obj: DbeView.cc:%d type=%d sel_obj %s\n"),
3089 __LINE__, type, lastSelObj ? lastSelObj->dump () : "NULL");
3090 if (lastSelObj == NULL)
3091 return NULL;
3092 switch (type)
3093 {
3094 case Histable::INSTR:
3095 if (!showAll)
3096 {
3097 // DBFIXME LIBRARY VISIBILITY
3098 // hack to get to the hide mode object for PCs when filtering
3099 // with a PC in timeline
3100 if (lastSelObj->get_type () == Histable::INSTR)
3101 {
3102 Function *func = (Function*) (lastSelObj->convertto (Histable::FUNCTION));
3103 LoadObject *lo = func->module->loadobject;
3104 if (get_lo_expand (lo->seg_idx) == LIBEX_HIDE)
3105 return lo->get_hide_function ();
3106 }
3107 }
3108 if (lastSelObj->get_type () == Histable::LINE)
3109 return convert_line_to_instr ((DbeLine*) lastSelObj);
3110 else if (lastSelObj->get_type () == Histable::FUNCTION)
3111 return convert_func_to_instr ((Function *) lastSelObj);
3112 return lastSelObj->convertto (type);
3113 case Histable::FUNCTION:
3114 if (lastSelObj->get_type () == Histable::LINE)
3115 {
3116 Function *func = convert_line_to_func ((DbeLine*) lastSelObj);
3117 if (func)
3118 return func;
3119 return NULL;
3120 }
3121 return lastSelObj->convertto (type);
3122 case Histable::LINE:
3123 default:
3124 return lastSelObj->convertto (type);
3125 }
3126 }
3127