]> Git Repo - binutils.git/blob - gprofng/src/DbeView.cc
Automatic date update in version.in
[binutils.git] / gprofng / src / DbeView.cc
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
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
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
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
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
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
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
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
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
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
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
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*> *
485 DbeView::get_all_reg_metrics ()
486 {
487   Vector<BaseMetric*> *mlist = dbeSession->get_all_reg_metrics ();
488   return mlist;
489 }
490
491 BaseMetric *
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 *
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 *
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 *
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 *
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
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
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
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
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
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
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
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
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
815 DbeView::get_exp_enable (int n)
816 {
817   return filters ? filters->fetch (n)->get_enabled () : true;
818 }
819
820 void
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
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
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 *
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
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 *
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 *
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
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
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 *
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 *
1293 DbeView::getSortCmd (MetricType mtype)
1294 {
1295   MetricList *mlist = get_metric_list (mtype);
1296   return mlist->get_sort_cmd ();
1297 }
1298
1299 int
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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
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 *
1780 DbeView::get_indxobj_sel (int subtype)
1781 {
1782   return sel_idxobj->fetch (subtype);
1783 }
1784
1785 void
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 *
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 *
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 *
1855 DbeView::get_cstack_data (MetricList *mlist)
1856 {
1857   return ptree->get_cstack_data (mlist);
1858 }
1859
1860 Stats_data *
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 *
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 *
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 *
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 *
1944 DbeView::get_filter ()
1945 {
1946   return dbe_strdup (cur_filter_str);
1947 }
1948
1949 FilterSet *
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*> *
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 *
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
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
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
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
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 *
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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 *
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 *
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
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 *
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 *
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 *
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 *
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 *
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 *
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 }
This page took 0.195652 seconds and 4 git commands to generate.