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