File indexing completed on 2024-04-28 05:41:28
0001 /* 0002 This file is part of KCachegrind. 0003 0004 SPDX-FileCopyrightText: 2002-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> 0005 0006 SPDX-License-Identifier: GPL-2.0-only 0007 */ 0008 0009 /* 0010 * Classes holding profiling data for 0011 * multiple tracefiles for one command. 0012 * See class TraceData first. 0013 */ 0014 0015 #ifndef TRACEDATA_H 0016 #define TRACEDATA_H 0017 0018 #include <qstring.h> 0019 #include <qstringlist.h> 0020 #include <qmap.h> 0021 0022 #include "costitem.h" 0023 #include "subcost.h" 0024 #include "utils.h" 0025 #include "addr.h" 0026 #include "context.h" 0027 #include "eventtype.h" 0028 0029 class QFile; 0030 0031 /** 0032 * All cost items are classes prefixed with "Trace". 0033 * "ProfileCostArray" holds basic cost metrics for the simplest, smallest 0034 * trace entity: These are events counted for an instruction at 0035 * a specific memory address of the traced program. 0036 * All other cost items are derived from ProfileCostArray, and add needed 0037 * cost metrics, e.g. for a call the number of calls that happened. 0038 * 0039 * Abstract, i.e. never instantiated cost items are 0040 * - ProfileCostArray: Basic cost metrics (instr/read/write access + cache events) 0041 * - TraceCallCost: Additional call count cost metric. 0042 * - TraceInclusiveCost: Additional ProfileCostArray aggregated. 0043 * - TraceListCost: Adds dependency to a list of ProfileCostArray's 0044 * - TraceCallListCost: same for list of TraceCallCost's 0045 * - TraceInclusiveListCost: same for list of TraceInclusiveCost's 0046 * - TraceCostItem: Base for cost items for "interesting" costs: 0047 * TraceFunction, TraceClass, TraceFile, TraceObject 0048 * 0049 * The smallest Cachegrind output is trace data indexed by a source 0050 * line number, a TracePartLine. Another one is a call from one 0051 * source line of a function to another function, a TracePartLineCall. 0052 * All other cost items derive the value by summation of cost metrics 0053 * from TraceLineItem and TracePartLineCall costs; their cost is 0054 * calculated lazy on demand and cached afterwards. 0055 * 0056 * For cost items, which are sums over all trace files read in, the 0057 * summed cost metrics change when e.g. a new trace file is read. 0058 * Thus, their cached costs are invalidated, and again recalculated 0059 * only on demand. In the following list, theses cost items are called 0060 * "dynamic", the other "fixed" (but neverless calculated lazy). 0061 * 0062 * Cost Item Type Summation of ... 0063 * 0064 * TracePartLineCall fixed Read from trace file 0065 * TracePartLine fixed Read from trace file 0066 * TracePartCall fixed TracePartLineCall's 0067 * TraceLineCall dynamic TracePartLineCall's 0068 * TraceCall dynamic TraceLineCall's 0069 * TraceLine dynamic TracePartLine's and TraceLineCall's 0070 * TracePartFunction fixed TracePartLine's / TracePartCall's 0071 * TraceFunction dynamic TraceLine's / TraceCall's (called from) 0072 * TracePartClass fixed TracePartFunction's 0073 * TraceClass dynamic TraceFunction's 0074 * TracePartFile fixed TracePartFunction's 0075 * TraceFile dynamic TraceFunction's 0076 * TracePartObject fixed TracePartFunction's 0077 * TraceObject dynamic TraceFunction's 0078 * TracePart fixed TracePartLine's 0079 * TraceData dynamic TracePart's 0080 * 0081 * As there exists only one TraceData object for a traced program, it is the 0082 * owner of some "high level" cost items. The following shows the owner 0083 * relationship of the cost item classes, together with references. 0084 * 0085 * Cost Item Owner (& back ref) Other References to 0086 * 0087 * TracePartLineCall TraceLineCall 0088 * TracePartCall TraceCall TracePartLineCall's 0089 * TracePartLine TraceLine TracePartLineCall's 0090 * TracePartFunction TraceFunction 0091 * TracePartClass TraceClass TracePart 0092 * TracePartFile TraceFile TracePart 0093 * TracePartObject TraceObject TracePart 0094 * TraceLineCall TraceCall TracePartLineCall's 0095 * TraceCall TraceFunction TracePartCall's 0096 * TraceLine TraceData TraceLineCall's 0097 * TraceFunction TraceData TraceCall's (calling) 0098 * TraceClass TraceData 0099 * TraceFile TraceData 0100 * TraceObject TraceData 0101 * TracePart TraceData 0102 * TraceData Main Application 0103 * 0104 * Convention: 0105 * - The owner has a factory method for owned objects, 0106 * and calls addXXX() to install references in other objects 0107 * - The owner is first arg in a constructor. 0108 */ 0109 0110 0111 class FixCost; 0112 class FixCallCost; 0113 class FixJump; 0114 class FixPool; 0115 class DynPool; 0116 class Logger; 0117 0118 class ProfileCostArray; 0119 class EventType; 0120 class EventTypeSet; 0121 class EventTypeMapping; 0122 class TraceJumpCost; 0123 class TraceCallCost; 0124 class TraceInclusiveCost; 0125 0126 class TracePartInstr; 0127 class TracePartInstrCall; 0128 class TracePartLine; 0129 class TracePartLineCall; 0130 class TracePartCall; 0131 class TracePartLineRegion; 0132 class TracePartFunction; 0133 class TracePartClass; 0134 class TracePartObject; 0135 class TracePartFile; 0136 0137 class TraceInstr; 0138 class TraceInstrJump; 0139 class TraceInstrCall; 0140 class TraceLine; 0141 class TraceLineJump; 0142 class TraceLineCall; 0143 class TraceCall; 0144 class TraceLineRegion; 0145 class TraceFunctionSource; 0146 class TraceFunction; 0147 class TraceFunctionCycle; 0148 class TraceClass; 0149 class TraceObject; 0150 class TraceFile; 0151 class TracePart; 0152 class TraceData; 0153 0154 typedef QList<ProfileCostArray*> TraceCostList; 0155 typedef QList<TraceJumpCost*> TraceJumpCostList; 0156 typedef QList<TraceCallCost*> TraceCallCostList; 0157 typedef QList<TraceInclusiveCost*> TraceInclusiveCostList; 0158 0159 typedef QList<TracePartCall*> TracePartCallList; 0160 typedef QList<TracePartInstr*> TracePartInstrList; 0161 typedef QList<TracePartLine*> TracePartLineList; 0162 typedef QList<TracePartLineRegion*> TracePartLineRegionList; 0163 typedef QList<TracePartFunction*> TracePartFunctionList; 0164 typedef QList<TracePartInstrCall*> TracePartInstrCallList; 0165 typedef QList<TracePartLineCall*> TracePartLineCallList; 0166 typedef QList<TracePart*> TracePartList; 0167 0168 typedef QList<TraceInstr*> TraceInstrList; 0169 typedef QList<TraceLine*> TraceLineList; 0170 typedef QList<TraceInstrJump*> TraceInstrJumpList; 0171 typedef QList<TraceLineJump*> TraceLineJumpList; 0172 typedef QList<TraceInstrCall*> TraceInstrCallList; 0173 typedef QList<TraceLineCall*> TraceLineCallList; 0174 typedef QList<TraceCall*> TraceCallList; 0175 typedef QList<TraceFile*> TraceFileList; 0176 typedef QList<TraceLineRegion*> TraceLineRegionList; 0177 typedef QList<TraceFunctionSource*> TraceFunctionSourceList; 0178 typedef QList<TraceFunction*> TraceFunctionList; 0179 typedef QList<TraceFunctionCycle*> TraceFunctionCycleList; 0180 typedef QMap<QString, TraceObject> TraceObjectMap; 0181 typedef QMap<QString, TraceClass> TraceClassMap; 0182 typedef QMap<QString, TraceFile> TraceFileMap; 0183 typedef QMap<QString, TraceFunction> TraceFunctionMap; 0184 typedef QMap<uint, TraceLine> TraceLineMap; 0185 typedef QMap<Addr, TraceInstr> TraceInstrMap; 0186 0187 0188 /** 0189 * Cost of a (conditional) jump. 0190 */ 0191 class TraceJumpCost: public CostItem 0192 { 0193 public: 0194 explicit TraceJumpCost(ProfileContext*); 0195 ~TraceJumpCost() override; 0196 0197 // reimplementations for cost addition 0198 QString costString(EventTypeSet* m) override; 0199 void clear() override; 0200 0201 void addCost(TraceJumpCost*); 0202 0203 // additional cost metrics 0204 SubCost followedCount(); 0205 SubCost executedCount(); 0206 void addFollowedCount(SubCost c) { _followedCount += c; } 0207 void addExecutedCount(SubCost c) { _executedCount += c; } 0208 0209 protected: 0210 SubCost _executedCount, _followedCount; 0211 }; 0212 0213 0214 0215 /** 0216 * Cost item with additional call count metric. 0217 */ 0218 class TraceCallCost: public ProfileCostArray 0219 { 0220 public: 0221 explicit TraceCallCost(ProfileContext*); 0222 ~TraceCallCost() override; 0223 0224 // reimplementations for cost addition 0225 QString costString(EventTypeSet* m) override; 0226 void clear() override; 0227 0228 // additional cost metric 0229 SubCost callCount(); 0230 QString prettyCallCount(); 0231 void addCallCount(SubCost c); 0232 0233 protected: 0234 SubCost _callCount; 0235 }; 0236 0237 0238 /** 0239 * Cost item with additional inclusive metric 0240 */ 0241 class TraceInclusiveCost: public ProfileCostArray 0242 { 0243 public: 0244 explicit TraceInclusiveCost(ProfileContext*); 0245 ~TraceInclusiveCost() override; 0246 0247 // reimplementations for cost addition 0248 QString costString(EventTypeSet* m) override; 0249 void clear() override; 0250 0251 // additional cost metric 0252 ProfileCostArray* inclusive(); 0253 void addInclusive(ProfileCostArray*); 0254 0255 protected: 0256 ProfileCostArray _inclusive; 0257 }; 0258 0259 0260 /** 0261 * Cost Item 0262 * depends on a list of cost items. 0263 */ 0264 class TraceListCost: public ProfileCostArray 0265 { 0266 public: 0267 explicit TraceListCost(ProfileContext*); 0268 ~TraceListCost() override; 0269 0270 // reimplementation for dependency list 0271 void update() override; 0272 0273 TraceCostList& deps() { return _deps; } 0274 void addDep(ProfileCostArray*); 0275 ProfileCostArray* findDepFromPart(TracePart*); 0276 0277 protected: 0278 // overwrite in subclass to change update behaviour 0279 virtual bool onlyActiveParts() { return false; } 0280 0281 TraceCostList _deps; 0282 0283 private: 0284 // very temporary: cached 0285 ProfileCostArray* _lastDep; 0286 }; 0287 0288 0289 /** 0290 * Jump Cost Item 0291 * depends on a list of Jump cost items. 0292 */ 0293 class TraceJumpListCost: public TraceJumpCost 0294 { 0295 public: 0296 explicit TraceJumpListCost(ProfileContext*); 0297 ~TraceJumpListCost() override; 0298 0299 // reimplementation for dependency list 0300 void update() override; 0301 0302 TraceJumpCostList deps() { return _deps; } 0303 void addDep(TraceJumpCost*); 0304 TraceJumpCost* findDepFromPart(TracePart*); 0305 0306 protected: 0307 // overwrite in subclass to change update behaviour 0308 virtual bool onlyActiveParts() { return false; } 0309 0310 TraceJumpCostList _deps; 0311 0312 private: 0313 // very temporary: cached 0314 TraceJumpCost* _lastDep; 0315 }; 0316 0317 0318 0319 0320 /** 0321 * Call Cost Item 0322 * depends on a list of Call cost items. 0323 */ 0324 class TraceCallListCost: public TraceCallCost 0325 { 0326 public: 0327 explicit TraceCallListCost(ProfileContext*); 0328 ~TraceCallListCost() override; 0329 0330 // reimplementation for dependency list 0331 void update() override; 0332 0333 TraceCallCostList deps() { return _deps; } 0334 void addDep(TraceCallCost*); 0335 TraceCallCost* findDepFromPart(TracePart*); 0336 0337 protected: 0338 // overwrite in subclass to change update behaviour 0339 virtual bool onlyActiveParts() { return false; } 0340 0341 TraceCallCostList _deps; 0342 0343 private: 0344 // very temporary: cached 0345 TraceCallCost* _lastDep; 0346 }; 0347 0348 0349 /** 0350 * Inclusive Cost Item depends on a list of inclusive cost items. 0351 */ 0352 class TraceInclusiveListCost: public TraceInclusiveCost 0353 { 0354 public: 0355 explicit TraceInclusiveListCost(ProfileContext*); 0356 ~TraceInclusiveListCost() override; 0357 0358 // reimplementation for dependency 0359 void update() override; 0360 0361 TraceInclusiveCostList deps() { return _deps; } 0362 void addDep(TraceInclusiveCost*); 0363 TraceInclusiveCost* findDepFromPart(TracePart*); 0364 0365 protected: 0366 // overwrite in subclass to change update behaviour 0367 virtual bool onlyActiveParts() { return false; } 0368 0369 TraceInclusiveCostList _deps; 0370 0371 private: 0372 // very temporary: cached 0373 TraceInclusiveCost* _lastDep; 0374 }; 0375 0376 0377 0378 0379 0380 /*----------------------------------------------------------------- 0381 * Classes for cost items of one trace file, i.e. a "trace part" 0382 *----------------------------------------------------------------- 0383 */ 0384 0385 /** 0386 * Cost of jump at a instruction code address from a trace file. 0387 */ 0388 class TracePartInstrJump: public TraceJumpCost 0389 { 0390 public: 0391 TracePartInstrJump(TraceInstrJump*, TracePartInstrJump*); 0392 ~TracePartInstrJump() override; 0393 0394 // fix cost item 0395 void update() override {} 0396 TraceInstrJump* instrJump() const { return (TraceInstrJump*) _dep; } 0397 TracePartInstrJump* next() const { return _next; } 0398 0399 private: 0400 // chaining all parts for InstrJump 0401 TracePartInstrJump* _next; 0402 }; 0403 0404 0405 /** 0406 * Cost of a call at a instruction code address from a trace file. 0407 * Cost is always up to date, no lazy update needed. 0408 */ 0409 class TracePartInstrCall: public TraceCallCost 0410 { 0411 public: 0412 explicit TracePartInstrCall(TraceInstrCall*); 0413 ~TracePartInstrCall() override; 0414 0415 // fix cost item 0416 void update() override {} 0417 TraceInstrCall* instrCall() const { return (TraceInstrCall*) _dep; } 0418 }; 0419 0420 0421 /** 0422 * Cost of a code instruction address from a trace file. 0423 * Cost is always up to date, no lazy update needed. 0424 */ 0425 class TracePartInstr: public ProfileCostArray 0426 { 0427 public: 0428 explicit TracePartInstr(TraceInstr*); 0429 ~TracePartInstr() override; 0430 0431 // fix cost item 0432 void update() override {} 0433 0434 TraceInstr* instr() const { return (TraceInstr*)_dep; } 0435 }; 0436 0437 0438 /** 0439 * Cost of jump at a source line from a trace file. 0440 */ 0441 class TracePartLineJump: public TraceJumpCost 0442 { 0443 public: 0444 explicit TracePartLineJump(TraceLineJump*); 0445 ~TracePartLineJump() override; 0446 0447 // fix cost item 0448 void update() override {} 0449 TraceLineJump* lineJump() const { return (TraceLineJump*) _dep; } 0450 }; 0451 0452 0453 /** 0454 * Cost of a call at a line from a trace file. 0455 * Cost is always up to date, no lazy update needed. 0456 */ 0457 class TracePartLineCall: public TraceCallCost 0458 { 0459 public: 0460 explicit TracePartLineCall(TraceLineCall*); 0461 ~TracePartLineCall() override; 0462 0463 // fix cost item 0464 void update() override {} 0465 TraceLineCall* lineCall() const { return (TraceLineCall*) _dep; } 0466 }; 0467 0468 0469 0470 /** 0471 * Cost of a line from a trace file. 0472 * Cost is always up to date, no lazy update needed. 0473 */ 0474 class TracePartLine: public ProfileCostArray 0475 { 0476 public: 0477 explicit TracePartLine(TraceLine*); 0478 ~TracePartLine() override; 0479 0480 // fix cost item 0481 void update() override {} 0482 0483 TraceLine* line() const { return (TraceLine*)_dep; } 0484 }; 0485 0486 0487 /** 0488 * Cost of a source region. 0489 */ 0490 class TracePartLineRegion: public TraceInclusiveCost 0491 { 0492 public: 0493 explicit TracePartLineRegion(TraceLineRegion*); 0494 ~TracePartLineRegion() override; 0495 0496 void update() override; 0497 0498 TraceLineRegion* region() const { return (TraceLineRegion*)_dep; } 0499 }; 0500 0501 0502 /** 0503 * Cost of a call at a function to another function, 0504 * from a single trace file. 0505 */ 0506 class TracePartCall: public TraceCallListCost 0507 { 0508 public: 0509 explicit TracePartCall(TraceCall* call); 0510 ~TracePartCall() override; 0511 0512 // calls a function itself? 0513 bool isRecursion(); 0514 0515 // reimplementation for dependency list 0516 void update() override; 0517 0518 TraceCall* call() const { return (TraceCall*)_dep; } 0519 0520 FixCallCost* setFirstFixCallCost(FixCallCost* fc) 0521 { FixCallCost* t = _firstFixCallCost; _firstFixCallCost = fc; return t; } 0522 FixCallCost* firstFixCallCost() const { return _firstFixCallCost; } 0523 0524 private: 0525 FixCallCost* _firstFixCallCost; 0526 }; 0527 0528 0529 /** 0530 * Cost of a function, 0531 * from a single trace file. 0532 */ 0533 class TracePartFunction: public TraceInclusiveCost 0534 { 0535 public: 0536 TracePartFunction(TraceFunction*, 0537 TracePartObject*, TracePartFile*); 0538 ~TracePartFunction() override; 0539 0540 void update() override; 0541 QString costString(EventTypeSet* m) override; 0542 0543 void addPartInstr(TracePartInstr*); 0544 void addPartLine(TracePartLine*); 0545 void addPartCaller(TracePartCall*); 0546 void addPartCalling(TracePartCall*); 0547 0548 TraceFunction* function() { return (TraceFunction*) _dep; } 0549 TracePartObject* partObject() { return _partObject; } 0550 TracePartClass* partClass() { return _partClass; } 0551 TracePartFile* partFile() { return _partFile; } 0552 const TracePartCallList& partCallers() { return _partCallers; } 0553 const TracePartCallList& partCallings() { return _partCallings; } 0554 void setPartObject(TracePartObject* o) { _partObject = o; } 0555 void setPartClass(TracePartClass* c) { _partClass = c; } 0556 void setPartFile(TracePartFile* f) { _partFile = f; } 0557 0558 /* for linked list of FixXXX objects */ 0559 FixCost* setFirstFixCost(FixCost* fc) 0560 { FixCost* t = _firstFixCost; _firstFixCost = fc; return t; } 0561 FixCost* firstFixCost() const { return _firstFixCost; } 0562 FixJump* setFirstFixJump(FixJump* fj) 0563 { FixJump* t = _firstFixJump; _firstFixJump = fj; return t; } 0564 FixJump* firstFixJump() const { return _firstFixJump; } 0565 0566 // additional cost metrics 0567 SubCost calledCount(); 0568 SubCost callingCount(); 0569 QString prettyCalledCount(); 0570 QString prettyCallingCount(); 0571 int calledContexts(); 0572 int callingContexts(); 0573 0574 private: 0575 TracePartObject* _partObject; 0576 TracePartClass* _partClass; 0577 TracePartFile* _partFile; 0578 0579 TracePartCallList _partCallings; 0580 TracePartCallList _partCallers; 0581 TracePartInstrList _partInstr; 0582 TracePartLineList _partLines; 0583 0584 // cached 0585 SubCost _calledCount, _callingCount; 0586 int _calledContexts, _callingContexts; 0587 0588 FixCost* _firstFixCost; 0589 FixJump* _firstFixJump; 0590 }; 0591 0592 0593 /** 0594 * Cost of a class, 0595 * from a single trace file. 0596 */ 0597 class TracePartClass: public TraceInclusiveListCost 0598 { 0599 public: 0600 explicit TracePartClass(TraceClass*); 0601 ~TracePartClass() override; 0602 0603 QString prettyName() const override; 0604 0605 TraceClass* cls() { return (TraceClass*)_dep; } 0606 void addPartFunction(TracePartFunction* f) { addDep(f); } 0607 }; 0608 0609 0610 /** 0611 * Cost of a source file, 0612 * from a single trace file. 0613 */ 0614 class TracePartFile: public TraceInclusiveListCost 0615 { 0616 public: 0617 explicit TracePartFile(TraceFile*); 0618 ~TracePartFile() override; 0619 0620 TraceFile* file() { return (TraceFile*)_dep; } 0621 void addPartFunction(TracePartFunction* f) { addDep(f); } 0622 }; 0623 0624 0625 /** 0626 * Cost of a object, 0627 * from a single trace file. 0628 */ 0629 class TracePartObject: public TraceInclusiveListCost 0630 { 0631 public: 0632 explicit TracePartObject(TraceObject*); 0633 ~TracePartObject() override; 0634 0635 TraceObject* object() const { return (TraceObject*)_dep; } 0636 void addPartFunction(TracePartFunction* f) { addDep(f); } 0637 }; 0638 0639 0640 0641 /** 0642 * A Trace Part: All data read from a trace file, containing all costs 0643 * that happened in a specified time interval of the executed command. 0644 */ 0645 class TracePart: public TraceListCost 0646 { 0647 public: 0648 explicit TracePart(TraceData*); 0649 ~TracePart() override; 0650 0651 TracePart* part() override { return this; } 0652 const TracePart* part() const override { return this; } 0653 0654 QString shortName() const; 0655 QString prettyName() const override; 0656 /// @return Name of the file this part was loaded from 0657 QString name() const override { return _name; } 0658 QString description() const { return _descr; } 0659 QString trigger() const { return _trigger; } 0660 QString timeframe() const { return _timeframe; } 0661 QString version() const { return _version; } 0662 int partNumber() const { return _number; } 0663 int threadID() const { return _tid; } 0664 int processID() const { return _pid; } 0665 void setDescription(const QString& d) { _descr = d; } 0666 void setTrigger(const QString& t) { _trigger = t; } 0667 void setTimeframe(const QString& t) { _timeframe = t; } 0668 void setVersion(const QString& v) { _version = v; } 0669 void setName(const QString& n) { _name = n; } 0670 void setPartNumber(int n); 0671 void setThreadID(int t); 0672 void setProcessID(int p); 0673 ProfileCostArray* totals() { return &_totals; } 0674 /* passes ownership of mapping */ 0675 void setEventMapping(EventTypeMapping* sm) { _eventTypeMapping = sm; } 0676 EventTypeMapping* eventTypeMapping() { return _eventTypeMapping; } 0677 0678 // returns true if something changed 0679 bool activate(bool); 0680 bool isActive() const { return _active; } 0681 0682 // for sorting 0683 bool operator<(const TracePart&) const; 0684 0685 private: 0686 QString _name; 0687 QString _descr; 0688 QString _trigger; 0689 QString _timeframe; 0690 QString _version; 0691 0692 int _number, _tid, _pid; 0693 0694 bool _active; 0695 0696 // the totals line 0697 ProfileCostArray _totals; 0698 0699 // event type mapping for all fix costs of this part 0700 EventTypeMapping* _eventTypeMapping; 0701 }; 0702 0703 0704 0705 /*----------------------------------------------------------------- 0706 * Classes for cost items summed up from multiple trace parts 0707 *----------------------------------------------------------------- 0708 */ 0709 0710 0711 /** 0712 * A jump from an instruction to another inside of a function 0713 */ 0714 class TraceInstrJump: public TraceJumpCost 0715 { 0716 public: 0717 TraceInstrJump(TraceInstr* instrFrom, TraceInstr* instrTo, 0718 bool isCondJump); 0719 ~TraceInstrJump() override; 0720 0721 QString name() const override; 0722 0723 void update() override; 0724 0725 TraceInstr* instrFrom() const { return _instrFrom; } 0726 TraceInstr* instrTo() const { return _instrTo; } 0727 bool isCondJump() const { return _isCondJump; } 0728 0729 // part factory 0730 TracePartInstrJump* partInstrJump(TracePart*); 0731 0732 private: 0733 TraceInstr *_instrFrom, *_instrTo; 0734 bool _isCondJump; 0735 // list of parts for this InstrJump 0736 TracePartInstrJump* _first; 0737 }; 0738 0739 0740 /** 0741 * A jump from one line to another inside of a function. 0742 */ 0743 class TraceLineJump: public TraceJumpListCost 0744 { 0745 public: 0746 TraceLineJump(TraceLine* lineFrom, TraceLine* lineTo, 0747 bool isCondJump); 0748 ~TraceLineJump() override; 0749 0750 QString name() const override; 0751 0752 TraceLine* lineFrom() const { return _lineFrom; } 0753 TraceLine* lineTo() const { return _lineTo; } 0754 bool isCondJump() { return _isCondJump; } 0755 0756 // part factory 0757 TracePartLineJump* partLineJump(TracePart*); 0758 0759 protected: 0760 bool onlyActiveParts() override { return true; } 0761 0762 private: 0763 TraceLine *_lineFrom, *_lineTo; 0764 bool _isCondJump; 0765 }; 0766 0767 0768 /** 0769 * A call from an instruction of one function to another function 0770 */ 0771 class TraceInstrCall: public TraceCallListCost 0772 { 0773 public: 0774 TraceInstrCall(TraceCall* call, TraceInstr* instr); 0775 ~TraceInstrCall() override; 0776 0777 QString name() const override; 0778 0779 TraceInstr* instr() const { return _instr; } 0780 TraceCall* call() const { return _call; } 0781 0782 // part factory 0783 TracePartInstrCall* partInstrCall(TracePart*, TracePartCall*); 0784 0785 protected: 0786 bool onlyActiveParts() override { return true; } 0787 0788 private: 0789 TraceInstr* _instr; 0790 TraceCall* _call; 0791 }; 0792 0793 0794 /** 0795 * A call from a line of one function to another function. 0796 */ 0797 class TraceLineCall: public TraceCallListCost 0798 { 0799 public: 0800 TraceLineCall(TraceCall* call, TraceLine* line); 0801 ~TraceLineCall() override; 0802 0803 QString name() const override; 0804 0805 TraceLine* line() const { return _line; } 0806 TraceCall* call() const { return _call; } 0807 0808 // part factory 0809 TracePartLineCall* partLineCall(TracePart*, TracePartCall*); 0810 0811 protected: 0812 bool onlyActiveParts() override { return true; } 0813 0814 private: 0815 TraceLine* _line; 0816 TraceCall* _call; 0817 }; 0818 0819 0820 /** 0821 * A call from one to another function. 0822 * Consists of a list a TraceLineCalls 0823 */ 0824 class TraceCall: public TraceCallListCost 0825 { 0826 public: 0827 TraceCall(TraceFunction* caller, TraceFunction* called); 0828 ~TraceCall() override; 0829 0830 QString name() const override; 0831 0832 // calls a function itself? 0833 bool isRecursion() { return _caller == _called; } 0834 0835 // return cycle number >0 if call is inside of a cycle 0836 int inCycle(); 0837 // we need some special handling for cycle calls 0838 void update() override; 0839 0840 void invalidateDynamicCost(); 0841 0842 // factories 0843 TracePartCall* partCall(TracePart*, 0844 TracePartFunction*, TracePartFunction*); 0845 TraceLineCall* lineCall(TraceLine*); 0846 TraceInstrCall* instrCall(TraceInstr*); 0847 0848 TraceFunction* caller(bool skipCycle=false) const; 0849 TraceFunction* called(bool skipCycle=false) const; 0850 QString callerName(bool skipCycle=false) const; 0851 QString calledName(bool skipCycle=false) const; 0852 const TraceLineCallList& lineCalls() const { return _lineCalls; } 0853 const TraceInstrCallList& instrCalls() const { return _instrCalls; } 0854 0855 FixCallCost* setFirstFixCost(FixCallCost* fc) 0856 { FixCallCost* t = _firstFixCost; _firstFixCost = fc; return t; } 0857 0858 protected: 0859 bool onlyActiveParts() override { return true; } 0860 0861 private: 0862 TraceInstrCallList _instrCalls; 0863 TraceLineCallList _lineCalls; 0864 TraceFunction* _caller; 0865 TraceFunction* _called; 0866 0867 FixCallCost* _firstFixCost; 0868 }; 0869 0870 0871 /** 0872 * A code instruction address of the program. 0873 * Consists of a list a TracePartInstr from different trace files 0874 * and a list of TraceInstrCalls if there are calls from this address. 0875 */ 0876 class TraceInstr: public TraceListCost 0877 { 0878 public: 0879 TraceInstr(); 0880 ~TraceInstr() override; 0881 0882 QString name() const override; 0883 QString prettyName() const override; 0884 0885 bool isValid() { return _addr != Addr(0); } 0886 0887 // factories 0888 TracePartInstr* partInstr(TracePart* part, 0889 TracePartFunction* partFunction); 0890 TraceInstrJump* instrJump(TraceInstr* to, bool isCondJump); 0891 0892 void addInstrCall(TraceInstrCall*); 0893 0894 Addr addr() const { return _addr; } 0895 TraceFunction* function() const { return _function; } 0896 TraceLine* line() const { return _line; } 0897 const TraceInstrJumpList& instrJumps() const { return _instrJumps; } 0898 const TraceInstrCallList& instrCalls() const { return _instrCalls; } 0899 bool hasCost(EventType*); 0900 0901 // only to be called after default constructor 0902 void setAddr(const Addr addr) { _addr = addr; } 0903 void setFunction(TraceFunction* f) { _function = f; } 0904 void setLine(TraceLine* l) { _line = l; } 0905 0906 protected: 0907 bool onlyActiveParts() override { return true; } 0908 0909 private: 0910 Addr _addr; 0911 TraceFunction* _function; 0912 TraceLine* _line; 0913 0914 TraceInstrJumpList _instrJumps; 0915 TraceInstrCallList _instrCalls; 0916 }; 0917 0918 0919 /** 0920 * A source line of the program. 0921 * Consists of a list a TracePartLines from different trace files 0922 * and a list of TraceLineCalls if there are calls from this line. 0923 */ 0924 class TraceLine: public TraceListCost 0925 { 0926 public: 0927 TraceLine(); 0928 ~TraceLine() override; 0929 0930 QString name() const override; 0931 QString prettyName() const override; 0932 0933 // factories 0934 TracePartLine* partLine(TracePart* part, 0935 TracePartFunction* partFunction); 0936 TraceLineJump* lineJump(TraceLine* to, bool isCondJump); 0937 0938 void addLineCall(TraceLineCall*); 0939 0940 0941 bool isValid() { return _sourceFile != nullptr; } 0942 bool hasCost(EventType*); 0943 TraceFunctionSource* functionSource() const { return _sourceFile; } 0944 uint lineno() const { return _lineno; } 0945 const TraceLineCallList& lineCalls() const { return _lineCalls; } 0946 const TraceLineJumpList& lineJumps() const { return _lineJumps; } 0947 0948 // only to be called after default constructor 0949 void setSourceFile(TraceFunctionSource* sf) { _sourceFile = sf; } 0950 void setLineno(uint lineno) { _lineno = lineno; } 0951 0952 protected: 0953 bool onlyActiveParts() override { return true; } 0954 0955 private: 0956 TraceFunctionSource* _sourceFile; 0957 uint _lineno; 0958 0959 TraceLineJumpList _lineJumps; 0960 TraceLineCallList _lineCalls; 0961 }; 0962 0963 0964 /* 0965 * Base class for all costs which 0966 * represent "interesting" items or group of items 0967 * with settable name and inclusive cost 0968 */ 0969 class TraceCostItem: public TraceInclusiveListCost 0970 { 0971 public: 0972 explicit TraceCostItem(ProfileContext*); 0973 ~TraceCostItem() override; 0974 0975 QString name() const override { return _name; } 0976 virtual void setName(const QString& name) { _name = name; } 0977 0978 protected: 0979 bool onlyActiveParts() override { return true; } 0980 0981 protected: 0982 QString _name; 0983 }; 0984 0985 0986 /** 0987 * Cost of a source region. 0988 */ 0989 class TraceLineRegion: public TraceInclusiveListCost 0990 { 0991 public: 0992 TraceLineRegion(uint from, uint to, QString name); 0993 ~TraceLineRegion() override; 0994 0995 void update() override; 0996 0997 uint from() const { return _from; } 0998 uint to() const { return _to; } 0999 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 1029 TraceFile* file() const { return _file; } 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 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*); 1080 TraceFunction* function() { return _function; } 1081 1082 void invalidate() { _valid = false; } 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 1151 TraceClass* cls() const { return _cls; } 1152 TraceFile* file() const { return _file; } 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); 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 1175 void setFile(TraceFile* file) { _file = file; } 1176 void setObject(TraceObject* object) { _object = object; } 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 1188 void setCycle(TraceFunctionCycle* c) { _cycle = c; } 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 1241 TraceFunction* base() const { return _base; } 1242 int cycleNo() const { return _cycleNo; } 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*); 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); 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(); 1302 const TraceFunctionList& functions() const { return _functions; } 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); 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(); 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 1361 TraceData* data() override { return this; } 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 1389 TracePartList parts() const { return _parts; } 1390 TracePart* partWithName(const QString& name); 1391 1392 // with path 1393 QString traceName() const { return _traceName; } 1394 1395 // without path 1396 QString shortTraceName() const; 1397 QString activePartRange(); 1398 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 1430 TraceObjectMap& objectMap() { return _objectMap; } 1431 TraceFileMap& fileMap() { return _fileMap; } 1432 TraceClassMap& classMap() { return _classMap; } 1433 TraceFunctionMap& functionMap() { return _functionMap; } 1434 1435 const TraceFunctionCycleList& functionCycles() { return _functionCycles; } 1436 1437 ProfileCostArray* callMax() { return &_callMax; } 1438 SubCost maxCallCount() { return _maxCallCount; } 1439 void updateMaxCallCount(SubCost); 1440 1441 void setCommand(const QString& command) { _command = command; } 1442 QString command() const { return _command; } 1443 void setArchitecture(Arch a) { _arch = a; } 1444 Arch architecture() const { return _arch; } 1445 ProfileCostArray* totals() { return &_totals; } 1446 void setMaxThreadID(int tid) { _maxThreadID = tid; } 1447 int maxThreadID() const { return _maxThreadID; } 1448 void setMaxPartNumber(int n) { _maxPartNumber = n; } 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(); 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