• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdesdk API Reference
  • KDE Home
  • Contact Us
 

kcachegrind

  • sources
  • kde-4.12
  • kdesdk
  • kcachegrind
  • libviews
instritem.cpp
Go to the documentation of this file.
1 /* This file is part of KCachegrind.
2  Copyright (C) 2003-2011 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
3 
4  KCachegrind is free software; you can redistribute it and/or
5  modify it under the terms of the GNU General Public
6  License as published by the Free Software Foundation, version 2.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; see the file COPYING. If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  Boston, MA 02110-1301, USA.
17 */
18 
19 /*
20  * Items of instruction view.
21  */
22 
23 #include "instritem.h"
24 
25 #include <QPixmap>
26 #include <QPainter>
27 #include <QPolygon>
28 
29 #include "globalguiconfig.h"
30 #include "listutils.h"
31 #include "instrview.h"
32 
33 //
34 // InstrItem
35 //
36 
37 // for messages
38 InstrItem::InstrItem(InstrView* iv, QTreeWidget* parent,
39  Addr addr, const QString& msg)
40  : QTreeWidgetItem(parent)
41 {
42  _view = iv;
43  _addr = addr;
44  _instr = 0;
45  _instrCall = 0;
46  _instrJump = 0;
47  _inside = false;
48 
49  setTextAlignment(0, Qt::AlignRight);
50  setTextAlignment(1, Qt::AlignRight);
51  setTextAlignment(2, Qt::AlignRight);
52 
53  setText(0, addr.pretty());
54  setText(6, msg);
55 
56  updateGroup();
57  updateCost();
58 }
59 
60 // for code lines
61 InstrItem::InstrItem(InstrView* iv, QTreeWidget* parent,
62  Addr addr, bool inside,
63  const QString& code, const QString& cmd,
64  const QString& args, TraceInstr* instr)
65  : QTreeWidgetItem(parent)
66 {
67  _view = iv;
68  _addr = addr;
69  _instr = instr;
70  _instrCall = 0;
71  _instrJump = 0;
72  _inside = inside;
73 
74  setTextAlignment(0, Qt::AlignRight);
75  setTextAlignment(1, Qt::AlignRight);
76  setTextAlignment(2, Qt::AlignRight);
77 
78  if (args == "...")
79  setText(0, args);
80  else
81  setText(0, addr.pretty());
82  setText(4, code);
83  setText(5, cmd);
84  setText(6, args);
85 
86  TraceLine* l;
87  if (instr && (l = instr->line()))
88  setText(7, l->name());
89 
90  updateGroup();
91  updateCost();
92 }
93 
94 // for call lines
95 InstrItem::InstrItem(InstrView* iv, QTreeWidgetItem* parent, Addr addr,
96  TraceInstr* instr, TraceInstrCall* instrCall)
97  : QTreeWidgetItem(parent)
98 {
99  _view = iv;
100  _addr = addr;
101  _instr = instr;
102  _instrCall = instrCall;
103  _instrJump = 0;
104  _inside = true;
105 
106  setTextAlignment(0, Qt::AlignRight);
107  setTextAlignment(1, Qt::AlignRight);
108  setTextAlignment(2, Qt::AlignRight);
109 
110  //qDebug("InstrItem: (file %d, line %d) Linecall to %s",
111  // fileno, lineno, _lineCall->call()->called()->prettyName().toAscii());
112 
113  SubCost cc = _instrCall->callCount();
114  QString callStr = " ";
115  if (cc==0)
116  callStr += QObject::tr("Active call to '%1'")
117  .arg(_instrCall->call()->calledName());
118  else
119  callStr += QObject::tr("%n call(s) to '%2'", "", (uint64)cc)
120  .arg(_instrCall->call()->calledName());
121 
122  TraceFunction* calledF = _instrCall->call()->called();
123  calledF->addPrettyLocation(callStr);
124 
125  setText(6, callStr);
126 
127  updateGroup();
128  updateCost();
129 }
130 
131 // for jump lines
132 InstrItem::InstrItem(InstrView* iv, QTreeWidgetItem* parent, Addr addr,
133  TraceInstr* instr, TraceInstrJump* instrJump)
134  : QTreeWidgetItem(parent)
135 {
136  _view = iv;
137  _addr = addr;
138  _inside = true;
139  _instr = instr;
140  _instrCall = 0;
141  _instrJump = instrJump;
142 
143  setTextAlignment(0, Qt::AlignRight);
144  setTextAlignment(1, Qt::AlignRight);
145  setTextAlignment(2, Qt::AlignRight);
146 
147  //qDebug("SourceItem: (file %d, line %d) Linecall to %s",
148  // fileno, lineno, _lineCall->call()->called()->prettyName().toAscii());
149 
150  QString jStr;
151  if (_instrJump->isCondJump())
152  jStr = QObject::tr("Jump %1 of %2 times to 0x%3")
153  .arg(_instrJump->followedCount().pretty())
154  .arg(_instrJump->executedCount().pretty())
155  .arg(_instrJump->instrTo()->addr().toString());
156  else
157  jStr = QObject::tr("Jump %1 times to 0x%2")
158  .arg(_instrJump->executedCount().pretty())
159  .arg(_instrJump->instrTo()->addr().toString());
160 
161  setText(6, jStr);
162 
163  updateGroup();
164  updateCost();
165 }
166 
167 
168 void InstrItem::updateGroup()
169 {
170  if (!_instrCall) return;
171 
172  TraceFunction* f = _instrCall->call()->called();
173  QColor c = GlobalGUIConfig::functionColor(_view->groupType(), f);
174  setIcon(6, colorPixmap(10, 10, c));
175 }
176 
177 void InstrItem::updateCost()
178 {
179  _pure = SubCost(0);
180  _pure2 = SubCost(0);
181 
182  if (!_instr) return;
183  if (_instrJump) return;
184 
185  ProfileCostArray* instrCost = _instrCall ?
186  (ProfileCostArray*)_instrCall : (ProfileCostArray*)_instr;
187 
188  // do not show any cost inside of cycles
189  if (_instrCall &&
190  ((_instrCall->call()->inCycle()>0) ||
191  (_instrCall->call()->isRecursion()))) {
192  QString str;
193  QPixmap p;
194 
195  QString icon = "edit-undo";
196 #if 0 // TODO
197  KIconLoader* loader = KIconLoader::global();
198  p= loader->loadIcon(icon, KIconLoader::Small, 0,
199  KIconLoader::DefaultState, QStringList(), 0, true);
200 #endif
201  if (p.isNull())
202  str = QObject::tr("(cycle)");
203 
204  setText(1, str);
205  setIcon(1, p);
206  setText(2, str);
207  setIcon(2, p);
208  return;
209  }
210 
211  ProfileCostArray* totalCost;
212  if (GlobalConfig::showExpanded())
213  totalCost = _instr->function()->inclusive();
214  else
215  totalCost = _instr->function()->data();
216 
217  EventType *et = _view->eventType();
218  _pure = et ? instrCost->subCost(et) : SubCost(0);
219  if (_pure == 0) {
220  setText(1, QString());
221  setIcon(1, QPixmap());
222  }
223  else {
224  double total = totalCost->subCost(et);
225  double pure = 100.0 * _pure / total;
226 
227  if (GlobalConfig::showPercentage())
228  setText(1, QString("%1")
229  .arg(pure, 0, 'f', GlobalConfig::percentPrecision()));
230  else
231  setText(1, _pure.pretty());
232 
233  setIcon(1, costPixmap(et, instrCost, total, false));
234  }
235 
236  EventType *ct2 = _view->eventType2();
237  _pure2 = ct2 ? instrCost->subCost(ct2) : SubCost(0);
238  if (_pure2 == 0) {
239  setText(2, QString());
240  setIcon(2, QPixmap());
241  }
242  else {
243  double total = totalCost->subCost(ct2);
244  double pure = 100.0 * _pure2 / total;
245 
246  if (GlobalConfig::showPercentage())
247  setText(2, QString("%1")
248  .arg(pure, 0, 'f', GlobalConfig::percentPrecision()));
249  else
250  setText(2, _pure2.pretty());
251 
252  setIcon(2, costPixmap(ct2, instrCost, total, false));
253  }
254 }
255 
256 bool InstrItem::operator<( const QTreeWidgetItem & other ) const
257 {
258  const InstrItem* ii1 = this;
259  const InstrItem* ii2 = (InstrItem*) &other;
260  int col = treeWidget()->sortColumn();
261 
262  if (col==1)
263  return (ii1->_pure < ii2->_pure);
264 
265  if (col==2)
266  return (ii1->_pure2 < ii2->_pure2);
267 
268  if (col==0) {
269  if (ii1->_addr < ii2->_addr) return true;
270  if (ii1->_addr > ii2->_addr) return false;
271 
272  // Same address: code gets above calls/jumps
273  if (!ii1->_instrCall && !ii1->_instrJump) return true;
274  if (!ii2->_instrCall && !ii2->_instrJump) return false;
275 
276  // calls above jumps
277  if (ii1->_instrCall && !ii2->_instrCall) return true;
278  if (ii2->_instrCall && !ii1->_instrCall) return false;
279 
280  if (ii1->_instrCall && ii2->_instrCall) {
281  // Two calls: desending sort according costs
282  if (ii1->_pure < ii2->_pure) return true;
283  if (ii1->_pure > ii2->_pure) return false;
284 
285  // Two calls: sort according function names
286  TraceFunction* f1 = ii1->_instrCall->call()->called();
287  TraceFunction* f2 = ii2->_instrCall->call()->called();
288  return (f1->prettyName() < f2->prettyName());
289  }
290 
291  // Two jumps: descending sort according target address
292  return (ii1->_instrJump->instrTo()->addr() <
293  ii2->_instrJump->instrTo()->addr());
294  }
295  return QTreeWidgetItem::operator<(other);
296 }
297 
298 void InstrItem::setJumpArray(const QVector<TraceInstrJump*>& a)
299 {
300  _jump = a;
301 }
302 
303 
304 //
305 // InstrItemDelegate
306 //
307 
308 InstrItemDelegate::InstrItemDelegate(InstrView *parent)
309 {
310  _parent = parent;
311 }
312 
313 QSize InstrItemDelegate::sizeHint(const QStyleOptionViewItem &option,
314  const QModelIndex &index) const
315 {
316  QSize sz = QItemDelegate::sizeHint(option, index);
317 
318  int c = index.column();
319  if (c != 3) return sz;
320 
321  InstrView* iv = (InstrView*) _parent;
322  int levels = iv->arrowLevels();
323 
324  if (levels == 0)
325  return QSize(0, sz.height());
326 
327  // 10 pixels for the arrow, 1 pixel margin left and right
328  return QSize(10 + 6*levels + 2, sz.height());
329 }
330 
331 void InstrItemDelegate::paint(QPainter *painter,
332  const QStyleOptionViewItem &option,
333  const QModelIndex &index) const
334 {
335  int column = index.column();
336  InstrItem* item = static_cast<InstrItem*>(index.internalPointer());
337 
338  QColor color;
339  if ( !item->inside() || ((column==1) || (column==2)))
340  color = option.palette.color( QPalette::Button );
341  else if ((item->instrCall() || item->instrJump()) && column>2)
342  color = option.palette.color( QPalette::Midlight );
343  if (color.isValid())
344  _parent->model()->setData(index, color, Qt::BackgroundRole);
345 
346  if(column==3)
347  paintArrows(painter, option, index);
348  else
349  QItemDelegate::paint(painter, option, index);
350 }
351 
352 void InstrItemDelegate::paintArrows(QPainter *p,
353  const QStyleOptionViewItem &option,
354  const QModelIndex &index) const
355 {
356  QTreeWidget* tw = _parent;
357  if ( !tw ) return;
358  InstrView* iv = (InstrView*) tw;
359  InstrItem* item = static_cast<InstrItem*>(index.internalPointer());
360  const QRect& rect = option.rect;
361  int height = rect.height();
362 
363  p->save();
364  drawBackground(p, option, index);
365  p->translate(rect.topLeft());
366 
367  int marg = 1;
368  int yy = height/2, y1, y2;
369  QColor c;
370 
371  int start = -1, end = -1;
372 
373  TraceInstrJump* instrJump = item->instrJump();
374  Addr addr = item->addr();
375  TraceInstrCall* instrCall = item->instrCall();
376 
377  // draw line borders, detect start/stop of a line
378  for(int i=0; i< item->jumpCount(); i++) {
379  TraceInstrJump* jump = item->jump(i);
380  if (jump == 0) continue;
381 
382  y1 = 0;
383  y2 = height;
384  if ((instrJump == jump) &&
385  (jump->instrFrom()->addr() == addr)) {
386 
387  //qDebug() << "InstrItem " << addr.toString() << ": start " << i;
388  if (start<0) start = i;
389  if (jump->instrTo()->addr() <= addr)
390  y2 = yy;
391  else
392  y1 = yy;
393  }
394  else if (!instrJump && !instrCall &&
395  (jump->instrTo()->addr() == addr)) {
396 
397  //qDebug() << "InstrItem " << addr.toString() << ": end " << i;
398  if (end<0) end = i;
399  if (jump->instrFrom()->addr() < addr)
400  y2 = yy;
401  else
402  y1 = yy;
403  }
404 
405  c = jump->isCondJump() ? Qt::red : Qt::blue;
406  p->fillRect( marg + 6*i, y1, 4, y2, c);
407  p->setPen(c.light());
408  p->drawLine( marg + 6*i, y1, marg + 6*i, y2);
409  p->setPen(c.dark());
410  p->drawLine( marg + 6*i +3, y1, marg + 6*i +3, y2);
411  }
412 
413  // draw start/stop horizontal line
414  int x, y = yy-2, w, h = 4;
415  if (start >= 0) {
416  c = item->jump(start)->isCondJump() ? Qt::red : Qt::blue;
417  x = marg + 6*start;
418  w = 6*(iv->arrowLevels() - start) + 10;
419  p->fillRect( x, y, w, h, c);
420  p->setPen(c.light());
421  p->drawLine(x, y, x+w-1, y);
422  p->drawLine(x, y, x, y+h-1);
423  p->setPen(c.dark());
424  p->drawLine(x+w-1, y, x+w-1, y+h-1);
425  p->drawLine(x+1, y+h-1, x+w-1, y+h-1);
426  }
427  if (end >= 0) {
428  c = item->jump(end)->isCondJump() ? Qt::red : Qt::blue;
429  x = marg + 6*end;
430  w = 6*(iv->arrowLevels() - end) + 10;
431 
432  QPolygon a;
433  a.putPoints(0, 8, x,y+h,
434  x,y, x+w-8,y, x+w-8,y-2,
435  x+w,yy,
436  x+w-8,y+h+2, x+w-8,y+h,
437  x,y+h);
438  p->setBrush(c);
439  p->drawConvexPolygon(a);
440 
441  p->setPen(c.light());
442  p->drawPolyline(a.constData(), 5);
443  p->setPen(c.dark());
444  p->drawPolyline(a.constData() + 4, 2);
445  p->setPen(c.light());
446  p->drawPolyline(a.constData() + 5, 2);
447  p->setPen(c.dark());
448  p->drawPolyline(a.constData() + 6, 2);
449  }
450 
451  // draw inner vertical line for start/stop
452  // this overwrites borders of horizontal line
453  for(int i=0; i< item->jumpCount(); i++) {
454  TraceInstrJump* jump = item->jump(i);
455  if (jump == 0) continue;
456 
457  c = jump->isCondJump() ? Qt::red : Qt::blue;
458 
459  if (jump->instrFrom()->addr() == addr) {
460  bool drawUp = true;
461  if (jump->instrTo()->addr() == addr)
462  if (start<0) drawUp=false;
463  if (jump->instrTo()->addr() > addr) drawUp=false;
464  if (drawUp)
465  p->fillRect( marg + 6*i +1, 0, 2, yy, c);
466  else
467  p->fillRect( marg + 6*i +1, yy, 2, height-yy, c);
468  }
469  else if (jump->instrTo()->addr() == addr) {
470  if (end<0) end = i;
471  if (jump->instrFrom()->addr() < addr)
472  p->fillRect( marg + 6*i +1, 0, 2, yy, c);
473  else
474  p->fillRect( marg + 6*i +1, yy, 2, height-yy, c);
475  }
476  }
477  p->restore();
478 }
479 
InstrItem::jumpCount
int jumpCount() const
Definition: instritem.h:62
Addr::pretty
QString pretty() const
Definition: addr.cpp:67
TraceCall::isRecursion
bool isRecursion()
Definition: tracedata.h:844
TraceItemView::eventType2
EventType * eventType2() const
Definition: traceitemview.h:152
InstrItem::operator<
bool operator<(const QTreeWidgetItem &other) const
Definition: instritem.cpp:256
GlobalConfig::showPercentage
static bool showPercentage()
Definition: globalconfig.cpp:328
ProfileCostArray::subCost
SubCost subCost(EventType *)
Returns a sub cost.
Definition: costitem.cpp:591
InstrItem::instr
TraceInstr * instr() const
Definition: instritem.h:58
TraceItemView::eventType
EventType * eventType() const
Definition: traceitemview.h:151
QTreeWidget
TraceInstrJump::instrTo
TraceInstr * instrTo() const
Definition: tracedata.h:737
InstrItem::setJumpArray
void setJumpArray(const QVector< TraceInstrJump * > &a)
Definition: instritem.cpp:298
GlobalGUIConfig::functionColor
static QColor functionColor(ProfileContext::Type gt, TraceFunction *)
Definition: globalguiconfig.cpp:205
TraceFunction
A traced function.
Definition: tracedata.h:1122
TraceJumpCost::executedCount
SubCost executedCount()
Definition: tracedata.cpp:55
TraceCallCost::callCount
SubCost callCount()
Definition: tracedata.cpp:125
uint64
unsigned long long uint64
Definition: subcost.h:27
TraceInstrCall
A call from an instruction of one function to another function.
Definition: tracedata.h:782
Addr
Addresses are 64bit values like costs to be able to always load profile data produced on 64bit archit...
Definition: addr.h:31
EventType
A cost type, e.g.
Definition: eventtype.h:43
TraceInstrJump::isCondJump
bool isCondJump() const
Definition: tracedata.h:738
TraceItemView::setData
virtual void setData(TraceData *d)
Definition: traceitemview.cpp:165
InstrItem::jump
TraceInstrJump * jump(int i) const
Definition: instritem.h:61
Addr::toString
QString toString() const
Definition: addr.cpp:50
ProfileCostArray
An array of basic cost metrics for a trace item.
Definition: costitem.h:144
InstrItemDelegate::_parent
InstrView * _parent
Definition: instritem.h:99
InstrItemDelegate::InstrItemDelegate
InstrItemDelegate(InstrView *parent)
Definition: instritem.cpp:308
TraceInstr
A code instruction address of the program.
Definition: tracedata.h:887
listutils.h
TraceInstr::function
TraceFunction * function() const
Definition: tracedata.h:906
InstrItem::updateGroup
void updateGroup()
Definition: instritem.cpp:168
TraceFunction::prettyName
QString prettyName() const
Similar to name, but prettyfied = more descriptive to humans.
Definition: tracedata.cpp:1889
CostItem::data
virtual TraceData * data()
Definition: costitem.cpp:111
globalguiconfig.h
TraceLine
A source line of the program.
Definition: tracedata.h:935
TraceCall::inCycle
int inCycle()
Definition: tracedata.cpp:1202
InstrView::arrowLevels
int arrowLevels()
Definition: instrview.h:44
TraceLine::name
virtual QString name() const
Returns dynamic name info (without type)
Definition: tracedata.cpp:1475
QTreeWidgetItem
instrview.h
TraceInstr::line
TraceLine * line() const
Definition: tracedata.h:907
InstrItem::inside
bool inside() const
Definition: instritem.h:57
TraceInstrJump
A jump from an instruction to another inside of a function.
Definition: tracedata.h:725
GlobalConfig::showExpanded
static bool showExpanded()
Definition: globalconfig.cpp:333
InstrItemDelegate::paintArrows
void paintArrows(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
Definition: instritem.cpp:352
GlobalConfig::percentPrecision
static int percentPrecision()
Definition: globalconfig.cpp:385
InstrView
Definition: instrview.h:32
InstrItem::addr
Addr addr() const
Definition: instritem.h:56
SubCost
Cost event counter, simple wrapper around a 64bit entity.
Definition: subcost.h:32
TraceCall::called
TraceFunction * called(bool skipCycle=false) const
Definition: tracedata.cpp:1235
TraceFunction::addPrettyLocation
void addPrettyLocation(QString &, int maxFiles=1) const
Definition: tracedata.cpp:2055
SubCost::pretty
QString pretty(char sep= ' ') const
Convert SubCost value into a QString, spaced every 3 digits.
Definition: subcost.cpp:46
instritem.h
TraceJumpCost::followedCount
SubCost followedCount()
Definition: tracedata.cpp:62
InstrItemDelegate::paint
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
Definition: instritem.cpp:331
InstrItem
Definition: instritem.h:34
TraceInstrJump::instrFrom
TraceInstr * instrFrom() const
Definition: tracedata.h:736
InstrItem::updateCost
void updateCost()
Definition: instritem.cpp:177
InstrItem::InstrItem
InstrItem(InstrView *iv, QTreeWidget *parent, Addr addr, const QString &)
Definition: instritem.cpp:38
InstrItem::instrCall
TraceInstrCall * instrCall() const
Definition: instritem.h:59
InstrItem::instrJump
TraceInstrJump * instrJump() const
Definition: instritem.h:60
TraceInstrCall::call
TraceCall * call() const
Definition: tracedata.h:791
TraceItemView::groupType
ProfileContext::Type groupType() const
Definition: traceitemview.h:153
costPixmap
QPixmap costPixmap(EventType *ct, ProfileCostArray *cost, double total, bool framed)
Definition: listutils.cpp:217
colorPixmap
QPixmap colorPixmap(int w, int h, QColor c)
Definition: listutils.cpp:32
TraceCall::calledName
QString calledName(bool skipCycle=false) const
Definition: tracedata.cpp:1264
TraceInclusiveCost::inclusive
ProfileCostArray * inclusive()
Definition: tracedata.cpp:163
InstrItemDelegate::sizeHint
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
Definition: instritem.cpp:313
TraceInstr::addr
Addr addr() const
Definition: tracedata.h:905
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:03:27 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kcachegrind

Skip menu "kcachegrind"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdesdk API Reference

Skip menu "kdesdk API Reference"
  • kapptemplate
  • kcachegrind
  • kompare
  • lokalize
  • okteta
  • umbrello
  •   umbrello

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal