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 47DbeView::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 133DbeView::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 213DbeView::~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 254void 255DbeView::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 273bool 274DbeView::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 286bool 287DbeView::set_libdefaults () 288{ 289 bool changed = settings->set_libdefaults (); 290 if (changed == true) 291 update_lo_expands (); 292 return changed; 293} 294 295void 296DbeView::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 312enum LibExpand 313DbeView::get_lo_expand (int idx) 314{ 315 if (idx < lo_expands->size ()) 316 return lo_expands->get (idx); 317 return LIBEX_SHOW; 318} 319 320bool 321DbeView::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 344void 345DbeView::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 376void 377DbeView::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 484Vector<BaseMetric*> * 485DbeView::get_all_reg_metrics () 486{ 487 Vector<BaseMetric*> *mlist = dbeSession->get_all_reg_metrics (); 488 return mlist; 489} 490 491BaseMetric * 492DbeView::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 498Metric * 499DbeView::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 514MetricList * 515DbeView::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; 536MetricList * 537DbeView::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 569MetricList * 570DbeView::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 602void 603DbeView::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 617bool 618DbeView::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 625void 626DbeView::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 668void 669DbeView::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 694void 695DbeView::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 740void 741DbeView::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 759void 760DbeView::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 797void 798DbeView::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 814bool 815DbeView::get_exp_enable (int n) 816{ 817 return filters ? filters->fetch (n)->get_enabled () : true; 818} 819 820void 821DbeView::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 832void 833DbeView::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 898void 899DbeView::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 979MetricList * 980DbeView::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 995void 996DbeView::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 1037char * 1038DbeView::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) 1116char * 1117DbeView::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) 1144void 1145DbeView::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 1223void 1224DbeView::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 1284char * 1285DbeView::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) 1292char * 1293DbeView::getSortCmd (MetricType mtype) 1294{ 1295 MetricList *mlist = get_metric_list (mtype); 1296 return mlist->get_sort_cmd (); 1297} 1298 1299int 1300DbeView::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 1360MetricList * 1361DbeView::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 1405Hist_data * 1406DbeView::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 1535Histable * 1536DbeView::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. 1565Hist_data * 1566DbeView::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 1582Hist_data * 1583DbeView::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 1729char * 1730DbeView::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 1738MemorySpace * 1739DbeView::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 1750MemorySpace * 1751DbeView::addMemorySpace (int subtype) 1752{ 1753 MemorySpace *ms = new MemorySpace (this, subtype); 1754 memspaces->append (ms); 1755 return ms; 1756} 1757 1758Hist_data * 1759DbeView::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 1766void 1767DbeView::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 1779Histable * 1780DbeView::get_indxobj_sel (int subtype) 1781{ 1782 return sel_idxobj->fetch (subtype); 1783} 1784 1785void 1786DbeView::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 1795Histable * 1796DbeView::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 1833Histable * 1834DbeView::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 1854CStack_data * 1855DbeView::get_cstack_data (MetricList *mlist) 1856{ 1857 return ptree->get_cstack_data (mlist); 1858} 1859 1860Stats_data * 1861DbeView::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 1869Ovw_data * 1870DbeView::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 1882char * 1883DbeView::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 1934FilterExp * 1935DbeView::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 1943char * 1944DbeView::get_filter () 1945{ 1946 return dbe_strdup (cur_filter_str); 1947} 1948 1949FilterSet * 1950DbeView::get_filter_set (int n) 1951{ 1952 fflush (stderr); 1953 if (n >= filters->size ()) 1954 return NULL; 1955 return ( filters->fetch (n)); 1956} 1957 1958Vector<FilterNumeric*> * 1959DbeView::get_all_filters (int nexp) 1960{ 1961 FilterSet *fs = get_filter_set (nexp); 1962 return fs ? fs->get_all_filters () : NULL; 1963} 1964 1965FilterNumeric * 1966DbeView::get_FilterNumeric (int nexp, int idx) 1967{ 1968 FilterSet *fs = get_filter_set (nexp); 1969 return fs ? fs->get_filter (idx) : NULL; 1970} 1971 1972void 1973DbeView::backtrack_filter() 1974{ 1975 if (prev_filter_str != NULL) 1976 set_filter(prev_filter_str); 1977 else set_filter("1"); // reset 1978 1979} 1980 1981void 1982DbeView::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 1999bool 2000DbeView::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 2027static void 2028append_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 2050char * 2051DbeView::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 2104bool 2105DbeView::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 2189void 2190DbeView::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 2209Cmd_status 2210DbeView::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 2219Cmd_status 2220DbeView::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 2231char * 2232DbeView::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 2253void 2254DbeView::dump_nodes (FILE *outfile) 2255{ 2256 FILE *f = (outfile == NULL ? stderr : outfile); 2257 ptree->print (f); 2258} 2259 2260// Dump the clock profile events 2261void 2262DbeView::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 2330void 2331DbeView::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 2389void 2390DbeView::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 2498void 2499DbeView::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 2570void 2571DbeView::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 2638void 2639DbeView::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 2675void 2676DbeView::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 2702void 2703DbeView::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 2714void 2715DbeView::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 2747void 2748DbeView::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 2850DataView * 2851DbeView::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 2917DataView * 2918DbeView::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 2927bool 2928DbeView::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: 2948char * 2949DbeView::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 2969Histable * 2970DbeView::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 3030DbeInstr * 3031DbeView::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 3046DbeInstr * 3047DbeView::convert_func_to_instr (Function *func) 3048{ 3049 return (lastSelInstr && lastSelInstr->func == func) ? 3050 lastSelInstr : (DbeInstr *) func->convertto (Histable::INSTR); 3051} 3052 3053Function * 3054DbeView::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 3084Histable * 3085DbeView::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