1 /*
2     This file is part of KCachegrind.
3 
4     SPDX-FileCopyrightText: 2002-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
5 
6     SPDX-License-Identifier: GPL-2.0-only
7 */
8 
9 /*
10  * Classes holding profiling data for
11  * multiple tracefiles for one command.
12  * See class TraceData first.
13  */
14 
15 #ifndef TRACEDATA_H
16 #define TRACEDATA_H
17 
18 #include <qstring.h>
19 #include <qstringlist.h>
20 #include <qmap.h>
21 
22 #include "costitem.h"
23 #include "subcost.h"
24 #include "utils.h"
25 #include "addr.h"
26 #include "context.h"
27 #include "eventtype.h"
28 
29 class QFile;
30 
31 /**
32  * All cost items are classes prefixed with "Trace".
33  * "ProfileCostArray" holds basic cost metrics for the simplest, smallest
34  * trace entity: These are events counted for an instruction at
35  * a specific memory address of the traced program.
36  * All other cost items are derived from ProfileCostArray, and add needed
37  * cost metrics, e.g. for a call the number of calls that happened.
38  *
39  * Abstract, i.e. never instantiated cost items are
40  * - ProfileCostArray: Basic cost metrics (instr/read/write access + cache events)
41  * - TraceCallCost: Additional call count cost metric.
42  * - TraceInclusiveCost: Additional ProfileCostArray aggregated.
43  * - TraceListCost: Adds dependency to a list of ProfileCostArray's
44  * - TraceCallListCost: same for list of TraceCallCost's
45  * - TraceInclusiveListCost: same for list of TraceInclusiveCost's
46  * - TraceCostItem: Base for cost items for "interesting" costs:
47  *              TraceFunction, TraceClass, TraceFile, TraceObject
48  *
49  * The smallest Cachegrind output is trace data indexed by a source
50  * line number, a TracePartLine. Another one is a call from one
51  * source line of a function to another function, a TracePartLineCall.
52  * All other cost items derive the value by summation of cost metrics
53  * from TraceLineItem and TracePartLineCall costs; their cost is
54  * calculated lazy on demand and cached afterwards.
55  *
56  * For cost items, which are sums over all trace files read in, the
57  * summed cost metrics change when e.g. a new trace file is read.
58  * Thus, their cached costs are invalidated, and again recalculated
59  * only on demand. In the following list, theses cost items are called
60  * "dynamic", the other "fixed" (but neverless calculated lazy).
61  *
62  *  Cost Item          Type      Summation of ...
63  *
64  *  TracePartLineCall  fixed     Read from trace file
65  *  TracePartLine      fixed     Read from trace file
66  *  TracePartCall      fixed     TracePartLineCall's
67  *  TraceLineCall      dynamic   TracePartLineCall's
68  *  TraceCall          dynamic   TraceLineCall's
69  *  TraceLine          dynamic   TracePartLine's and TraceLineCall's
70  *  TracePartFunction  fixed     TracePartLine's / TracePartCall's
71  *  TraceFunction      dynamic   TraceLine's / TraceCall's (called from)
72  *  TracePartClass     fixed     TracePartFunction's
73  *  TraceClass         dynamic   TraceFunction's
74  *  TracePartFile      fixed     TracePartFunction's
75  *  TraceFile          dynamic   TraceFunction's
76  *  TracePartObject    fixed     TracePartFunction's
77  *  TraceObject        dynamic   TraceFunction's
78  *  TracePart          fixed     TracePartLine's
79  *  TraceData          dynamic   TracePart's
80  *
81  * As there exists only one TraceData object for a traced program, it is the
82  * owner of some "high level" cost items. The following shows the owner
83  * relationship of the cost item classes, together with references.
84  *
85  *  Cost Item          Owner (& back ref)   Other References to
86  *
87  *  TracePartLineCall  TraceLineCall
88  *  TracePartCall      TraceCall            TracePartLineCall's
89  *  TracePartLine      TraceLine            TracePartLineCall's
90  *  TracePartFunction  TraceFunction
91  *  TracePartClass     TraceClass           TracePart
92  *  TracePartFile      TraceFile            TracePart
93  *  TracePartObject    TraceObject          TracePart
94  *  TraceLineCall      TraceCall            TracePartLineCall's
95  *  TraceCall          TraceFunction        TracePartCall's
96  *  TraceLine          TraceData            TraceLineCall's
97  *  TraceFunction      TraceData            TraceCall's (calling)
98  *  TraceClass         TraceData
99  *  TraceFile          TraceData
100  *  TraceObject        TraceData
101  *  TracePart          TraceData
102  *  TraceData          Main Application
103  *
104  * Convention:
105  * - The owner has a factory method for owned objects,
106  *   and calls addXXX() to install references in other objects
107  * - The owner is first arg in a constructor.
108  */
109 
110 
111 class FixCost;
112 class FixCallCost;
113 class FixJump;
114 class FixPool;
115 class DynPool;
116 class Logger;
117 
118 class ProfileCostArray;
119 class EventType;
120 class EventTypeSet;
121 class EventTypeMapping;
122 class TraceJumpCost;
123 class TraceCallCost;
124 class TraceInclusiveCost;
125 
126 class TracePartInstr;
127 class TracePartInstrCall;
128 class TracePartLine;
129 class TracePartLineCall;
130 class TracePartCall;
131 class TracePartLineRegion;
132 class TracePartFunction;
133 class TracePartClass;
134 class TracePartObject;
135 class TracePartFile;
136 
137 class TraceInstr;
138 class TraceInstrJump;
139 class TraceInstrCall;
140 class TraceLine;
141 class TraceLineJump;
142 class TraceLineCall;
143 class TraceCall;
144 class TraceLineRegion;
145 class TraceFunctionSource;
146 class TraceFunction;
147 class TraceFunctionCycle;
148 class TraceClass;
149 class TraceObject;
150 class TraceFile;
151 class TracePart;
152 class TraceData;
153 
154 typedef QList<ProfileCostArray*> TraceCostList;
155 typedef QList<TraceJumpCost*> TraceJumpCostList;
156 typedef QList<TraceCallCost*> TraceCallCostList;
157 typedef QList<TraceInclusiveCost*> TraceInclusiveCostList;
158 
159 typedef QList<TracePartCall*> TracePartCallList;
160 typedef QList<TracePartInstr*> TracePartInstrList;
161 typedef QList<TracePartLine*> TracePartLineList;
162 typedef QList<TracePartLineRegion*> TracePartLineRegionList;
163 typedef QList<TracePartFunction*> TracePartFunctionList;
164 typedef QList<TracePartInstrCall*> TracePartInstrCallList;
165 typedef QList<TracePartLineCall*> TracePartLineCallList;
166 typedef QList<TracePart*> TracePartList;
167 
168 typedef QList<TraceInstr*> TraceInstrList;
169 typedef QList<TraceLine*> TraceLineList;
170 typedef QList<TraceInstrJump*> TraceInstrJumpList;
171 typedef QList<TraceLineJump*> TraceLineJumpList;
172 typedef QList<TraceInstrCall*> TraceInstrCallList;
173 typedef QList<TraceLineCall*> TraceLineCallList;
174 typedef QList<TraceCall*> TraceCallList;
175 typedef QList<TraceFile*> TraceFileList;
176 typedef QList<TraceLineRegion*> TraceLineRegionList;
177 typedef QList<TraceFunctionSource*> TraceFunctionSourceList;
178 typedef QList<TraceFunction*> TraceFunctionList;
179 typedef QList<TraceFunctionCycle*> TraceFunctionCycleList;
180 typedef QMap<QString, TraceObject> TraceObjectMap;
181 typedef QMap<QString, TraceClass> TraceClassMap;
182 typedef QMap<QString, TraceFile> TraceFileMap;
183 typedef QMap<QString, TraceFunction> TraceFunctionMap;
184 typedef QMap<uint, TraceLine> TraceLineMap;
185 typedef QMap<Addr, TraceInstr> TraceInstrMap;
186 
187 
188 /**
189  * Cost of a (conditional) jump.
190  */
191 class TraceJumpCost: public CostItem
192 {
193 public:
194     explicit TraceJumpCost(ProfileContext*);
195     ~TraceJumpCost() override;
196 
197     // reimplementations for cost addition
198     QString costString(EventTypeSet* m) override;
199     void clear() override;
200 
201     void addCost(TraceJumpCost*);
202 
203     // additional cost metrics
204     SubCost followedCount();
205     SubCost executedCount();
addFollowedCount(SubCost c)206     void addFollowedCount(SubCost c) { _followedCount += c; }
addExecutedCount(SubCost c)207     void addExecutedCount(SubCost c) { _executedCount += c; }
208 
209 protected:
210     SubCost _executedCount, _followedCount;
211 };
212 
213 
214 
215 /**
216  * Cost item with additional call count metric.
217  */
218 class TraceCallCost: public ProfileCostArray
219 {
220 public:
221     explicit TraceCallCost(ProfileContext*);
222     ~TraceCallCost() override;
223 
224     // reimplementations for cost addition
225     QString costString(EventTypeSet* m) override;
226     void clear() override;
227 
228     // additional cost metric
229     SubCost callCount();
230     QString prettyCallCount();
231     void addCallCount(SubCost c);
232 
233 protected:
234     SubCost _callCount;
235 };
236 
237 
238 /**
239  * Cost item with additional inclusive metric
240  */
241 class TraceInclusiveCost: public ProfileCostArray
242 {
243 public:
244     explicit TraceInclusiveCost(ProfileContext*);
245     ~TraceInclusiveCost() override;
246 
247     // reimplementations for cost addition
248     QString costString(EventTypeSet* m) override;
249     void clear() override;
250 
251     // additional cost metric
252     ProfileCostArray* inclusive();
253     void addInclusive(ProfileCostArray*);
254 
255 protected:
256     ProfileCostArray _inclusive;
257 };
258 
259 
260 /**
261  * Cost Item
262  * depends on a list of cost items.
263  */
264 class TraceListCost: public ProfileCostArray
265 {
266 public:
267     explicit TraceListCost(ProfileContext*);
268     ~TraceListCost() override;
269 
270     // reimplementation for dependency list
271     void update() override;
272 
deps()273     TraceCostList& deps() { return _deps; }
274     void addDep(ProfileCostArray*);
275     ProfileCostArray* findDepFromPart(TracePart*);
276 
277 protected:
278     // overwrite in subclass to change update behaviour
onlyActiveParts()279     virtual bool onlyActiveParts() { return false; }
280 
281     TraceCostList _deps;
282 
283 private:
284     // very temporary: cached
285     ProfileCostArray* _lastDep;
286 };
287 
288 
289 /**
290  * Jump Cost Item
291  * depends on a list of Jump cost items.
292  */
293 class TraceJumpListCost: public TraceJumpCost
294 {
295 public:
296     explicit TraceJumpListCost(ProfileContext*);
297     ~TraceJumpListCost() override;
298 
299     // reimplementation for dependency list
300     void update() override;
301 
deps()302     TraceJumpCostList deps() { return _deps; }
303     void addDep(TraceJumpCost*);
304     TraceJumpCost* findDepFromPart(TracePart*);
305 
306 protected:
307     // overwrite in subclass to change update behaviour
onlyActiveParts()308     virtual bool onlyActiveParts() { return false; }
309 
310     TraceJumpCostList _deps;
311 
312 private:
313     // very temporary: cached
314     TraceJumpCost* _lastDep;
315 };
316 
317 
318 
319 
320 /**
321  * Call Cost Item
322  * depends on a list of Call cost items.
323  */
324 class TraceCallListCost: public TraceCallCost
325 {
326 public:
327     explicit TraceCallListCost(ProfileContext*);
328     ~TraceCallListCost() override;
329 
330     // reimplementation for dependency list
331     void update() override;
332 
deps()333     TraceCallCostList deps() { return _deps; }
334     void addDep(TraceCallCost*);
335     TraceCallCost* findDepFromPart(TracePart*);
336 
337 protected:
338     // overwrite in subclass to change update behaviour
onlyActiveParts()339     virtual bool onlyActiveParts() { return false; }
340 
341     TraceCallCostList _deps;
342 
343 private:
344     // very temporary: cached
345     TraceCallCost* _lastDep;
346 };
347 
348 
349 /**
350  * Inclusive Cost Item depends on a list of inclusive cost items.
351  */
352 class TraceInclusiveListCost: public TraceInclusiveCost
353 {
354 public:
355     explicit TraceInclusiveListCost(ProfileContext*);
356     ~TraceInclusiveListCost() override;
357 
358     // reimplementation for dependency
359     void update() override;
360 
deps()361     TraceInclusiveCostList deps() { return _deps; }
362     void addDep(TraceInclusiveCost*);
363     TraceInclusiveCost* findDepFromPart(TracePart*);
364 
365 protected:
366     // overwrite in subclass to change update behaviour
onlyActiveParts()367     virtual bool onlyActiveParts() { return false; }
368 
369     TraceInclusiveCostList _deps;
370 
371 private:
372     // very temporary: cached
373     TraceInclusiveCost* _lastDep;
374 };
375 
376 
377 
378 
379 
380 /*-----------------------------------------------------------------
381  * Classes for cost items of one trace file, i.e. a "trace part"
382  *-----------------------------------------------------------------
383  */
384 
385 /**
386  * Cost of jump at a instruction code address from a trace file.
387  */
388 class TracePartInstrJump: public TraceJumpCost
389 {
390 public:
391     TracePartInstrJump(TraceInstrJump*, TracePartInstrJump*);
392     ~TracePartInstrJump() override;
393 
394     // fix cost item
update()395     void update() override {}
instrJump()396     TraceInstrJump* instrJump() const { return (TraceInstrJump*) _dep; }
next()397     TracePartInstrJump* next() const { return _next; }
398 
399 private:
400     // chaining all parts for InstrJump
401     TracePartInstrJump* _next;
402 };
403 
404 
405 /**
406  * Cost of a call at a instruction code address from a trace file.
407  * Cost is always up to date, no lazy update needed.
408  */
409 class TracePartInstrCall: public TraceCallCost
410 {
411 public:
412     explicit TracePartInstrCall(TraceInstrCall*);
413     ~TracePartInstrCall() override;
414 
415     // fix cost item
update()416     void update() override {}
instrCall()417     TraceInstrCall* instrCall() const { return (TraceInstrCall*) _dep; }
418 };
419 
420 
421 /**
422  * Cost of a code instruction address from a trace file.
423  * Cost is always up to date, no lazy update needed.
424  */
425 class TracePartInstr: public ProfileCostArray
426 {
427 public:
428     explicit TracePartInstr(TraceInstr*);
429     ~TracePartInstr() override;
430 
431     // fix cost item
update()432     void update() override {}
433 
instr()434     TraceInstr* instr() const { return (TraceInstr*)_dep; }
435 };
436 
437 
438 /**
439  * Cost of jump at a source line from a trace file.
440  */
441 class TracePartLineJump: public TraceJumpCost
442 {
443 public:
444     explicit TracePartLineJump(TraceLineJump*);
445     ~TracePartLineJump() override;
446 
447     // fix cost item
update()448     void update() override {}
lineJump()449     TraceLineJump* lineJump() const { return (TraceLineJump*) _dep; }
450 };
451 
452 
453 /**
454  * Cost of a call at a line from a trace file.
455  * Cost is always up to date, no lazy update needed.
456  */
457 class TracePartLineCall: public TraceCallCost
458 {
459 public:
460     explicit TracePartLineCall(TraceLineCall*);
461     ~TracePartLineCall() override;
462 
463     // fix cost item
update()464     void update() override {}
lineCall()465     TraceLineCall* lineCall() const { return (TraceLineCall*) _dep; }
466 };
467 
468 
469 
470 /**
471  * Cost of a line from a trace file.
472  * Cost is always up to date, no lazy update needed.
473  */
474 class TracePartLine: public ProfileCostArray
475 {
476 public:
477     explicit TracePartLine(TraceLine*);
478     ~TracePartLine() override;
479 
480     // fix cost item
update()481     void update() override {}
482 
line()483     TraceLine* line() const { return (TraceLine*)_dep; }
484 };
485 
486 
487 /**
488  * Cost of a source region.
489  */
490 class TracePartLineRegion: public TraceInclusiveCost
491 {
492 public:
493     explicit TracePartLineRegion(TraceLineRegion*);
494     ~TracePartLineRegion() override;
495 
496     void update() override;
497 
region()498     TraceLineRegion* region() const { return (TraceLineRegion*)_dep; }
499 };
500 
501 
502 /**
503  * Cost of a call at a function to another function,
504  * from a single trace file.
505  */
506 class TracePartCall: public TraceCallListCost
507 {
508 public:
509     explicit TracePartCall(TraceCall* call);
510     ~TracePartCall() override;
511 
512     // calls a function itself?
513     bool isRecursion();
514 
515     // reimplementation for dependency list
516     void update() override;
517 
call()518     TraceCall* call() const { return (TraceCall*)_dep; }
519 
setFirstFixCallCost(FixCallCost * fc)520     FixCallCost* setFirstFixCallCost(FixCallCost* fc)
521     { FixCallCost* t = _firstFixCallCost; _firstFixCallCost = fc; return t; }
firstFixCallCost()522     FixCallCost* firstFixCallCost() const { return _firstFixCallCost; }
523 
524 private:
525     FixCallCost* _firstFixCallCost;
526 };
527 
528 
529 /**
530  * Cost of a function,
531  * from a single trace file.
532  */
533 class TracePartFunction: public TraceInclusiveCost
534 {
535 public:
536     TracePartFunction(TraceFunction*,
537                       TracePartObject*, TracePartFile*);
538     ~TracePartFunction() override;
539 
540     void update() override;
541     QString costString(EventTypeSet* m) override;
542 
543     void addPartInstr(TracePartInstr*);
544     void addPartLine(TracePartLine*);
545     void addPartCaller(TracePartCall*);
546     void addPartCalling(TracePartCall*);
547 
function()548     TraceFunction* function() { return (TraceFunction*) _dep; }
partObject()549     TracePartObject* partObject() { return _partObject; }
partClass()550     TracePartClass* partClass() { return _partClass; }
partFile()551     TracePartFile* partFile() { return _partFile; }
partCallers()552     const TracePartCallList& partCallers() { return _partCallers; }
partCallings()553     const TracePartCallList& partCallings() { return _partCallings; }
setPartObject(TracePartObject * o)554     void setPartObject(TracePartObject* o) { _partObject = o; }
setPartClass(TracePartClass * c)555     void setPartClass(TracePartClass* c) { _partClass = c; }
setPartFile(TracePartFile * f)556     void setPartFile(TracePartFile* f) { _partFile = f; }
557 
558     /* for linked list of FixXXX objects */
setFirstFixCost(FixCost * fc)559     FixCost* setFirstFixCost(FixCost* fc)
560     { FixCost* t = _firstFixCost; _firstFixCost = fc; return t; }
firstFixCost()561     FixCost* firstFixCost() const { return _firstFixCost; }
setFirstFixJump(FixJump * fj)562     FixJump* setFirstFixJump(FixJump* fj)
563     { FixJump* t = _firstFixJump; _firstFixJump = fj; return t; }
firstFixJump()564     FixJump* firstFixJump() const { return _firstFixJump; }
565 
566     // additional cost metrics
567     SubCost calledCount();
568     SubCost callingCount();
569     QString prettyCalledCount();
570     QString prettyCallingCount();
571     int calledContexts();
572     int callingContexts();
573 
574 private:
575     TracePartObject* _partObject;
576     TracePartClass* _partClass;
577     TracePartFile* _partFile;
578 
579     TracePartCallList _partCallings;
580     TracePartCallList _partCallers;
581     TracePartInstrList _partInstr;
582     TracePartLineList _partLines;
583 
584     // cached
585     SubCost _calledCount, _callingCount;
586     int _calledContexts, _callingContexts;
587 
588     FixCost* _firstFixCost;
589     FixJump* _firstFixJump;
590 };
591 
592 
593 /**
594  * Cost of a class,
595  * from a single trace file.
596  */
597 class TracePartClass: public TraceInclusiveListCost
598 {
599 public:
600     explicit TracePartClass(TraceClass*);
601     ~TracePartClass() override;
602 
603     QString prettyName() const override;
604 
cls()605     TraceClass* cls() { return (TraceClass*)_dep; }
addPartFunction(TracePartFunction * f)606     void addPartFunction(TracePartFunction* f) { addDep(f); }
607 };
608 
609 
610 /**
611  * Cost of a source file,
612  * from a single trace file.
613  */
614 class TracePartFile: public TraceInclusiveListCost
615 {
616 public:
617     explicit TracePartFile(TraceFile*);
618     ~TracePartFile() override;
619 
file()620     TraceFile* file() { return (TraceFile*)_dep; }
addPartFunction(TracePartFunction * f)621     void addPartFunction(TracePartFunction* f) { addDep(f); }
622 };
623 
624 
625 /**
626  * Cost of a object,
627  * from a single trace file.
628  */
629 class TracePartObject: public TraceInclusiveListCost
630 {
631 public:
632     explicit TracePartObject(TraceObject*);
633     ~TracePartObject() override;
634 
object()635     TraceObject* object() const { return (TraceObject*)_dep; }
addPartFunction(TracePartFunction * f)636     void addPartFunction(TracePartFunction* f) { addDep(f); }
637 };
638 
639 
640 
641 /**
642  * A Trace Part: All data read from a trace file, containing all costs
643  * that happened in a specified time interval of the executed command.
644  */
645 class TracePart: public TraceListCost
646 {
647 public:
648     explicit TracePart(TraceData*);
649     ~TracePart() override;
650 
part()651     TracePart* part() override { return this; }
part()652     const TracePart* part() const override { return this; }
653 
654     QString shortName() const;
655     QString prettyName() const override;
656     /// @return Name of the file this part was loaded from
name()657     QString name() const override { return _name; }
description()658     QString description() const { return _descr; }
trigger()659     QString trigger() const { return _trigger; }
timeframe()660     QString timeframe() const { return _timeframe; }
version()661     QString version() const { return _version; }
partNumber()662     int partNumber() const { return _number; }
threadID()663     int threadID() const { return _tid; }
processID()664     int processID() const { return _pid; }
setDescription(const QString & d)665     void setDescription(const QString& d) { _descr = d; }
setTrigger(const QString & t)666     void setTrigger(const QString& t) { _trigger = t; }
setTimeframe(const QString & t)667     void setTimeframe(const QString& t) { _timeframe = t; }
setVersion(const QString & v)668     void setVersion(const QString& v) { _version = v; }
setName(const QString & n)669     void setName(const QString& n) { _name = n; }
670     void setPartNumber(int n);
671     void setThreadID(int t);
672     void setProcessID(int p);
totals()673     ProfileCostArray* totals() { return &_totals; }
674     /* passes ownership of mapping */
setEventMapping(EventTypeMapping * sm)675     void setEventMapping(EventTypeMapping* sm) { _eventTypeMapping = sm; }
eventTypeMapping()676     EventTypeMapping* eventTypeMapping() { return _eventTypeMapping; }
677 
678     // returns true if something changed
679     bool activate(bool);
isActive()680     bool isActive() const { return _active; }
681 
682     // for sorting
683     bool operator<(const TracePart&) const;
684 
685 private:
686     QString _name;
687     QString _descr;
688     QString _trigger;
689     QString _timeframe;
690     QString _version;
691 
692     int _number, _tid, _pid;
693 
694     bool _active;
695 
696     // the totals line
697     ProfileCostArray _totals;
698 
699     // event type mapping for all fix costs of this part
700     EventTypeMapping* _eventTypeMapping;
701 };
702 
703 
704 
705 /*-----------------------------------------------------------------
706  * Classes for cost items summed up from multiple trace parts
707  *-----------------------------------------------------------------
708  */
709 
710 
711 /**
712  * A jump from an instruction to another inside of a function
713  */
714 class TraceInstrJump: public TraceJumpCost
715 {
716 public:
717     TraceInstrJump(TraceInstr* instrFrom, TraceInstr* instrTo,
718                    bool isCondJump);
719     ~TraceInstrJump() override;
720 
721     QString name() const override;
722 
723     void update() override;
724 
instrFrom()725     TraceInstr* instrFrom() const { return _instrFrom; }
instrTo()726     TraceInstr* instrTo() const { return _instrTo; }
isCondJump()727     bool isCondJump() const { return _isCondJump; }
728 
729     // part factory
730     TracePartInstrJump* partInstrJump(TracePart*);
731 
732 private:
733     TraceInstr *_instrFrom, *_instrTo;
734     bool _isCondJump;
735     // list of parts for this InstrJump
736     TracePartInstrJump* _first;
737 };
738 
739 
740 /**
741  * A jump from one line to another inside of a function.
742  */
743 class TraceLineJump: public TraceJumpListCost
744 {
745 public:
746     TraceLineJump(TraceLine* lineFrom, TraceLine* lineTo,
747                   bool isCondJump);
748     ~TraceLineJump() override;
749 
750     QString name() const override;
751 
lineFrom()752     TraceLine* lineFrom() const { return _lineFrom; }
lineTo()753     TraceLine* lineTo() const { return _lineTo; }
isCondJump()754     bool isCondJump() { return _isCondJump; }
755 
756     // part factory
757     TracePartLineJump* partLineJump(TracePart*);
758 
759 protected:
onlyActiveParts()760     bool onlyActiveParts() override { return true; }
761 
762 private:
763     TraceLine *_lineFrom, *_lineTo;
764     bool _isCondJump;
765 };
766 
767 
768 /**
769  * A call from an instruction of one function to another function
770  */
771 class TraceInstrCall: public TraceCallListCost
772 {
773 public:
774     TraceInstrCall(TraceCall* call, TraceInstr* instr);
775     ~TraceInstrCall() override;
776 
777     QString name() const override;
778 
instr()779     TraceInstr* instr() const { return _instr; }
call()780     TraceCall* call() const { return _call; }
781 
782     // part factory
783     TracePartInstrCall* partInstrCall(TracePart*, TracePartCall*);
784 
785 protected:
onlyActiveParts()786     bool onlyActiveParts() override { return true; }
787 
788 private:
789     TraceInstr* _instr;
790     TraceCall* _call;
791 };
792 
793 
794 /**
795  * A call from a line of one function to another function.
796  */
797 class TraceLineCall: public TraceCallListCost
798 {
799 public:
800     TraceLineCall(TraceCall* call, TraceLine* line);
801     ~TraceLineCall() override;
802 
803     QString name() const override;
804 
line()805     TraceLine* line() const { return _line; }
call()806     TraceCall* call() const { return _call; }
807 
808     // part factory
809     TracePartLineCall* partLineCall(TracePart*, TracePartCall*);
810 
811 protected:
onlyActiveParts()812     bool onlyActiveParts() override { return true; }
813 
814 private:
815     TraceLine* _line;
816     TraceCall* _call;
817 };
818 
819 
820 /**
821  * A call from one to another function.
822  * Consists of a list a TraceLineCalls
823  */
824 class TraceCall: public TraceCallListCost
825 {
826 public:
827     TraceCall(TraceFunction* caller, TraceFunction* called);
828     ~TraceCall() override;
829 
830     QString name() const override;
831 
832     // calls a function itself?
isRecursion()833     bool isRecursion() { return _caller == _called; }
834 
835     // return cycle number >0 if call is inside of a cycle
836     int inCycle();
837     // we need some special handling for cycle calls
838     void update() override;
839 
840     void invalidateDynamicCost();
841 
842     // factories
843     TracePartCall* partCall(TracePart*,
844                             TracePartFunction*, TracePartFunction*);
845     TraceLineCall* lineCall(TraceLine*);
846     TraceInstrCall* instrCall(TraceInstr*);
847 
848     TraceFunction* caller(bool skipCycle=false) const;
849     TraceFunction* called(bool skipCycle=false) const;
850     QString callerName(bool skipCycle=false) const;
851     QString calledName(bool skipCycle=false) const;
lineCalls()852     const TraceLineCallList& lineCalls() const { return _lineCalls; }
instrCalls()853     const TraceInstrCallList& instrCalls() const { return _instrCalls; }
854 
setFirstFixCost(FixCallCost * fc)855     FixCallCost* setFirstFixCost(FixCallCost* fc)
856     { FixCallCost* t = _firstFixCost; _firstFixCost = fc; return t; }
857 
858 protected:
onlyActiveParts()859     bool onlyActiveParts() override { return true; }
860 
861 private:
862     TraceInstrCallList _instrCalls;
863     TraceLineCallList _lineCalls;
864     TraceFunction* _caller;
865     TraceFunction* _called;
866 
867     FixCallCost* _firstFixCost;
868 };
869 
870 
871 /**
872  * A code instruction address of the program.
873  * Consists of a list a TracePartInstr from different trace files
874  * and a list of TraceInstrCalls if there are calls from this address.
875  */
876 class TraceInstr: public TraceListCost
877 {
878 public:
879     TraceInstr();
880     ~TraceInstr() override;
881 
882     QString name() const override;
883     QString prettyName() const override;
884 
isValid()885     bool isValid() { return _addr != Addr(0); }
886 
887     // factories
888     TracePartInstr* partInstr(TracePart* part,
889                               TracePartFunction* partFunction);
890     TraceInstrJump* instrJump(TraceInstr* to, bool isCondJump);
891 
892     void addInstrCall(TraceInstrCall*);
893 
addr()894     Addr addr() const { return _addr; }
function()895     TraceFunction* function() const { return _function; }
line()896     TraceLine* line() const { return _line; }
instrJumps()897     const TraceInstrJumpList& instrJumps() const { return _instrJumps; }
instrCalls()898     const TraceInstrCallList& instrCalls() const { return _instrCalls; }
899     bool hasCost(EventType*);
900 
901     // only to be called after default constructor
setAddr(const Addr addr)902     void setAddr(const Addr addr) { _addr = addr; }
setFunction(TraceFunction * f)903     void setFunction(TraceFunction* f) { _function = f; }
setLine(TraceLine * l)904     void setLine(TraceLine* l) { _line = l; }
905 
906 protected:
onlyActiveParts()907     bool onlyActiveParts() override { return true; }
908 
909 private:
910     Addr _addr;
911     TraceFunction* _function;
912     TraceLine* _line;
913 
914     TraceInstrJumpList _instrJumps;
915     TraceInstrCallList _instrCalls;
916 };
917 
918 
919 /**
920  * A source line of the program.
921  * Consists of a list a TracePartLines from different trace files
922  * and a list of TraceLineCalls if there are calls from this line.
923  */
924 class TraceLine: public TraceListCost
925 {
926 public:
927     TraceLine();
928     ~TraceLine() override;
929 
930     QString name() const override;
931     QString prettyName() const override;
932 
933     // factories
934     TracePartLine* partLine(TracePart* part,
935                             TracePartFunction* partFunction);
936     TraceLineJump* lineJump(TraceLine* to, bool isCondJump);
937 
938     void addLineCall(TraceLineCall*);
939 
940 
isValid()941     bool isValid() { return _sourceFile != nullptr; }
942     bool hasCost(EventType*);
functionSource()943     TraceFunctionSource* functionSource() const { return _sourceFile; }
lineno()944     uint lineno() const { return _lineno; }
lineCalls()945     const TraceLineCallList& lineCalls() const { return _lineCalls; }
lineJumps()946     const TraceLineJumpList& lineJumps() const { return _lineJumps; }
947 
948     // only to be called after default constructor
setSourceFile(TraceFunctionSource * sf)949     void setSourceFile(TraceFunctionSource* sf) { _sourceFile = sf; }
setLineno(uint lineno)950     void setLineno(uint lineno) { _lineno = lineno; }
951 
952 protected:
onlyActiveParts()953     bool onlyActiveParts() override { return true; }
954 
955 private:
956     TraceFunctionSource* _sourceFile;
957     uint _lineno;
958 
959     TraceLineJumpList _lineJumps;
960     TraceLineCallList _lineCalls;
961 };
962 
963 
964 /*
965  * Base class for all costs which
966  * represent "interesting" items or group of items
967  * with settable name and inclusive cost
968  */
969 class TraceCostItem: public TraceInclusiveListCost
970 {
971 public:
972     explicit TraceCostItem(ProfileContext*);
973     ~TraceCostItem() override;
974 
name()975     QString name() const override { return _name; }
setName(const QString & name)976     virtual void setName(const QString& name) { _name = name; }
977 
978 protected:
onlyActiveParts()979     bool onlyActiveParts() override { return true; }
980 
981 protected:
982     QString _name;
983 };
984 
985 
986 /**
987  * Cost of a source region.
988  */
989 class TraceLineRegion: public TraceInclusiveListCost
990 {
991 public:
992     TraceLineRegion(uint from, uint to, QString name);
993     ~TraceLineRegion() override;
994 
995     void update() override;
996 
from()997     uint from() const { return _from; }
to()998     uint to() const { return _to; }
name()999     QString name() const override { return _name; }
1000 
1001     // factories
1002     TracePartLine* partLineRegion(TracePart* part,
1003                                   TracePartFunction* partFunction);
1004 private:
1005     uint _from, _to;
1006     QString _name;
1007 };
1008 
1009 
1010 /**
1011  * A container helper class for TraceFunction for source lines
1012  * where a function is implemented in.
1013  * With inlining, lines of the same function can come from
1014  * different source files.
1015  * An instance of this class holds all lines of one source file
1016  * for a function in a map
1017  */
1018 class TraceFunctionSource: public ProfileCostArray
1019 {
1020 public:
1021     TraceFunctionSource(TraceFunction*, TraceFile*);
1022     ~TraceFunctionSource() override;
1023 
1024     QString name() const override;
1025 
1026     // reimplementation for dependency map
1027     void update() override;
1028 
file()1029     TraceFile* file() const { return _file; }
function()1030     TraceFunction* function() const { return _function; }
1031     uint firstLineno();
1032     uint lastLineno();
1033     TraceLineMap* lineMap();
1034 
1035     void invalidateDynamicCost();
1036 
1037     /* factories */
1038     TraceLine* line(uint lineno, bool createNew = true);
1039     TraceLineRegion* region(uint from, uint to, QString name,
1040                             bool createNew = true);
1041 
1042 private:
1043     TraceFile* _file;
1044     TraceFunction* _function;
1045     TraceLineMap* _lineMap;
1046     TraceLine* _line0;
1047     TraceLineRegionList* _regions;
1048 
1049     bool _lineMapFilled;
1050 };
1051 
1052 
1053 /**
1054  * For temporary association of objects with TraceFunctions.
1055  * Used in coverage analysis and TreeMap drawing.
1056  */
1057 class TraceAssociation
1058 {
1059 public:
1060     /**
1061      * Creates an invalid association.
1062      */
1063     TraceAssociation();
1064     virtual ~TraceAssociation();
1065 
1066     // for runtime detection
rtti()1067     virtual int rtti() { return 0; }
1068 
1069     /**
1070      * Could we set the function association to ourself?
1071      * This only can return false if this is a unique association.
1072      */
1073     bool isAssociated();
1074 
1075     /**
1076      * reset function to associate this object to.
1077      * returns true if association could be established
1078      */
1079     bool setFunction(TraceFunction*);
function()1080     TraceFunction* function() { return _function; }
1081 
invalidate()1082     void invalidate() { _valid = false; }
isValid()1083     bool isValid() { return _valid; }
1084 
1085     /**
1086      * Delete all associations in TraceFunctions of data with
1087      * rtti runtime info. rtti = 0: delete ALL associations.
1088      */
1089     static void clear(TraceData* data, int rtti);
1090 
1091     /**
1092      * Invalidate all associations in TraceFunctions of data with
1093      * rtti runtime info. rtti = 0: Invalidate ALL associations.
1094      */
1095     static void invalidate(TraceData* data, int rtti);
1096 
1097 protected:
1098     TraceFunction* _function;
1099     bool _valid;
1100 };
1101 
1102 typedef QList<TraceAssociation*> TraceAssociationList;
1103 
1104 /**
1105  * A traced function
1106  *
1107  * References to functions are stored in
1108  *  (1) a function map in TraceData (by value)
1109  *  (2) a TraceClass
1110  */
1111 class TraceFunction: public TraceCostItem
1112 {
1113 public:
1114     TraceFunction();
1115     TraceFunction(TraceData* data, const QString& name,
1116                   TraceClass* cls, TraceFile* file, TraceObject* object);
1117     ~TraceFunction() override;
1118 
1119     void update() override;
1120 
1121     // this invalidate all subcosts of function depending on
1122     // active status of parts
1123     void invalidateDynamicCost();
1124 
1125     void addCaller(TraceCall*);
1126 
1127     // factories
1128     TraceCall* calling(TraceFunction* called);
1129     TraceLine* line(TraceFile*, uint lineno, bool createNew = true);
1130     TraceInstr* instr(Addr addr, bool createNew = true);
1131     TracePartFunction* partFunction(TracePart*,
1132                                     TracePartFile*, TracePartObject*);
1133 
1134     /**
1135      * Returns empty string if location is fully unknown.
1136      * Use prettyLocation for single user-visible string.
1137      * A function can have a lot of code from different sources (inlined);
1138      * maxItems limits this list. Default is full list
1139      */
1140     QString location(int maxFiles = 0) const;
1141 
1142     QString prettyName() const override;
1143     QString formattedName() const override;
1144     static QString prettyEmptyName();
1145     QString prettyLocation(int maxFiles = 0) const;
1146     QString prettyNameWithLocation(int maxFiles = 1) const;
1147     void addPrettyLocation(QString&, int maxFiles = 1) const;
1148     // type + name + location
1149     QString info() const;
1150 
cls()1151     TraceClass* cls() const { return _cls; }
file()1152     TraceFile* file() const { return _file; }
object()1153     TraceObject* object() const { return _object; }
1154     // get the source file with lines from function declaration (not inlined)
1155     TraceFunctionSource* sourceFile(TraceFile* file = nullptr,
1156                                     bool createNew = false);
sourceFiles()1157     const TraceFunctionSourceList& sourceFiles() const
1158     { return _sourceFiles; }
1159     TraceCallList callers(bool skipCycle=false) const;
1160     const TraceCallList& callings(bool skipCycle=false) const;
1161 
1162     Addr firstAddress() const;
1163     Addr lastAddress() const;
1164     TraceInstrMap* instrMap();
1165 
1166     // cost metrics
1167     SubCost calledCount();
1168     SubCost callingCount();
1169     QString prettyCalledCount();
1170     QString prettyCallingCount();
1171     int calledContexts();
1172     int callingContexts();
1173 
1174     // only to be called after default constructor
setFile(TraceFile * file)1175     void setFile(TraceFile* file) { _file = file; }
setObject(TraceObject * object)1176     void setObject(TraceObject* object) { _object = object; }
setClass(TraceClass * cls)1177     void setClass(TraceClass* cls) { _cls = cls; }
1178     //void setMapIterator(TraceFunctionMap::Iterator it) { _myMapIterator = it; }
1179 
1180     // see TraceFunctionAssociation
1181     void addAssociation(TraceAssociation* a);
1182     void removeAssociation(TraceAssociation* a);
1183     void removeAssociation(int rtti, bool reallyDelete = true);
1184     void invalidateAssociation(int rtti);
1185     TraceAssociation* association(int rtti);
1186 
1187     // cycles
setCycle(TraceFunctionCycle * c)1188     void setCycle(TraceFunctionCycle* c) { _cycle = c; }
cycle()1189     TraceFunctionCycle* cycle() { return _cycle; }
1190     bool isCycle();
1191     bool isCycleMember();
1192     void cycleReset();
1193     void cycleDFS(int d, int& pNo, TraceFunction** pTop);
1194 
1195 protected:
1196     TraceCallList _callers; // list of calls we are called from
1197     TraceCallList _callings; // list of calls we are calling (we are owner)
1198     TraceFunctionCycle* _cycle;
1199 
1200 private:
1201     bool isUniquePrefix(const QString&) const;
1202     //TraceFunctionMap::Iterator _myMapIterator;
1203 
1204     TraceClass* _cls;
1205     TraceObject* _object;
1206     TraceFile* _file;
1207 
1208     TraceFunctionSourceList _sourceFiles; // we are owner
1209     TraceInstrMap* _instrMap; // we are owner
1210     bool _instrMapFilled;
1211 
1212     // see TraceAssociation
1213     TraceAssociationList _associations;
1214 
1215     // for cycle detection
1216     int _cycleLow;
1217     TraceFunction* _cycleStackDown;
1218 
1219     // cached
1220     SubCost _calledCount, _callingCount;
1221     int _calledContexts, _callingContexts;
1222 };
1223 
1224 
1225 /**
1226  * A cycle of recursive calling functions.
1227  *
1228  * This is itself shown as a function
1229  */
1230 class TraceFunctionCycle: public TraceFunction
1231 {
1232 public:
1233     TraceFunctionCycle(TraceFunction*, int n);
1234 
1235     // this removes all members from this cycle
1236     void init();
1237     void add(TraceFunction*);
1238     // this sets up the cycle once members are added
1239     void setup();
1240 
base()1241     TraceFunction* base() const { return _base; }
cycleNo()1242     int cycleNo() const { return _cycleNo; }
members()1243     const TraceFunctionList& members() const { return _members; }
1244 
1245 private:
1246     TraceFunction* _base;
1247     int _cycleNo;
1248 
1249     TraceFunctionList _members;
1250 };
1251 
1252 
1253 /**
1254  * A C++ Class / Namespace
1255  *
1256  * If a function symbol has a prefix ending in "::",
1257  * the prefix is supposed to be a class/namespace specifier.
1258  * Without such a prefix, we put a symbol in the "(global)" namespace.
1259  */
1260 class TraceClass: public TraceCostItem
1261 {
1262 public:
1263     TraceClass();
1264     ~TraceClass() override;
1265 
1266     QString prettyName() const override;
1267     static QString prettyEmptyName();
1268 
1269     void addFunction(TraceFunction*);
functions()1270     const TraceFunctionList& functions() const { return _functions; }
1271 
1272     // part factory
1273     TracePartClass* partClass(TracePart*);
1274 
1275 private:
1276     TraceFunctionList _functions;
1277 };
1278 
1279 
1280 
1281 /**
1282  * A source file containing function definitions
1283  */
1284 class TraceFile: public TraceCostItem
1285 {
1286 public:
1287     TraceFile();
1288     ~TraceFile() override;
1289 
1290     void setDirectory(const QString& dir);
resetDirectory()1291     void resetDirectory() { _dir = QString(); }
1292     QString directory();
1293 
1294     void addFunction(TraceFunction*);
1295     void addSourceFile(TraceFunctionSource*);
1296 
1297     // without path
1298     QString shortName() const;
1299     QString prettyName() const override;
1300     QString prettyLongName() const;
1301     static QString prettyEmptyName();
functions()1302     const TraceFunctionList& functions() const { return _functions; }
sourceFiles()1303     const TraceFunctionSourceList& sourceFiles() const
1304     { return _sourceFiles; }
1305 
1306     // part factory
1307     TracePartFile* partFile(TracePart*);
1308 
1309 private:
1310     TraceFunctionList _functions;
1311     TraceFunctionSourceList _sourceFiles;
1312     QString _dir;
1313 };
1314 
1315 
1316 /**
1317  * A object containing a text segment (shared lib/executable)
1318  * with defined functions
1319  */
1320 class TraceObject: public TraceCostItem
1321 {
1322 public:
1323     TraceObject();
1324     ~TraceObject() override;
1325 
1326     void setDirectory(const QString& dir);
resetDirectory()1327     void resetDirectory() { _dir = QString(); }
1328     QString directory();
1329 
1330     void addFunction(TraceFunction*);
1331 
1332     QString shortName() const;
1333     QString prettyName() const override;
1334     static QString prettyEmptyName();
functions()1335     const TraceFunctionList& functions() const { return _functions; }
1336 
1337     // part factory
1338     TracePartObject* partObject(TracePart*);
1339 
1340 private:
1341     TraceFunctionList _functions;
1342     QString _dir;
1343 };
1344 
1345 
1346 
1347 /**
1348  * This class holds profiling data of multiple tracefiles
1349  * generated with cachegrind on one command.
1350  *
1351  */
1352 class TraceData: public ProfileCostArray
1353 {
1354 public:
1355     // profiled architecture (must be same for every part)
1356     enum Arch { ArchUnknown, ArchARM };
1357 
1358     explicit TraceData(Logger* l = nullptr);
1359     ~TraceData() override;
1360 
data()1361     TraceData* data() override { return this; }
data()1362     const TraceData* data() const override { return this; }
1363 
1364     /**
1365      * Loads profile data files.
1366      * If a single file is given, it is assumed to be a prefix.
1367      *
1368      * This adjusts the EventTypeSet according to given cost types.
1369      * Returns the number of parts loaded
1370      */
1371     int load(QStringList files);
1372     int load(QString file);
1373     int load(QIODevice*, const QString&);
1374 
1375     /** returns true if something changed. These do NOT
1376      * invalidate the dynamic costs on a activation change,
1377      * i.e. all cost items depends on active parts.
1378      * This has to be done by the caller when true is returned by
1379      * calling invalidateDynamicCost().
1380      */
1381     bool activateParts(const TracePartList&);
1382     bool activateParts(TracePartList, bool active);
1383     bool activatePart(TracePart*, bool active);
1384     bool activateAll(bool active=true);
1385 
1386     // to be used by loader
1387     void addPart(TracePart*);
1388 
parts()1389     TracePartList parts() const { return _parts; }
1390     TracePart* partWithName(const QString& name);
1391 
1392     // with path
traceName()1393     QString traceName() const { return _traceName; }
1394 
1395     // without path
1396     QString shortTraceName() const;
1397     QString activePartRange();
1398 
eventTypes()1399     EventTypeSet* eventTypes() { return &_eventTypes; }
1400 
1401     // memory pools
1402     FixPool* fixPool();
1403     DynPool* dynPool();
1404 
1405     // factories for object/file/class/function/line instances
1406     TraceObject* object(const QString& name);
1407     TraceFile* file(const QString& name);
1408     TraceClass* cls(const QString& fnName, QString& shortName);
1409     // function creation involves class creation if needed
1410     TraceFunction* function(const QString& name, TraceFile*, TraceObject*);
1411     // factory for function cycles
1412     TraceFunctionCycle* functionCycle(TraceFunction*);
1413 
1414     /**
1415      * Search for item with given name and highest subcost of given cost type.
1416      *
1417      * For some items, they will only be found if the parent cost is given:
1418      *  Instr, Line, Call  => need parent of type Function
1419      * For Function, a parent of type Obj/File/Class can be given, but
1420      * is not needed.
1421      */
1422     ProfileCostArray* search(ProfileContext::Type, QString,
1423                              EventType* ct = nullptr, ProfileCostArray* parent = nullptr);
1424 
1425     // for pretty function names without signature if unique...
1426     TraceFunctionMap::Iterator functionIterator(TraceFunction*);
1427     TraceFunctionMap::ConstIterator functionBeginIterator() const;
1428     TraceFunctionMap::ConstIterator functionEndIterator() const;
1429 
objectMap()1430     TraceObjectMap& objectMap() { return _objectMap; }
fileMap()1431     TraceFileMap& fileMap() { return _fileMap; }
classMap()1432     TraceClassMap& classMap() { return _classMap; }
functionMap()1433     TraceFunctionMap& functionMap() { return _functionMap; }
1434 
functionCycles()1435     const TraceFunctionCycleList& functionCycles() { return _functionCycles; }
1436 
callMax()1437     ProfileCostArray* callMax() { return &_callMax; }
maxCallCount()1438     SubCost maxCallCount() { return _maxCallCount; }
1439     void updateMaxCallCount(SubCost);
1440 
setCommand(const QString & command)1441     void setCommand(const QString& command) { _command = command; }
command()1442     QString command() const { return _command; }
setArchitecture(Arch a)1443     void setArchitecture(Arch a) { _arch = a; }
architecture()1444     Arch architecture() const { return _arch; }
totals()1445     ProfileCostArray* totals() { return &_totals; }
setMaxThreadID(int tid)1446     void setMaxThreadID(int tid) { _maxThreadID = tid; }
maxThreadID()1447     int maxThreadID() const { return _maxThreadID; }
setMaxPartNumber(int n)1448     void setMaxPartNumber(int n) { _maxPartNumber = n; }
maxPartNumber()1449     int maxPartNumber() const { return _maxPartNumber; }
1450 
1451     // reset all manually set directories for source files
1452     void resetSourceDirs();
1453 
1454     void update() override;
1455 
1456     // invalidates all cost items dependent on active state of parts
1457     void invalidateDynamicCost();
1458 
1459     // cycle detection
1460     void updateFunctionCycles();
1461     void updateObjectCycles();
1462     void updateClassCycles();
1463     void updateFileCycles();
inFunctionCycleUpdate()1464     bool inFunctionCycleUpdate() { return _inFunctionCycleUpdate; }
1465 
1466 private:
1467     void init();
1468     // add profile parts from one file
1469     int internalLoad(QIODevice* file, const QString& filename);
1470 
1471     // for notification callbacks
1472     Logger* _logger;
1473 
1474     TracePartList _parts;
1475 
1476     // The set for all costs
1477     EventTypeSet _eventTypes;
1478 
1479     FixPool* _fixPool;
1480     DynPool* _dynPool;
1481 
1482     // always the trace totals (not dependent on active parts)
1483     ProfileCostArray _totals;
1484     int _maxThreadID;
1485     int _maxPartNumber;
1486 
1487     TraceObjectMap _objectMap;
1488     TraceClassMap _classMap;
1489     TraceFileMap _fileMap;
1490     TraceFunctionMap _functionMap;
1491     QString _command;
1492     Arch _arch;
1493     QString _traceName;
1494 
1495     // Max of all costs of calls: This allows to see if the incl. cost can
1496     // be hidden for a cost type, as it is always the same as self cost
1497     ProfileCostArray _callMax;
1498     SubCost _maxCallCount;
1499 
1500     // cycles
1501     TraceFunctionCycleList _functionCycles;
1502     int _functionCycleCount;
1503     bool _inFunctionCycleUpdate;
1504 };
1505 
1506 
1507 
1508 #endif
1509