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

kcachegrind

  • sources
  • kde-4.14
  • kdesdk
  • kcachegrind
  • libcore
stackbrowser.cpp
Go to the documentation of this file.
1 /* This file is part of KCachegrind.
2  Copyright (C) 2003 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 #include "stackbrowser.h"
20 
21 
22 // Stack
23 
24 Stack::Stack(TraceFunction* top, TraceCallList calls)
25 {
26  _refCount = 0;
27  _top = top;
28  _calls = calls;
29 
30  extendBottom();
31 }
32 
33 Stack::Stack(TraceFunction* f)
34 {
35  _refCount = 0;
36  _top = f;
37 
38  extendBottom();
39  extendTop();
40 }
41 
42 void Stack::extendBottom()
43 {
44  SubCost most;
45  TraceFunction* f;
46 
47  if (!_calls.isEmpty())
48  f = _calls.last()->called();
49  else
50  f = _top;
51 
52  if (!f) return;
53  // do not follow calls from cycles
54  if (f->cycle() == f) return;
55 
56  // event type to use for the "most probable" call stack
57  // we simply take the first real event type
58  if ((_top->data() == 0) ||
59  (_top->data()->eventTypes()->realCount() <1)) return;
60  EventType* e = _top->data()->eventTypes()->realType(0);
61 
62  int max = 30;
63 
64  // try to extend to lower stack frames
65  while (f && (max-- >0)) {
66  TraceCall* call = 0;
67  most = 0;
68  foreach(TraceCall* c, f->callings()) {
69  // no cycle calls in stack: could be deleted without notice
70  if (c->called()->cycle() == c->called()) continue;
71  // no simple recursions
72  if (c->called() == _top) continue;
73 
74  if (c->called()->name().isEmpty()) continue;
75  SubCost sc = c->subCost(e);
76  if (sc == 0) continue;
77 
78  if (sc > most) {
79  most = sc;
80  call = c;
81  }
82  }
83  if (!call)
84  break;
85 
86  _calls.append(call);
87  f = call->called();
88  }
89 }
90 
91 
92 void Stack::extendTop()
93 {
94  SubCost most;
95 
96  int max = 10;
97 
98  // do not follow calls from cycles
99  if (_top->cycle() == _top) return;
100 
101  // event type to use for the "most probable" call stack
102  // we simply take the first real event type
103  if ((_top->data() == 0) ||
104  (_top->data()->eventTypes()->realCount() <1)) return;
105  EventType* e = _top->data()->eventTypes()->realType(0);
106 
107  // try to extend to upper stack frames
108  while (_top && (max-- >0)) {
109  TraceCall* call = 0;
110  most = 0;
111  foreach(TraceCall* c, _top->callers()) {
112  // no cycle calls in stack: could be deleted without notice
113  if (c->caller()->cycle() == c->caller()) continue;
114  // no simple recursions
115  if (c->caller() == _top) continue;
116 
117  if (c->caller()->name().isEmpty()) continue;
118  SubCost sc = c->subCost(e);
119  if (sc == 0) continue;
120 
121  if (sc > most) {
122  most = sc;
123  call = c;
124  }
125  }
126  if (!call)
127  break;
128 
129  _calls.prepend(call);
130  _top = call->caller();
131  }
132 }
133 
134 TraceFunction* Stack::caller(TraceFunction* fn, bool extend)
135 {
136  TraceFunction* f;
137 
138  if (extend && (_top == fn)) {
139  // extend at top
140  extendTop();
141  f = _top;
142  }
143 
144  foreach(TraceCall* c, _calls) {
145  f = c->called();
146  if (f == fn)
147  return c->caller();
148  }
149  return 0;
150 }
151 
152 TraceFunction* Stack::called(TraceFunction* fn, bool extend)
153 {
154  TraceFunction* f;
155 
156  foreach(TraceCall* c, _calls) {
157  f = c->caller();
158  if (f == fn)
159  return c->called();
160  }
161 
162  if (extend) {
163  // extend at bottom
164  extendBottom();
165 
166  // and search again
167  foreach(TraceCall* c, _calls) {
168  f = c->caller();
169  if (f == fn)
170  return c->called();
171  }
172  }
173 
174  return 0;
175 }
176 
177 bool Stack::contains(TraceFunction* fn)
178 {
179  // cycles are listed on there own
180  if (fn->cycle() == fn) return false;
181  if (_top->cycle() == _top) return false;
182 
183  if (fn == _top)
184  return true;
185 
186  TraceFunction* f = _top;
187 
188  foreach(TraceCall* c, _calls) {
189  f = c->called();
190  if (f == fn)
191  return true;
192  }
193 
194  // try to extend at bottom (even if callCount 0)
195  foreach(TraceCall* c, f->callings()) {
196  f = c->called();
197  if (f == fn) {
198  _calls.append(c);
199 
200  // extend at bottom after found one
201  extendBottom();
202  return true;
203  }
204  }
205 
206  // try to extend at top (even if callCount 0)
207  foreach(TraceCall* c, _top->callers()) {
208  f = c->caller();
209  if (f == fn) {
210  _calls.prepend(c);
211 
212  // extend at top after found one
213  extendTop();
214  return true;
215  }
216  }
217 
218  return false;
219 }
220 
221 Stack* Stack::split(TraceFunction* f)
222 {
223  TraceCallList calls = _calls;
224 
225  // cycles are listed on there own
226  if (f->cycle() == f) return 0;
227  if (_top->cycle() == _top) return 0;
228 
229  foreach(TraceCall* c, calls) {
230  foreach(TraceCall* c2, c->called()->callings()) {
231  if (c2 == c) continue;
232  if (c2->called() != f) continue;
233 
234  // remove bottom part
235  while (!calls.isEmpty() && (calls.last()!=c))
236  calls.removeLast();
237 
238  calls.append(c2);
239  return new Stack(_top, calls);
240  }
241  }
242  return 0;
243 }
244 
245 QString Stack::toString()
246 {
247  QString res = _top->name();
248  foreach(TraceCall *c, _calls)
249  res += "\n > " + c->called()->name();
250 
251  return res;
252 }
253 
254 
255 // HistoryItem
256 
257 HistoryItem::HistoryItem(Stack* stack, TraceFunction* function)
258 {
259  _stack = stack;
260  _function = function;
261  if (_stack)
262  _stack->ref();
263 
264  _last = 0;
265  _next = 0;
266 
267 /*
268  qDebug("New Stack History Item (sRef %d): %s\n %s",
269  _stack->refCount(), qPrintable(_function->name()),
270  qPrintable(_stack->toString()));
271 */
272 }
273 
274 HistoryItem::~HistoryItem()
275 {
276  if (0) qDebug("Deleting Stack History Item (sRef %d): %s",
277  _stack->refCount(),
278  qPrintable(_function->name()));
279 
280  if (_last)
281  _last->_next = _next;
282  if (_stack) {
283  if (_stack->deref() == 0)
284  delete _stack;
285  }
286 }
287 
288 
289 // StackBrowser
290 
291 StackBrowser::StackBrowser()
292 {
293  _current = 0;
294 }
295 
296 StackBrowser::~StackBrowser()
297 {
298  delete _current;
299 }
300 
301 HistoryItem* StackBrowser::select(TraceFunction* f)
302 {
303  if (!_current) {
304  Stack* s = new Stack(f);
305  _current = new HistoryItem(s, f);
306  }
307  else if (_current->function() != f) {
308  // make current item the last one
309  HistoryItem* item = _current;
310  if (item->next()) {
311  item = item->next();
312  item->last()->setNext(0);
313 
314  while (item->next()) {
315  item = item->next();
316  delete item->last();
317  }
318  delete item;
319  }
320 
321  Stack* s = _current->stack();
322  if (!s->contains(f)) {
323  s = s->split(f);
324  if (!s)
325  s = new Stack(f);
326  }
327 
328  item = _current;
329  _current = new HistoryItem(s, f);
330  item->setNext(_current);
331  _current->setLast(item);
332  }
333 
334  // qDebug("Selected %s in StackBrowser", qPrintable(f->name()));
335 
336  return _current;
337 }
338 
339 HistoryItem* StackBrowser::goBack()
340 {
341  if (_current && _current->last())
342  _current = _current->last();
343 
344  return _current;
345 }
346 
347 HistoryItem* StackBrowser::goForward()
348 {
349  if (_current && _current->next())
350  _current = _current->next();
351 
352  return _current;
353 }
354 
355 HistoryItem* StackBrowser::goUp()
356 {
357  if (_current) {
358  TraceFunction* f = _current->stack()->caller(_current->function(), true);
359  if (f)
360  _current = select(f);
361  }
362 
363  return _current;
364 }
365 
366 HistoryItem* StackBrowser::goDown()
367 {
368  if (_current) {
369  TraceFunction* f = _current->stack()->called(_current->function(), true);
370  if (f)
371  _current = select(f);
372  }
373 
374  return _current;
375 }
376 
377 bool StackBrowser::canGoBack()
378 {
379  return _current && _current->last();
380 }
381 
382 bool StackBrowser::canGoForward()
383 {
384  return _current && _current->next();
385 }
386 
387 bool StackBrowser::canGoUp()
388 {
389  if (!_current) return false;
390 
391  return _current->stack()->caller(_current->function(), false);
392 }
393 
394 bool StackBrowser::canGoDown()
395  {
396  if (!_current) return false;
397 
398  return _current->stack()->called(_current->function(), false);
399 }
EventTypeSet::realCount
int realCount()
Definition: eventtype.h:133
HistoryItem::function
TraceFunction * function()
Definition: stackbrowser.h:71
StackBrowser::goUp
HistoryItem * goUp()
Definition: stackbrowser.cpp:355
ProfileCostArray::subCost
SubCost subCost(EventType *)
Returns a sub cost.
Definition: costitem.cpp:591
Stack::ref
void ref()
Definition: stackbrowser.h:42
HistoryItem::~HistoryItem
~HistoryItem()
Definition: stackbrowser.cpp:274
StackBrowser::canGoDown
bool canGoDown()
Definition: stackbrowser.cpp:394
Stack::called
TraceFunction * called(TraceFunction *, bool extend)
Definition: stackbrowser.cpp:152
StackBrowser::goBack
HistoryItem * goBack()
Definition: stackbrowser.cpp:339
TraceFunction::callings
const TraceCallList & callings(bool skipCycle=false) const
Definition: tracedata.cpp:2302
HistoryItem::HistoryItem
HistoryItem(Stack *, TraceFunction *)
Definition: stackbrowser.cpp:257
TraceCall::caller
TraceFunction * caller(bool skipCycle=false) const
Definition: tracedata.cpp:1230
stackbrowser.h
TraceFunction
A traced function.
Definition: tracedata.h:1122
StackBrowser::~StackBrowser
~StackBrowser()
Definition: stackbrowser.cpp:296
StackBrowser::StackBrowser
StackBrowser()
Definition: stackbrowser.cpp:291
TraceFunction::cycle
TraceFunctionCycle * cycle()
Definition: tracedata.h:1200
TraceData::eventTypes
EventTypeSet * eventTypes()
Definition: tracedata.h:1407
StackBrowser::canGoUp
bool canGoUp()
Definition: stackbrowser.cpp:387
Stack::caller
TraceFunction * caller(TraceFunction *, bool extend)
Definition: stackbrowser.cpp:134
StackBrowser::goForward
HistoryItem * goForward()
Definition: stackbrowser.cpp:347
TraceFunction::callers
TraceCallList callers(bool skipCycle=false) const
Definition: tracedata.cpp:2278
EventType
A cost type, e.g.
Definition: eventtype.h:43
Stack::Stack
Stack(TraceFunction *)
Definition: stackbrowser.cpp:33
Stack::toString
QString toString()
Definition: stackbrowser.cpp:245
Stack
Definition: stackbrowser.h:26
QList::append
void append(const T &value)
StackBrowser::canGoBack
bool canGoBack()
Definition: stackbrowser.cpp:377
QList::isEmpty
bool isEmpty() const
QString::isEmpty
bool isEmpty() const
Stack::deref
bool deref()
Definition: stackbrowser.h:44
HistoryItem::stack
Stack * stack()
Definition: stackbrowser.h:70
TraceCostItem::name
virtual QString name() const
Returns dynamic name info (without type)
Definition: tracedata.h:986
CostItem::data
virtual TraceData * data()
Definition: costitem.cpp:111
Stack::split
Stack * split(TraceFunction *)
Definition: stackbrowser.cpp:221
QString
QList
StackBrowser::select
HistoryItem * select(TraceFunction *)
Definition: stackbrowser.cpp:301
HistoryItem::next
HistoryItem * next()
Definition: stackbrowser.h:73
Stack::extendBottom
void extendBottom()
Definition: stackbrowser.cpp:42
EventTypeSet::realType
EventType * realType(int)
Definition: eventtype.cpp:462
HistoryItem::last
HistoryItem * last()
Definition: stackbrowser.h:72
Stack::calls
TraceCallList calls()
Definition: stackbrowser.h:48
Stack::contains
bool contains(TraceFunction *)
Definition: stackbrowser.cpp:177
Stack::extendTop
void extendTop()
Definition: stackbrowser.cpp:92
SubCost
Cost event counter, simple wrapper around a 64bit entity.
Definition: subcost.h:32
HistoryItem::setLast
void setLast(HistoryItem *h)
Definition: stackbrowser.h:74
QList::last
T & last()
Stack::refCount
int refCount() const
Definition: stackbrowser.h:45
TraceCall::called
TraceFunction * called(bool skipCycle=false) const
Definition: tracedata.cpp:1235
QList::removeLast
void removeLast()
Stack::top
TraceFunction * top()
Definition: stackbrowser.h:47
QList::prepend
void prepend(const T &value)
HistoryItem
Definition: stackbrowser.h:64
TraceCall
A call from one to another function.
Definition: tracedata.h:835
StackBrowser::goDown
HistoryItem * goDown()
Definition: stackbrowser.cpp:366
StackBrowser::canGoForward
bool canGoForward()
Definition: stackbrowser.cpp:382
HistoryItem::setNext
void setNext(HistoryItem *h)
Definition: stackbrowser.h:75
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:39:50 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
  • 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