Wolfgang Thallergcc16 merge934c3885 months agoHistory
1889 lines · 44.3 KB · C++
RawDownload
/* Copyright (C) 2021-2026 Free Software Foundation, Inc.   Contributed by Oracle.    This file is part of GNU Binutils.    This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 3, or (at your option)   any later version.    This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.    You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, 51 Franklin Street - Fifth Floor, Boston,   MA 02110-1301, USA.  */ #include "config.h"#include <assert.h> #include "util.h"#include "DefaultMap.h"#include "DbeSession.h"#include "Experiment.h"#include "DataObject.h"#include "Function.h"#include "Hist_data.h"#include "Histable.h"#include "MemObject.h"#include "IndexObject.h"#include "MetricList.h"#include "Metric.h"#include "Module.h"#include "LoadObject.h"#include "Settings.h"#include "StringBuilder.h"#include "ExpGroup.h"#include "PathTree.h"#include "DbeView.h"#include "FileData.h" Hist_data::HistItem::HistItem (long n){  obj = NULL;  type = 0;  size = n;  value = new TValue[n];  memset (value, 0, sizeof (TValue) * n);} Hist_data::HistItem::~HistItem (){  for (long i = 0; i < size; i++)    if (value[i].tag == VT_LABEL)      free (value[i].l);  delete[] value;} longHist_data::size (){  // If the data values have not been computed, do so  // Return the total number of items  return hist_items->size ();} Hist_data::HistItem *Hist_data::fetch (long index){  return (index < VecSize (hist_items)) ? hist_items->get (index) : NULL;} intHist_data::sort_compare (HistItem *hi_1, HistItem *hi_2, Sort_type stype,			 long ind, Hist_data *hdata){  // Sort the data depending upon order and type  int result = 0;  Histable::Type type = hi_1->obj->get_type ();  if (stype == ALPHA)    {      if (type != Histable::MEMOBJ && type != Histable::INDEXOBJ	      && type != Histable::IOACTVFD && type != Histable::IOACTFILE	      && type != Histable::IOCALLSTACK)	{	  char *nm1 = hi_1->obj->get_name ();	  char *nm2 = hi_2->obj->get_name ();	  if (nm1 != NULL && nm2 != NULL)	    result = strcoll (nm1, nm2);	}      else if (type == Histable::IOCALLSTACK || type == Histable::IOACTVFD	       || type == Histable::IOACTFILE)	{	  uint64_t idx1, idx2;	  idx1 = ((FileData *) (hi_1->obj))->get_index ();	  idx2 = ((FileData *) (hi_2->obj))->get_index ();	  if (idx1 < idx2)	    result = -1;	  else if (idx1 > idx2)	    result = 1;	  else	    result = 0;	}      else	{	  // for memory and index objects, "alphabetic" is really by index	  // <Total> has index -2, and always comes first	  // <Unknown> has index -1, and always comes second.	  uint64_t i1, i2;	  bool needsStringCompare = false;	  if (type == Histable::MEMOBJ)	    {	      i1 = ((MemObj *) (hi_1->obj))->get_index ();	      i2 = ((MemObj *) (hi_2->obj))->get_index ();	    }	  else if (type == Histable::INDEXOBJ)	    {	      i1 = ((IndexObject *) (hi_1->obj))->get_index ();	      i2 = ((IndexObject *) (hi_2->obj))->get_index ();	      needsStringCompare =		      ((IndexObject *) (hi_1->obj))->requires_string_sort ();	    }	  else	    abort ();	  if (i1 == (uint64_t) - 2)	    result = -1;	  else if (i2 == (uint64_t) - 2)	    result = 1;	  else if (i1 == (uint64_t) - 1)	    result = -1;	  else if (i2 == (uint64_t) - 1)	    result = 1;	  else if (needsStringCompare)	    {	      char *nm1 = hi_1->obj->get_name ();	      char *nm2 = hi_2->obj->get_name ();	      if (nm1 != NULL && nm2 != NULL)		{		  char nm1_lead = nm1[0];		  char nm2_lead = nm2[0];		  // put "(unknown)" and friends at end of list		  if (nm1_lead == '(' && nm1_lead != nm2_lead)		    result = 1;		  else if (nm2_lead == '(' && nm1_lead != nm2_lead)		    result = -1;		  else		    result = strcoll (nm1, nm2);		}	    }	  if (result == 0)	    { // matches, resolve by index	      if (i1 < i2)		result = -1;	      else if (i1 > i2)		result = 1;	    }	}    }  else if (stype == AUX)    {      switch (type)	{	case Histable::INSTR:	  {	    DbeInstr *instr1 = (DbeInstr*) hi_1->obj;	    DbeInstr *instr2 = (DbeInstr*) hi_2->obj;	    result = instr1 ? instr1->pc_cmp (instr2) : instr2 ? 1 : 0;	    break;	  }	case Histable::LINE:	  {	    DbeLine *dbl1 = (DbeLine*) hi_1->obj;	    DbeLine *dbl2 = (DbeLine*) hi_2->obj;	    result = dbl1->line_cmp (dbl2);	  }	  break;	default:	  assert (0);	}    }  else if (stype == VALUE)    {      Metric *m = hdata->get_metric_list ()->get (ind);      if ((m->get_visbits () & (VAL_DELTA | VAL_RATIO)) != 0)	{	  TValue v1, v2;	  int first_ind = hdata->hist_metrics[ind].indFirstExp;	  if ((m->get_visbits () & VAL_DELTA) != 0)	    {	      v1.make_delta (hi_1->value + ind, hi_1->value + first_ind);	      v2.make_delta (hi_2->value + ind, hi_2->value + first_ind);	    }	  else	    {	      v1.make_ratio (hi_1->value + ind, hi_1->value + first_ind);	      v2.make_ratio (hi_2->value + ind, hi_2->value + first_ind);	    }	  result = v1.compare (&v2);	}      else	result = hi_1->value[ind].compare (hi_2->value + ind);    }  return result;} intHist_data::sort_compare_all (const void *a, const void *b, const void *arg){  HistItem *hi_1 = *((HistItem **) a);  HistItem *hi_2 = *((HistItem **) b);   Hist_data *hdata = (Hist_data*) arg;  int result = sort_compare (hi_1, hi_2, hdata->sort_type, hdata->sort_ind, hdata);  if (hdata->sort_order == DESCEND)    result = -result;   // Use the name as the 2d sort key (always ASCEND)  // except for MemoryObjects and  IndexObjects, where the index is used  // For the Alphabetic sort  if (result == 0)    {      result = sort_compare (hi_1, hi_2, ALPHA, 0, NULL);      if (result == 0)	{	  for (long i = 0, sz = hdata->metrics->size (); i < sz; i++)	    {	      Metric *m = hdata->metrics->get (i);	      if (m->get_type () != Metric::ONAME)		{		  result = sort_compare (hi_1, hi_2, VALUE, i, hdata);		  if (result != 0)		    {		      if (hdata->sort_order == DESCEND)			result = -result;		      break;		    }		}	    }	}    }   // Use the address as the 3d sort key  // ( FUNCTION only, always ASCEND )  if (result == 0 && hi_1->obj->get_type () == Histable::FUNCTION)    {      Function *f1 = (Function*) hi_1->obj;      Function *f2 = (Function*) hi_2->obj;      if (f1->get_addr () < f2->get_addr ())	result = -1;      else if (f1->get_addr () > f2->get_addr ())	result = 1;    }   // Use the Histable id (ID of function, line, etc.) as the 4th sort key  // Note that IDs are not guaranteed to be stable,  if (result == 0)    {      if (hi_1->obj->id < hi_2->obj->id)	result = -1;      else if (hi_1->obj->id > hi_2->obj->id)	result = 1;    }   if (result == 0)    return result; // shouldn't happen in most cases; line allows for breakpoint  if (hdata->rev_sort)    result = -result;  return result;} intHist_data::sort_compare_dlayout (const void *a, const void *b, const void *arg){  assert ((a != (const void *) NULL));  assert ((b != (const void *) NULL));  HistItem *hi_1 = *((HistItem **) a);  HistItem *hi_2 = *((HistItem **) b);  DataObject * dobj1 = (DataObject *) (hi_1->obj);  DataObject * dobj2 = (DataObject *) (hi_2->obj);  DataObject * parent1 = dobj1->parent;  DataObject * parent2 = dobj2->parent;   Hist_data *hdata = (Hist_data*) arg;   // are the two items members of the same object?  if (parent1 == parent2)    {      // yes      if (parent1)	{	  // and they have real parents...	  if (parent1->get_typename ())	    { // element	      // use dobj1/dobj2 offset for sorting	      uint64_t off1 = dobj1->get_offset ();	      uint64_t off2 = dobj2->get_offset ();	      if (off1 < off2)		return -1;	      if (off1 > off2)		return 1;	      return 0;	    }	}    }  else    { // parents differ      if (parent1)	{	  if (parent1 == dobj2)	    // sorting an object and its parent: parent always first	    return 1;	  dobj1 = parent1;	}      if (parent2)	{	  if (parent2 == dobj1)	    return -1;	  dobj2 = parent2;	}    }  //  Either two unknowns, or two scalars, or two parents  hi_1 = hdata->hi_map->get (dobj1);  hi_2 = hdata->hi_map->get (dobj2);  return sort_compare_all ((const void*) &hi_1, (const void*) &hi_2, hdata);} Hist_data::Hist_data (MetricList *_metrics, Histable::Type _type,		      Hist_data::Mode _mode, bool _viewowned){  hist_items = new Vector<HistItem*>;  metrics = _metrics;  nmetrics = metrics->get_items ()->size ();  type = _type;  mode = _mode;  gprof_item = new_hist_item (NULL);  viewowned = _viewowned;  sort_ind = -1;  rev_sort = false;   Histable *tobj = new Other;  tobj->name = dbe_strdup (NTXT ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));  minimum = new_hist_item (tobj);   tobj = new Other;  tobj->name = dbe_strdup (NTXT (""));  maximum = new_hist_item (tobj);   tobj = new Other;  tobj->name = dbe_strdup (NTXT ("xxxxxxxxxxxxxxxxxxxxxx"));  maximum_inc = new_hist_item (tobj);   tobj = new Other;  tobj->name = dbe_strdup (NTXT ("<Total>"));  total = new_hist_item (tobj);   tobj = new Other;  tobj->name = dbe_strdup (NTXT ("XXXX Threshold XXXX"));  threshold = new_hist_item (tobj);   hi_map = new HashMap<Histable*, HistItem*>;  callsite_mark = new DefaultMap<Histable*, int>;  hist_metrics = new Metric::HistMetric[metrics->size ()];  for (long i = 0, sz = metrics->size (); i < sz; i++)    {      Metric::HistMetric *h = hist_metrics + i;      h->init ();      Metric *m = metrics->get (i);      if (0 != (m->get_visbits () & (VAL_DELTA | VAL_RATIO)))	h->indFirstExp =	      metrics->get_listorder (m->get_cmd (),				      m->get_subtype (), "EXPGRID==1");      if (m->is_tvisible () && m->get_type () == BaseMetric::HWCNTR	  && m->get_dependent_bm ())	h->indTimeVal =	      metrics->get_listorder (m->get_dependent_bm ()->get_cmd (),				      m->get_subtype (), m->get_expr_spec ());    }  status = NO_DATA;} Hist_data::~Hist_data (){  delete[] hist_metrics;  if (hist_items)    {      hist_items->destroy ();      delete hist_items;      hist_items = NULL;    }  if (gprof_item)    {      delete gprof_item;      gprof_item = NULL;    }  if (maximum)    {      delete maximum->obj;      delete maximum;      maximum = NULL;    }  if (maximum_inc)    {      delete maximum_inc->obj;      delete maximum_inc;      maximum_inc = NULL;    }  if (minimum)    {      delete minimum->obj;      delete minimum;      minimum = NULL;    }  if (total)    {      delete total->obj;      delete total;      total = NULL;    }  if (threshold)    {      delete threshold->obj;      delete threshold;      threshold = NULL;    }  delete metrics;  delete hi_map;  delete callsite_mark;} voidHist_data::dump (char *msg, FILE *f){  fprintf (f, "   Hist_data dump:  %s\n", msg);  fprintf (f, "      %d=%d metrics\n", (int) nmetrics, (int) metrics->size ());  for (int i = 0; i < nmetrics; i++)    {      Metric *m = metrics->get_items ()->fetch (i);      char *s = m->get_expr_spec ();      fprintf (f, "          %4d %15s %4d %15s\n", i, m->get_mcmd (0),	       m->get_id (), s ? s : "(NULL)");    }   fprintf (f, NTXT ("      HistItem listing\n"));  int n = hist_items->size ();  for (int j = -1; j < n; j++)    {      HistItem *hi;      if (j < 0)	{	  hi = total;	  fprintf (f, NTXT ("                         total"));	}      else	{	  hi = hist_items->fetch (j);	  fprintf (f, NTXT ("%30s"), hi->obj->get_name ());	}      for (int i = 0; i < nmetrics; i++)	{	  char *stmp = hi->value[i].l;	  switch (hi->value[i].tag)	    {	    case VT_SHORT: fprintf (f, NTXT (" %d"), hi->value[i].s);	      break;	    case VT_INT: fprintf (f, NTXT (" %d"), hi->value[i].i);	      break;	    case VT_LLONG: fprintf (f, NTXT (" %12lld"), hi->value[i].ll);	      break;	    case VT_FLOAT: fprintf (f, NTXT (" %f"), hi->value[i].f);	      break;	    case VT_DOUBLE: fprintf (f, NTXT (" %12.6lf"), hi->value[i].d);	      break;	    case VT_HRTIME: fprintf (f, NTXT (" %12llu"), hi->value[i].ull);	      break;	    case VT_LABEL: fprintf (f, NTXT (" %s"), stmp ? stmp: "(unnamed)");	      break;	    case VT_ADDRESS: fprintf (f, NTXT (" %12lld"), hi->value[i].ll);	      break;	    case VT_OFFSET: fprintf (f, NTXT (" %p"), hi->value[i].p);	      break;	    case VT_ULLONG: fprintf (f, NTXT (" %12llu"), hi->value[i].ull);	      break;	    default: fprintf (f, NTXT ("     "));	      break;	    }	}      fprintf (f, NTXT ("\n"));    }} voidHist_data::sort (long ind, bool reverse){  if (mode != MODL && ind != -1 && ind == sort_ind && reverse == rev_sort)    // there's no change to the sorting    return; 

Lines 1–500 of 1889.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t