• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
22 // bcIndex   bytecode   count    fast    slow    typerate
23 // ====================(print all)=======================
24 // ........
25 // ======================================================
26 // total
27 
28 // tip: not print if count below 10000
29 // ====================(top1 method: name, methodId)=====
30 // .......
31 // (bcIndex   bytecode   count    fast    slow    typerate)
32 // .......
33 // ======================================================
34 
35 // ====================(top2 method: name)===============
36 // .......
37 // ======================================================
38 
39 // .......
40 
41 // ====================(top10 method: name)==============
42 // .......
43 // ======================================================
44 
45 // methodId, abcId, bcIndex, Value1(opcode, fastcount, slowcount),Value2(methodName, totalcount)
46 // key: methodId, abcId
47 // std::map<key, <bcIndex, Value1>>
48 // std::map<key, Value2>
49 
50 namespace panda::ecmascript {
51 class OptCodeProfiler {
52 public:
53     using EcmaOpcode = kungfu::EcmaOpcode;
54 
55     enum Mode {
56         TYPED_PATH,
57         SLOW_PATH,
58     };
59 
60     struct Value {
ValueValue61         Value() : typedPathValue(0), slowPathValue(0) {}
62 
TypedPathCountValue63         uint64_t TypedPathCount() const
64         {
65             return typedPathValue;
66         }
67 
SlowPathCountValue68         uint64_t SlowPathCount() const
69         {
70             return slowPathValue;
71         }
72 
CountValue73         uint64_t Count() const
74         {
75             return typedPathValue + slowPathValue;
76         }
77 
ResetStatValue78         void ResetStat()
79         {
80             typedPathValue = 0;
81             slowPathValue = 0;
82         }
83 
84         uint64_t typedPathValue;
85         uint64_t slowPathValue;
86     };
87 
88     struct Key {
KeyKey89         Key(uint32_t abcId, uint32_t methodId)
90         {
91             abcAndMethodId_ = (((uint64_t)abcId) << 32) + methodId; // 32: 32bit
92         }
93 
KeyKey94         Key(uint64_t key) : abcAndMethodId_(key) {};
95 
GetAbcIdKey96         uint32_t GetAbcId() const
97         {
98             return (uint32_t) (abcAndMethodId_ >> 32); // 32: 32bit
99         }
100 
GetMehodIdKey101         uint32_t GetMehodId() const
102         {
103             return (uint32_t) abcAndMethodId_;
104         }
105 
ValueKey106         uint64_t Value() const
107         {
108             return abcAndMethodId_;
109         }
110 
111         uint64_t abcAndMethodId_;
112     };
113 
114     struct Name {
NameName115         Name(std::string name) : methodName_(name), totalCount_(1) {}
116 
CountName117         uint64_t Count() const
118         {
119             return totalCount_;
120         }
121 
IncName122         void Inc()
123         {
124             totalCount_ = totalCount_ + 1;
125         }
126 
GetNameName127         std::string GetName() const
128         {
129             return methodName_;
130         }
131 
132         std::string methodName_;
133         uint64_t totalCount_;
134     };
135 
136     struct Record {
RecordRecord137         Record(EcmaOpcode opcode) : opcode_(opcode), fast_(0), slow_(0) {}
138 
CountRecord139         uint64_t Count() const
140         {
141             return fast_ + slow_;
142         }
143 
GetFastRecord144         uint64_t GetFast() const
145         {
146             return fast_;
147         }
148 
GetSlowRecord149         uint64_t GetSlow() const
150         {
151             return slow_;
152         }
153 
GetOpCodeRecord154         EcmaOpcode GetOpCode() const
155         {
156             return opcode_;
157         }
158 
IncFastRecord159         void IncFast()
160         {
161             fast_ = fast_ + 1;
162         }
163 
IncSlowRecord164         void IncSlow()
165         {
166             slow_ = slow_ + 1;
167         }
168 
169         EcmaOpcode opcode_;
170         uint64_t fast_;
171         uint64_t slow_;
172     };
173 
OptCodeProfiler()174     OptCodeProfiler()
175     {
176 #if ECMASCRIPT_ENABLE_OPT_CODE_PROFILER
177         profMap_ = {
178 #define BYTECODE_PROF_MAP(name) { kungfu::EcmaOpcode::name, OptCodeProfiler::Value() },
179     ECMA_OPCODE_LIST(BYTECODE_PROF_MAP)
180 #undef BYTECODE_PROF_MAP
181         };
182 #endif
183     }
184 
185     ~OptCodeProfiler();
186 
187     void Update(JSHandle<JSTaggedValue> &func, int bcIndex, EcmaOpcode opcode, Mode mode);
188 
189     void PrintAndReset();
190 
191     using BcRecord = std::map<int, Record>;
192 private:
193     void FilterMethodToPrint();
194     void PrintMethodRecord(Key key, std::string methodName);
ResetMethodInfo()195     void ResetMethodInfo()
196     {
197         methodIdToRecord_.clear();
198         methodIdToName_.clear();
199     }
200 
201     int printMehodCount_ {10};
202     int skipMaxCount_ {10000};
203     std::map<EcmaOpcode, Value> profMap_;
204     std::map<uint64_t, BcRecord> methodIdToRecord_;
205     std::map<uint64_t, Name> methodIdToName_;
206     std::vector<CString> abcNames_;
207 };
208 
209 class TypedOpProfiler {
210 public:
211     using OpCode = kungfu::OpCode;
212 
TypedOpProfiler()213     TypedOpProfiler()
214     {
215         strOpMap_ = {
216             { "LOAD_BUILTIN_OBJECT", OpCode::LOAD_BUILTIN_OBJECT },
217             { "LOAD_PROPERTY", OpCode::LOAD_PROPERTY },
218             { "LOAD_ELEMENT", OpCode::LOAD_ELEMENT }
219         };
220 
221         profMap_ = {
222             { OpCode::LOAD_BUILTIN_OBJECT, 0 },
223             { OpCode::LOAD_PROPERTY, 0 },
224             { OpCode::LOAD_ELEMENT, 0 }
225         };
226     }
227 
Update(OpCode opcode)228     void Update(OpCode opcode)
229     {
230         auto it = profMap_.find(opcode);
231         if (it != profMap_.end()) {
232             it->second++;
233         }
234     }
235 
PrintAndReset(std::string opStr)236     void PrintAndReset(std::string opStr)
237     {
238         auto it = strOpMap_.find(opStr);
239         if (it != strOpMap_.end()) {
240             LOG_TRACE(INFO) << "Opcode: " << it->first << " Count:"
241                             << profMap_.at(it->second);
242 
243             profMap_.at(it->second) = 0;
244         }
245     }
246 
247 private:
248     std::map<std::string, OpCode> strOpMap_;
249     std::map<OpCode, uint64_t> profMap_;
250 };
251 }  // namespace panda::ecmascript
252 #endif  // ECMASCRIPT_DFX_VMSTAT_OPT_CODE_PROFILER_H
253