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