Wolfgang Thallergcc16 merge934c3885 months agoHistory
2637 lines · 67.8 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 <stdio.h>#include <stdlib.h> #include "util.h"#include "DefaultMap.h"#include "CacheMap.h" #include "DbeSession.h"#include "Application.h"#include "CallStack.h"#include "Emsg.h"#include "Experiment.h"#include "Expression.h"#include "Function.h"#include "Histable.h"#include "IndexObject.h"#include "MetricList.h"#include "Module.h"#include "DbeView.h"#include "Metric.h"#include "PathTree.h"#include "LoadObject.h"#include "Sample.h"#include "StringBuilder.h"#include "Table.h" // Define counts, rate for error warnings for statistical profiles#define MIN_PROF_CNT    100#define MAX_PROF_RATE   1000. #define NUM_DESCENDANTS(nd) ((nd)->descendants ? (nd)->descendants->size() : 0)#define IS_LEAF(nd)         ((nd)->descendants == NULL) #ifdef DEBUG#define DBG(__func) __func#else#define DBG(__func)#endif voidPathTree::construct (DbeView *_dbev, int _indxtype, PathTreeType _pathTreeType){  dbev = _dbev;  indxtype = _indxtype;  pathTreeType = _pathTreeType;  status = 0;  nchunks = 0;  chunks = NULL;  nodes = 1; // don't use node 0  nslots = 0;  slots = NULL;  root_idx = 0;  root = NULL;  depth = 1;  dnodes = 0;  phaseIdx = -1;  nexps = 0;  total_obj = NULL;  indx_expr = NULL;  statsq = NULL;  warningq = NULL;  cancel_ok = 1;  ptree_internal = NULL;  ftree_internal = NULL;  ftree_needs_update = false;  depth_map = NULL;  init ();} PathTree::~PathTree (){  fini ();  for (long i = 0; i < nchunks; i++)    delete[] chunks[i];  delete[] chunks;} voidPathTree::init (){  fn_map = new DefaultMap<Function*, NodeIdx>;  stack_prop = PROP_NONE;  desc_htable_size = 511;  desc_htable_nelem = 0;  descHT = new hash_node_t*[desc_htable_size];  for (int i = 0; i < desc_htable_size; i++)    descHT[i] = NULL;  pathMap = new CacheMap<uint64_t, NodeIdx>;  statsq = new Emsgqueue (NTXT ("statsq"));  warningq = new Emsgqueue (NTXT ("warningq"));  if (indxtype < 0)    {      Function *ftotal = dbeSession->get_Total_Function ();      if (pathTreeType == PATHTREE_INTERNAL_FUNCTREE)	total_obj = ftotal;      else	total_obj = ftotal->find_dbeinstr (0, 0);      VMode view_mode = dbev->get_view_mode ();      if (view_mode == VMODE_MACHINE)	stack_prop = PROP_MSTACK;      else if (view_mode == VMODE_EXPERT)	stack_prop = PROP_XSTACK;      else if (view_mode == VMODE_USER)	{	  stack_prop = PROP_USTACK;	  if (dbeSession->is_omp_available ()	      && pathTreeType == PATHTREE_INTERNAL_OMP)	    stack_prop = PROP_XSTACK;	}    }  else    {      total_obj = new IndexObject (indxtype, (uint64_t) - 2);      total_obj->set_name (dbe_strdup (NTXT ("<Total>")));      char *idxname = dbeSession->getIndexSpaceName (indxtype);      if (streq (idxname, NTXT ("OMP_preg")))	stack_prop = PROP_CPRID;      else if (streq (idxname, NTXT ("OMP_task")))	stack_prop = PROP_TSKID;      else	indx_expr = dbeSession->getIndexSpaceExpr (indxtype);    }  root_idx = new_Node (0, total_obj, false);  root = NODE_IDX (root_idx);} voidPathTree::fini (){  // For each node free its descendants vector  // and reset the node list of its function  for (long i = 1; i < nodes; i++)    {      Node *node = NODE_IDX (i);      if (node->descendants)	delete node->descendants;    }  nodes = 1; // don't use node 0   for (int i = 0; i < nslots; i++)    {      int **tmp = slots[i].mvals;      for (long j = 0; j < nchunks; j++)	delete[] tmp[j];      delete[] tmp;    }  delete[] slots;  slots = NULL;  nslots = 0;  delete fn_map;  fn_map = NULL;  delete pathMap;  pathMap = NULL;  destroy (depth_map);  depth_map = NULL;  if (indxtype >= 0)    delete total_obj;   for (int i = 0; i < desc_htable_size; i++)    {      hash_node_t *p = descHT[i];      while (p)	{	  hash_node_t *p1 = p;	  p = p->next;	  delete p1;	}    }  delete[] descHT;  delete statsq;  delete warningq;  depth = 1;  dnodes = 0;  phaseIdx = -1;  nexps = 0;  status = 0;} PtreePhaseStatusPathTree::reset (){  if (pathTreeType == PATHTREE_INTERNAL_FUNCTREE)    return NORMAL; // never process reset for ftree_internal.   if (dbeSession->is_omp_available () && dbev->get_view_mode () == VMODE_USER      && pathTreeType == PATHTREE_MAIN && ptree_internal == NULL)    ptree_internal = new PathTree (dbev, indxtype, PATHTREE_INTERNAL_OMP);   if (phaseIdx != dbev->getPhaseIdx ())    {      fini ();      init ();      phaseIdx = dbev->getPhaseIdx ();      ftree_needs_update = true;    }  for (; nexps < dbeSession->nexps (); nexps++)    {      ftree_needs_update = true;      if (add_experiment (nexps) == CANCELED)	return CANCELED;    }   // LIBRARY_VISIBILITY  if (dbev->isNewViewMode ())    dbev->resetNewViewMode ();  if (dbev->isShowHideChanged ())    dbev->resetShowHideChanged ();  return NORMAL;} intPathTree::allocate_slot (int id, ValueTag vtype){   int i;  int slot_idx = find_slot (id);  if (slot_idx >= 0)    {      DBG (assert (slots[slot_idx].vtype == vtype));      return slot_idx;    }  slot_idx = nslots++;   Slot *old_slots = slots;  slots = new Slot[nslots];  for (i = 0; i < slot_idx; i++)    slots[i] = old_slots[i];  delete[] old_slots;   slots[slot_idx].id = id;  slots[slot_idx].vtype = vtype;  int **ip = new int*[nchunks];  for (i = 0; i < nchunks; i++)    ip[i] = NULL;  slots[slot_idx].mvals = ip;   return slot_idx;} voidPathTree::allocate_slots (Slot *new_slots, int new_nslots){  // duplicates new_slots   // if previously had more slots than currently requested, delete the data from those slots.  for (int i = new_nslots; i < nslots; i++)    {      int **tmp = slots[i].mvals;      for (long j = 0; j < nchunks; j++)	delete tmp[j];      delete tmp;    }  if (new_nslots == 0)    {      nslots = new_nslots;      delete[] slots;      slots = NULL;      return;    }   Slot *old_slots = slots;  slots = new Slot[new_nslots];  for (int i = 0; i < new_nslots; i++)    {      slots[i] = new_slots[i]; // pick up id and vtype      if (i < nslots)	slots[i].mvals = old_slots[i].mvals;      else	{	  if (nchunks == 0)	    slots[i].mvals = NULL;	  else	    {	      int **ip = new int*[nchunks];	      for (long j = 0; j < nchunks; j++)		ip[j] = NULL;	      slots[i].mvals = ip;	    }	}    }  nslots = new_nslots;  delete old_slots;} intPathTree::find_slot (int id){  for (int i = 0; i < nslots; i++)    if (slots[i].id == id)      return i;  return -1;} PathTree::NodeIdxPathTree::new_Node (NodeIdx anc, Histable *instr, bool leaf){  if (nodes >= nchunks * CHUNKSZ)    {      long idx = nchunks++;       // Reallocate Node chunk array      Node **old_chunks = chunks;      chunks = new Node*[nchunks];      for (long k = 0; k < idx; k++)	chunks[k] = old_chunks[k];      delete[] old_chunks;       // Reallocate metric value chunk arrays.      for (int i = 0; i < nslots; i++)	{	  int **mvals = new int*[nchunks];	  for (long k = 0; k < idx; k++)	    {	      mvals[k] = slots[i].mvals[k];	    }	  delete[] slots[i].mvals;	  slots[i].mvals = mvals;	  slots[i].mvals[idx] = NULL;	}       // Allocate new chunk for nodes.      // Note that we don't need to allocate new chunks      // for metric values at this point as we rely on      // lazy allocation.      //      allocate_chunk (chunks, idx);    }  NodeIdx node_idx = nodes++;  Node *node = NODE_IDX (node_idx);  node->ancestor = anc;  node->descendants = leaf ? (Vector<NodeIdx>*)NULL : new Vector<NodeIdx>(2);  node->instr = instr;  Function *func = (Function*) (instr->convertto (Histable::FUNCTION));  node->funclist = fn_map->get (func);  fn_map->put (func, node_idx);  return node_idx;} PathTree::NodeIdxPathTree::find_path (Experiment *exp, DataView *dview, long recIdx){  if (indx_expr != NULL)    {      Expression::Context ctx (dbev, exp, dview, recIdx);      uint64_t idx = indx_expr->eval (&ctx);      Histable *cur_obj = dbeSession->createIndexObject (indxtype, idx);      cur_obj->set_name_from_context (&ctx);      NodeIdx dsc_idx = find_in_desc_htable (root_idx, cur_obj, true);      depth = 2;      return dsc_idx;    }   bool showAll = dbev->isShowAll ();  int t_stack_prop = stack_prop;  void *stackId = dview->getObjValue (t_stack_prop, recIdx);  NodeIdx node_idx;  if (stackId != NULL)    {      // pathMap does not work with NULL key      node_idx = pathMap->get ((uint64_t) stackId);      if (node_idx != 0)	return node_idx;    }  Vector<Histable*> *stack = (Vector<Histable*>*)CallStack::getStackPCs (stackId, !showAll);  int stack_size = stack->size ();  if (stack_size == 0)    return root_idx;   node_idx = root_idx;  int thisdepth = 1;   for (int i = stack_size - 1; i >= 0; i--)    {      bool leaf = (i == 0);      Histable *cur_addr = stack->fetch (i);       // bail out of loop if load object API-only is set      // and this is not the top frame      // This is now done in HSTACK if hide is set       Function *func = (Function*) cur_addr->convertto (Histable::FUNCTION);      if (func != NULL)	{	  Module *mod = func->module;	  LoadObject *lo = mod->loadobject;	  int segx = lo->seg_idx;	  if (showAll && dbev->get_lo_expand (segx) == LIBEX_API	      && i != stack_size - 1)	    leaf = true;	}       NodeIdx dsc_idx = find_desc_node (node_idx, cur_addr, leaf);      thisdepth++;      node_idx = dsc_idx;       // LIBEX_API processing might have set leaf to true      if (leaf)	break;    }  if (thisdepth > depth)    depth = thisdepth;  delete stack;  pathMap->put ((uint64_t) stackId, node_idx);  return node_idx;} static intdesc_node_comp (const void *s1, const void *s2, const void *ptree){  PathTree::NodeIdx t1, t2;  t1 = *(PathTree::NodeIdx *)s1;  t2 = *(PathTree::NodeIdx *)s2;  PathTree* Ptree = (PathTree *) ptree;  PathTree::Node *n1 = Ptree->NODE_IDX (t1);  PathTree::Node *n2 = Ptree->NODE_IDX (t2);  Histable *d1 = n1->instr;  Histable *d2 = n2->instr;  if (d1->id < d2->id)    return -1;  else if (d1->id > d2->id)    return +1;  else    return 0;} PathTree::NodeIdxPathTree::find_in_desc_htable (NodeIdx node_idx, Histable *instr, bool leaf){  unsigned int hash_code = (unsigned int) instr->id % desc_htable_size;  Node *node = NODE_IDX (node_idx);  hash_node_t *p = NULL;  for (p = descHT[hash_code]; p; p = p->next)    {      Node *dsc = NODE_IDX (p->nd);      Histable *dinstr = dsc->instr;      if (dinstr->id == instr->id && leaf == IS_LEAF (dsc))	return p->nd;    }  // Not found  NodeIdx dsc_idx = new_Node (node_idx, instr, leaf);  node->descendants->append (dsc_idx);  p = new hash_node_t ();  p->nd = dsc_idx;  p->next = descHT[hash_code];  descHT[hash_code] = p;  desc_htable_nelem++;   // time to resize  if (desc_htable_nelem == desc_htable_size)    {      int old_htable_size = desc_htable_size;      desc_htable_size = old_htable_size * 2 + 1;      hash_node_t **old_htable = descHT;      descHT = new hash_node_t*[desc_htable_size];      for (int i = 0; i < desc_htable_size; i++)	descHT[i] = NULL;       for (int i = 0; i < old_htable_size; i++)	if (old_htable[i] != NULL)	  {	    hash_node *old_p;	    hash_node_t *hash_p = old_htable[i];	    while (hash_p != NULL)	      {		hash_node_t *new_p = new hash_node_t ();		new_p->nd = hash_p->nd;		Node *dnode = NODE_IDX (hash_p->nd);		Histable *dnode_instr = dnode->instr;		hash_code = (unsigned int) dnode_instr->id % desc_htable_size;		new_p->next = descHT[hash_code];		descHT[hash_code] = new_p;		old_p = hash_p;		hash_p = hash_p->next;		delete old_p;	      }	  }      delete[] old_htable;    }  return dsc_idx;

Lines 1–500 of 2637.

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