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 }