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 51 namespace panda::ecmascript { 52 class OptCodeProfiler { 53 public: 54 using EcmaOpcode = kungfu::EcmaOpcode; 55 56 enum Mode { 57 TYPED_PATH, 58 SLOW_PATH, 59 }; 60 61 struct Value { Valuepanda::ecmascript::OptCodeProfiler::Value62 Value() : typedPathValue(0), slowPathValue(0) {} 63 TypedPathCountpanda::ecmascript::OptCodeProfiler::Value64 uint64_t TypedPathCount() const 65 { 66 return typedPathValue; 67 } 68 SlowPathCountpanda::ecmascript::OptCodeProfiler::Value69 uint64_t SlowPathCount() const 70 { 71 return slowPathValue; 72 } 73 Countpanda::ecmascript::OptCodeProfiler::Value74 uint64_t Count() const 75 { 76 return typedPathValue + slowPathValue; 77 } 78 ResetStatpanda::ecmascript::OptCodeProfiler::Value79 void ResetStat() 80 { 81 typedPathValue = 0; 82 slowPathValue = 0; 83 } 84 85 uint64_t typedPathValue; 86 uint64_t slowPathValue; 87 }; 88 89 struct Key { Keypanda::ecmascript::OptCodeProfiler::Key90 Key(uint32_t abcId, uint32_t methodId) 91 { 92 abcAndMethodId_ = (((uint64_t)abcId) << 32) + methodId; // 32: 32bit 93 } 94 Keypanda::ecmascript::OptCodeProfiler::Key95 Key(uint64_t key) : abcAndMethodId_(key) {}; 96 GetAbcIdpanda::ecmascript::OptCodeProfiler::Key97 uint32_t GetAbcId() const 98 { 99 return (uint32_t) (abcAndMethodId_ >> 32); // 32: 32bit 100 } 101 GetMethodIdpanda::ecmascript::OptCodeProfiler::Key102 uint32_t GetMethodId() const 103 { 104 return (uint32_t) abcAndMethodId_; 105 } 106 Valuepanda::ecmascript::OptCodeProfiler::Key107 uint64_t Value() const 108 { 109 return abcAndMethodId_; 110 } 111 112 uint64_t abcAndMethodId_; 113 }; 114 115 struct Name { Namepanda::ecmascript::OptCodeProfiler::Name116 Name(std::string name) : methodName_(name), totalCount_(1) {} 117 Countpanda::ecmascript::OptCodeProfiler::Name118 uint64_t Count() const 119 { 120 return totalCount_; 121 } 122 Incpanda::ecmascript::OptCodeProfiler::Name123 void Inc() 124 { 125 totalCount_ = totalCount_ + 1; 126 } 127 GetNamepanda::ecmascript::OptCodeProfiler::Name128 std::string GetName() const 129 { 130 return methodName_; 131 } 132 133 std::string methodName_; 134 uint64_t totalCount_; 135 }; 136 137 struct Record { Recordpanda::ecmascript::OptCodeProfiler::Record138 Record(EcmaOpcode opcode) : opcode_(opcode), fast_(0), slow_(0) {} 139 Countpanda::ecmascript::OptCodeProfiler::Record140 uint64_t Count() const 141 { 142 return fast_ + slow_; 143 } 144 GetFastpanda::ecmascript::OptCodeProfiler::Record145 uint64_t GetFast() const 146 { 147 return fast_; 148 } 149 GetSlowpanda::ecmascript::OptCodeProfiler::Record150 uint64_t GetSlow() const 151 { 152 return slow_; 153 } 154 GetOpCodepanda::ecmascript::OptCodeProfiler::Record155 EcmaOpcode GetOpCode() const 156 { 157 return opcode_; 158 } 159 IncFastpanda::ecmascript::OptCodeProfiler::Record160 void IncFast() 161 { 162 fast_ = fast_ + 1; 163 } 164 IncSlowpanda::ecmascript::OptCodeProfiler::Record165 void IncSlow() 166 { 167 slow_ = slow_ + 1; 168 } 169 170 EcmaOpcode opcode_; 171 uint64_t fast_; 172 uint64_t slow_; 173 }; 174 OptCodeProfiler()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>; 193 private: 194 void FilterMethodToPrint(); 195 void PrintMethodRecord(Key key, std::string methodName); ResetMethodInfo()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 210 class TypedOpProfiler { 211 public: 212 using OpCode = kungfu::OpCode; 213 TypedOpProfiler()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 Update(OpCode opcode)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 Print(std::string opStr)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 Clear()263 void Clear() 264 { 265 for (OpCode op : recordOp_) { 266 profMap_.at(op) = 0; 267 } 268 recordOp_.clear(); 269 } 270 271 private: 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