1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#ifndef ECMASCRIPT_DFX_VMSTAT_OPT_CODE_PROFILER_H 16#define ECMASCRIPT_DFX_VMSTAT_OPT_CODE_PROFILER_H 17 18#include "ecmascript/compiler/bytecodes.h" 19#include "ecmascript/compiler/ecma_opcode_des.h" 20#include "ecmascript/compiler/share_opcodes.h" 21#include <set> 22 23// bcIndex bytecode count fast slow typerate 24// ====================(print all)======================= 25// ........ 26// ====================================================== 27// total 28 29// tip: not print if count below 10000 30// ====================(top1 method: name, methodId)===== 31// ....... 32// (bcIndex bytecode count fast slow typerate) 33// ....... 34// ====================================================== 35 36// ====================(top2 method: name)=============== 37// ....... 38// ====================================================== 39 40// ....... 41 42// ====================(top10 method: name)============== 43// ....... 44// ====================================================== 45 46// methodId, abcId, bcIndex, Value1(opcode, fastcount, slowcount),Value2(methodName, totalcount) 47// key: methodId, abcId 48// std::map<key, <bcIndex, Value1>> 49// std::map<key, Value2> 50 51namespace panda::ecmascript { 52class OptCodeProfiler { 53public: 54 using EcmaOpcode = kungfu::EcmaOpcode; 55 56 enum Mode { 57 TYPED_PATH, 58 SLOW_PATH, 59 }; 60 61 struct Value { 62 Value() : typedPathValue(0), slowPathValue(0) {} 63 64 uint64_t TypedPathCount() const 65 { 66 return typedPathValue; 67 } 68 69 uint64_t SlowPathCount() const 70 { 71 return slowPathValue; 72 } 73 74 uint64_t Count() const 75 { 76 return typedPathValue + slowPathValue; 77 } 78 79 void ResetStat() 80 { 81 typedPathValue = 0; 82 slowPathValue = 0; 83 } 84 85 uint64_t typedPathValue; 86 uint64_t slowPathValue; 87 }; 88 89 struct Key { 90 Key(uint32_t abcId, uint32_t methodId) 91 { 92 abcAndMethodId_ = (((uint64_t)abcId) << 32) + methodId; // 32: 32bit 93 } 94 95 Key(uint64_t key) : abcAndMethodId_(key) {}; 96 97 uint32_t GetAbcId() const 98 { 99 return (uint32_t) (abcAndMethodId_ >> 32); // 32: 32bit 100 } 101 102 uint32_t GetMethodId() const 103 { 104 return (uint32_t) abcAndMethodId_; 105 } 106 107 uint64_t Value() const 108 { 109 return abcAndMethodId_; 110 } 111 112 uint64_t abcAndMethodId_; 113 }; 114 115 struct Name { 116 Name(std::string name) : methodName_(name), totalCount_(1) {} 117 118 uint64_t Count() const 119 { 120 return totalCount_; 121 } 122 123 void Inc() 124 { 125 totalCount_ = totalCount_ + 1; 126 } 127 128 std::string GetName() const 129 { 130 return methodName_; 131 } 132 133 std::string methodName_; 134 uint64_t totalCount_; 135 }; 136 137 struct Record { 138 Record(EcmaOpcode opcode) : opcode_(opcode), fast_(0), slow_(0) {} 139 140 uint64_t Count() const 141 { 142 return fast_ + slow_; 143 } 144 145 uint64_t GetFast() const 146 { 147 return fast_; 148 } 149 150 uint64_t GetSlow() const 151 { 152 return slow_; 153 } 154 155 EcmaOpcode GetOpCode() const 156 { 157 return opcode_; 158 } 159 160 void IncFast() 161 { 162 fast_ = fast_ + 1; 163 } 164 165 void IncSlow() 166 { 167 slow_ = slow_ + 1; 168 } 169 170 EcmaOpcode opcode_; 171 uint64_t fast_; 172 uint64_t slow_; 173 }; 174 175 OptCodeProfiler() 176 { 177#if ECMASCRIPT_ENABLE_OPT_CODE_PROFILER 178 profMap_ = { 179#define BYTECODE_PROF_MAP(name) { kungfu::EcmaOpcode::name, OptCodeProfiler::Value() }, 180 ECMA_OPCODE_LIST(BYTECODE_PROF_MAP) 181#undef BYTECODE_PROF_MAP 182 }; 183#endif 184 } 185 186 ~OptCodeProfiler(); 187 188 void Update(JSHandle<JSTaggedValue> &func, int bcIndex, EcmaOpcode opcode, Mode mode); 189 190 void PrintAndReset(); 191 192 using BcRecord = std::map<int, Record>; 193private: 194 void FilterMethodToPrint(); 195 void PrintMethodRecord(Key key, std::string methodName); 196 void ResetMethodInfo() 197 { 198 methodIdToRecord_.clear(); 199 methodIdToName_.clear(); 200 } 201#if ECMASCRIPT_ENABLE_JIT_WARMUP_PROFILER == 0 202 int printMehodCount_ {10}; 203#endif 204 std::map<EcmaOpcode, Value> profMap_; 205 std::map<uint64_t, BcRecord> methodIdToRecord_; 206 std::map<uint64_t, Name> methodIdToName_; 207 std::vector<CString> abcNames_; 208}; 209 210class TypedOpProfiler { 211public: 212 using OpCode = kungfu::OpCode; 213 214 TypedOpProfiler() 215 { 216 strOpMap_ = { 217#define DECLARE_GATE_OPCODE(NAME, OP, R, S, D, V) \ 218 { #OP, OpCode::OP }, 219 220 MCR_IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_OPCODE) 221 MCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_OPCODE) 222 MCR_GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_OPCODE) 223 MCR_GATE_META_DATA_LIST_WITH_VALUE(DECLARE_GATE_OPCODE) 224 MCR_GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_OPCODE) 225 MCR_GATE_META_DATA_LIST_WITH_GATE_TYPE(DECLARE_GATE_OPCODE) 226 MCR_GATE_META_DATA_LIST_WITH_VALUE_IN(DECLARE_GATE_OPCODE) 227#undef DECLARE_GATE_OPCODE 228 }; 229 230 profMap_ = { 231#define DECLARE_GATE_OPCODE(NAME, OP, R, S, D, V) \ 232 { OpCode::OP, 0 }, 233 234 MCR_IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_OPCODE) 235 MCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_OPCODE) 236 MCR_GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_OPCODE) 237 MCR_GATE_META_DATA_LIST_WITH_VALUE(DECLARE_GATE_OPCODE) 238 MCR_GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_OPCODE) 239 MCR_GATE_META_DATA_LIST_WITH_GATE_TYPE(DECLARE_GATE_OPCODE) 240 MCR_GATE_META_DATA_LIST_WITH_VALUE_IN(DECLARE_GATE_OPCODE) 241#undef DECLARE_GATE_OPCODE 242 }; 243 } 244 245 void Update(OpCode opcode) 246 { 247 auto it = profMap_.find(opcode); 248 if (it != profMap_.end()) { 249 it->second++; 250 recordOp_.insert(opcode); 251 } 252 } 253 254 void Print(std::string opStr) 255 { 256 auto it = strOpMap_.find(opStr); 257 if (it != strOpMap_.end()) { 258 LOG_TRACE(INFO) << "Opcode: " << it->first << " Count:" 259 << profMap_.at(it->second); 260 } 261 } 262 263 void Clear() 264 { 265 for (OpCode op : recordOp_) { 266 profMap_.at(op) = 0; 267 } 268 recordOp_.clear(); 269 } 270 271private: 272 std::map<std::string, OpCode> strOpMap_; 273 std::map<OpCode, uint64_t> profMap_; 274 std::set<OpCode> recordOp_ {}; 275}; 276} // namespace panda::ecmascript 277#endif // ECMASCRIPT_DFX_VMSTAT_OPT_CODE_PROFILER_H 278