File indexing completed on 2024-04-28 05:41:25

0001 /*
0002     This file is part of KCachegrind.
0003 
0004     SPDX-FileCopyrightText: 2003-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
0005 
0006     SPDX-License-Identifier: GPL-2.0-only
0007 */
0008 
0009 #include "fixcost.h"
0010 #include "utils.h"
0011 #include "addr.h"
0012 
0013 // FixCost
0014 
0015 FixCost::FixCost(TracePart* part, FixPool* pool,
0016                  TraceFunctionSource* functionSource,
0017                  PositionSpec& pos,
0018                  TracePartFunction* partFunction,
0019                  FixString& s)
0020 {
0021     int maxCount = part->eventTypeMapping()->count();
0022 
0023     _part = part;
0024     _functionSource = functionSource;
0025     _pos = pos;
0026 
0027     _cost = (SubCost*) pool->reserve(sizeof(SubCost) * maxCount);
0028     s.stripSpaces();
0029     int i = 0;
0030     while(i<maxCount) {
0031         if (!s.stripUInt64(_cost[i])) {
0032             // xdebug used to emit negative costs if it freed memory. It no
0033             // longer does this. However, old cachegrind files still exist,
0034             // and they cause KCacheGrind to constantly print messages about
0035             // garbage (the negative cost it couldn't parse as unsigned) at
0036             // the end of the line. This checks for a negative signed value if
0037             // we can't find a positive one and clamps to zero, which is what
0038             // xdebug does now itself. [1]
0039             // [1]: xdebug commit 688c552e620dc5be7eea22cb893c6b71f395c6d4
0040             int64 temp;
0041             if (s.stripInt64(temp) && temp < 0) {
0042                 _cost[i] = 0;
0043             } else {
0044                 break;
0045             }
0046         }
0047         i++;
0048     }
0049     _count = i;
0050 
0051     if (!pool->allocateReserved(sizeof(SubCost) * _count))
0052         _count = 0;
0053 
0054     _nextCostOfPartFunction = partFunction ?
0055                                   partFunction->setFirstFixCost(this) : nullptr;
0056 }
0057 
0058 void* FixCost::operator new(size_t size, FixPool* pool)
0059 {
0060     return pool->allocate(size);
0061 }
0062 
0063 void FixCost::addTo(ProfileCostArray* c)
0064 {
0065     EventTypeMapping* sm = _part->eventTypeMapping();
0066 
0067     int i, realIndex;
0068 
0069     c->reserve(sm->maxRealIndex(_count)+1);
0070     for(i=0; i<_count; i++) {
0071         realIndex = sm->realIndex(i);
0072         c->addCost(realIndex, _cost[i]);
0073     }
0074 }
0075 
0076 
0077 
0078 // FixCallCost
0079 
0080 FixCallCost::FixCallCost(TracePart* part, FixPool* pool,
0081                          TraceFunctionSource* functionSource,
0082                          unsigned int line, Addr addr,
0083                          TracePartCall* partCall,
0084                          SubCost callCount, FixString& s)
0085 {
0086     if (0) qDebug("Got FixCallCost (addr 0x%s, line %d): calls %s",
0087                   qPrintable(addr.toString()), line,
0088                   qPrintable(callCount.pretty()));
0089 
0090     int maxCount = part->eventTypeMapping()->count();
0091 
0092     _part = part;
0093     _functionSource = functionSource;
0094     _line = line;
0095     _addr = addr;
0096 
0097     _cost = (SubCost*) pool->reserve(sizeof(SubCost) * (maxCount+1));
0098     s.stripSpaces();
0099     int i = 0;
0100     while(i<maxCount) {
0101         if (!s.stripUInt64(_cost[i])) {
0102             // Same case as in the FixCost ctor.
0103             int64 temp;
0104             if (s.stripInt64(temp) && temp < 0) {
0105                 _cost[i] = 0;
0106             } else {
0107                 break;
0108             }
0109         }
0110         i++;
0111     }
0112     _count = i;
0113 
0114     if (!pool->allocateReserved(sizeof(SubCost) * (_count+1) ))
0115         _count = 0;
0116     else
0117         _cost[_count] = callCount;
0118 
0119     _nextCostOfPartCall = partCall ? partCall->setFirstFixCallCost(this) : nullptr;
0120 }
0121 
0122 void* FixCallCost::operator new(size_t size, FixPool* pool)
0123 {
0124     return pool->allocate(size);
0125 }
0126 
0127 void FixCallCost::addTo(TraceCallCost* c)
0128 {
0129     EventTypeMapping* sm = _part->eventTypeMapping();
0130 
0131     int i, realIndex;
0132 
0133     for(i=0; i<_count; i++) {
0134         realIndex = sm->realIndex(i);
0135         c->addCost(realIndex, _cost[i]);
0136     }
0137     c->addCallCount(_cost[_count]);
0138 
0139     if (0) qDebug("Adding from (addr 0x%s, ln %d): calls %s",
0140                   qPrintable(_addr.toString()), _line,
0141                   qPrintable(_cost[_count].pretty()));
0142 }
0143 
0144 void FixCallCost::setMax(ProfileCostArray* c)
0145 {
0146     EventTypeMapping* sm = _part->eventTypeMapping();
0147 
0148     int i, realIndex;
0149 
0150     for(i=0; i<_count; i++) {
0151         realIndex = sm->realIndex(i);
0152         c->maxCost(realIndex, _cost[i]);
0153     }
0154 }
0155 
0156 
0157 // FixJump
0158 
0159 FixJump::FixJump(TracePart* part, FixPool* pool,
0160                  unsigned int line, Addr addr,
0161                  TracePartFunction* partFunction,
0162                  TraceFunctionSource* source,
0163                  unsigned int targetLine, Addr targetAddr,
0164                  TraceFunction* targetFunction,
0165                  TraceFunctionSource* targetSource,
0166                  bool isCondJump,
0167                  SubCost executed, SubCost followed)
0168 {
0169     _part   = part;
0170     _source = source;
0171     _line   = line;
0172     _addr   = addr;
0173 
0174     _targetFunction = targetFunction;
0175     _targetSource   = targetSource;
0176     _targetLine     = targetLine;
0177     _targetAddr     = targetAddr;
0178     
0179     _isCondJump = isCondJump;
0180 
0181     int size = (isCondJump ? 2 : 1) * sizeof(SubCost);
0182     _cost = (SubCost*) pool->allocate(size);
0183     _cost[0] = executed;
0184     if (isCondJump) _cost[1] = followed;
0185 
0186     _nextJumpOfPartFunction = partFunction ?
0187                                   partFunction->setFirstFixJump(this) : nullptr;
0188 }
0189 
0190 void* FixJump::operator new(size_t size, FixPool* pool)
0191 {
0192     return pool->allocate(size);
0193 }
0194 
0195 void FixJump::addTo(TraceJumpCost* jc)
0196 {
0197     jc->addExecutedCount(_cost[0]);
0198     if (_isCondJump)
0199         jc->addFollowedCount(_cost[1]);
0200 }