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
16 #include "ecmascript/compiler/compiler_log.h"
17
18 namespace panda::ecmascript::kungfu {
CompilerLog(const std::string & logOpt)19 CompilerLog::CompilerLog(const std::string &logOpt)
20 {
21 outputCIR_ = (logOpt.find("cir") != std::string::npos) || (logOpt.find("0") != std::string::npos);
22 outputLLIR_ = (logOpt.find("llir") != std::string::npos) || (logOpt.find("1") != std::string::npos);
23 outputASM_ = (logOpt.find("asm") != std::string::npos) || (logOpt.find("2") != std::string::npos);
24 outputType_ = (logOpt.find("type") != std::string::npos) || (logOpt.find("3") != std::string::npos);
25 allMethod_ = logOpt.find("all") != std::string::npos;
26 cerMethod_ = (logOpt.find("all") == std::string::npos) && (logOpt.find("cer") != std::string::npos);
27 noneMethod_ = (logOpt.find("all") == std::string::npos) && (logOpt.find("cer") == std::string::npos);
28 }
29
SetMethodLog(const std::string & fileName,const std::string & methodName,AotMethodLogList * logList)30 void CompilerLog::SetMethodLog(const std::string &fileName,
31 const std::string &methodName, AotMethodLogList *logList)
32 {
33 bool enableMethodLog = !NoneMethod();
34 if (CertainMethod()) {
35 enableMethodLog = logList->IncludesMethod(fileName, methodName);
36 }
37 SetEnableMethodLog(enableMethodLog);
38 }
39
SetStubLog(const std::string & stubName,MethodLogList * logList)40 void CompilerLog::SetStubLog(const std::string &stubName, MethodLogList *logList)
41 {
42 bool enableMethodLog = !NoneMethod();
43 if (CertainMethod()) {
44 enableMethodLog = logList->IncludesMethod(stubName);
45 }
46 SetEnableMethodLog(enableMethodLog);
47 }
48
IncludesMethod(const std::string & methodName) const49 bool MethodLogList::IncludesMethod(const std::string &methodName) const
50 {
51 bool empty = methodName.empty();
52 bool found = methods_.find(methodName) != std::string::npos;
53 return !empty && found;
54 }
55
IncludesMethod(const std::string & fileName,const std::string & methodName) const56 bool AotMethodLogList::IncludesMethod(const std::string &fileName, const std::string &methodName) const
57 {
58 if (fileMethods_.find(fileName) == fileMethods_.end()) {
59 return false;
60 }
61 std::vector methodVector = fileMethods_.at(fileName);
62 auto it = find(methodVector.begin(), methodVector.end(), methodName);
63 return (it != methodVector.end());
64 }
65
spiltString(const std::string & str,const char ch)66 std::vector<std::string> AotMethodLogList::spiltString(const std::string &str, const char ch)
67 {
68 std::vector<std::string> vec {};
69 std::istringstream sstr(str.c_str());
70 std::string spilt;
71 while (getline(sstr, spilt, ch)) {
72 vec.emplace_back(spilt);
73 }
74 return vec;
75 }
76
ParseFileMethodsName(const std::string & logMethods)77 void AotMethodLogList::ParseFileMethodsName(const std::string &logMethods)
78 {
79 std::vector<std::string> fileVector = spiltString(logMethods, fileSplitSign);
80 std::vector<std::string> itemVector;
81 for (size_t index = 0; index < fileVector.size(); ++index) {
82 itemVector = spiltString(fileVector[index], methodSplitSign);
83 std::vector<std::string> methodVector(itemVector.begin() + 1, itemVector.end());
84 fileMethods_[itemVector[0]] = methodVector;
85 }
86 }
87
TimeScope(std::string name,std::string methodName,uint32_t methodOffset,CompilerLog * log)88 TimeScope::TimeScope(std::string name, std::string methodName, uint32_t methodOffset, CompilerLog* log)
89 : ClockScope(), name_(std::move(name)), methodName_(std::move(methodName)), methodOffset_(methodOffset), log_(log)
90 {
91 if (log_->GetEnableCompilerLogTime()) {
92 if (log_->nameIndex_.find(name_) == log_->nameIndex_.end()) {
93 log_->nameIndex_[name_] = log_->GetIndex();
94 }
95 startTime_ = ClockScope().GetCurTime();
96 }
97 }
98
TimeScope(std::string name,CompilerLog * log)99 TimeScope::TimeScope(std::string name, CompilerLog* log)
100 : ClockScope(), name_(std::move(name)), log_(log)
101 {
102 if (log_->GetEnableCompilerLogTime()) {
103 if (log_->nameIndex_.find(name_) == log_->nameIndex_.end()) {
104 log_->nameIndex_[name_] = log_->GetIndex();
105 }
106 startTime_ = ClockScope().GetCurTime();
107 }
108 }
109
~TimeScope()110 TimeScope::~TimeScope()
111 {
112 if (log_->GetEnableCompilerLogTime()) {
113 timeUsed_ = ClockScope().GetCurTime() - startTime_;
114 if (log_->CertainMethod() && log_->GetEnableMethodLog()) {
115 LOG_COMPILER(INFO) << std::setw(PASS_LENS) << name_ << " " << std::setw(METHOD_LENS)
116 << GetShortName(methodName_) << " offset:" << std::setw(OFFSET_LENS) << methodOffset_
117 << " time used:" << std::setw(TIME_LENS) << timeUsed_ / MILLION_TIME << "ms";
118 }
119 std::string shortName = GetShortName(methodName_);
120 log_->AddPassTime(name_, timeUsed_);
121 log_->AddMethodTime(shortName, methodOffset_, timeUsed_);
122 }
123 }
124
GetShortName(const std::string & methodName)125 const std::string TimeScope::GetShortName(const std::string& methodName)
126 {
127 std::string KeyStr = "@";
128 if (methodName.find(KeyStr) != std::string::npos) {
129 std::string::size_type index = methodName.find(KeyStr);
130 std::string extracted = methodName.substr(0, index);
131 return extracted;
132 } else {
133 return methodName;
134 }
135 }
136
Print() const137 void CompilerLog::Print() const
138 {
139 if (compilerLogTime_) {
140 PrintTime();
141 }
142 }
143
PrintPassTime() const144 void CompilerLog::PrintPassTime() const
145 {
146 double allPassTimeforAllMethods = 0;
147 auto myMap = timePassMap_;
148 auto myIndexMap = nameIndex_;
149 std::multimap<int, std::string> PassTimeMap;
150 for (auto it = myMap.begin(); it != myMap.end(); it++) {
151 PassTimeMap.insert(make_pair(myIndexMap[it->first], it->first));
152 allPassTimeforAllMethods += it->second;
153 }
154 for (auto [key, val] : PassTimeMap) {
155 LOG_COMPILER(INFO) << std::setw(PASS_LENS) << val << " Total cost time is "<< std::setw(TIME_LENS)
156 << myMap[val] / MILLION_TIME << "ms " << "percentage:"
157 << std::fixed << std::setprecision(PERCENT_LENS)
158 << myMap[val] / allPassTimeforAllMethods * HUNDRED_TIME << "% ";
159 }
160 }
161
PrintMethodTime() const162 void CompilerLog::PrintMethodTime() const
163 {
164 double methodTotalTime = 0;
165 auto myMap = timeMethodMap_;
166 std::multimap<double, std::pair<uint32_t, std::string>> MethodTimeMap;
167 std::map<std::pair<uint32_t, std::string>, double>::iterator it;
168 for (it = myMap.begin(); it != myMap.end(); it++) {
169 MethodTimeMap.insert(make_pair(it->second, it->first));
170 }
171 for (auto [key, val] : MethodTimeMap) {
172 methodTotalTime += key;
173 }
174 for (auto [key, val] : MethodTimeMap) {
175 LOG_COMPILER(INFO) << "method:" << std::setw(METHOD_LENS) << val.second
176 << " offset:" << std::setw(OFFSET_LENS) << val.first << " all pass cost time is "
177 << std::setw(TIME_LENS) << key / MILLION_TIME << "ms " << "percentage:" << std::fixed
178 << std::setprecision(PERCENT_LENS) << key / methodTotalTime * HUNDRED_TIME << "% ";
179 }
180 LOG_COMPILER(INFO) << "total compile time is " << std::setw(TIME_LENS) << methodTotalTime / MILLION_TIME << "ms ";
181 }
182
PrintTime() const183 void CompilerLog::PrintTime() const
184 {
185 LOG_COMPILER(INFO) << " ";
186 PrintPassTime();
187 LOG_COMPILER(INFO) << " ";
188 PrintMethodTime();
189 }
190
AddMethodTime(const std::string & name,uint32_t id,double time)191 void CompilerLog::AddMethodTime(const std::string& name, uint32_t id, double time)
192 {
193 auto methodInfo = std::make_pair(id, name);
194 timeMethodMap_[methodInfo] += time;
195 }
196
AddPassTime(const std::string & name,double time)197 void CompilerLog::AddPassTime(const std::string& name, double time)
198 {
199 timePassMap_[name] += time;
200 }
201
GetIndex()202 int CompilerLog::GetIndex()
203 {
204 return (idx_++);
205 }
206
CollectGateTypeLogInfo(GateRef gate,bool isBinOp)207 void PGOTypeLogList::CollectGateTypeLogInfo(GateRef gate, bool isBinOp)
208 {
209 log_ += "[PGOTypePrinter] ";
210 log_ += "gate id: "+ std::to_string(acc_.GetId(gate)) + ", ";
211 EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
212 log_ += "bytecode: " + GetEcmaOpcodeStr(ecmaOpcode);
213
214 uint32_t pcOffset = acc_.TryGetPcOffset(gate);
215 if (isBinOp) {
216 const PGOSampleType *sampleType = acc_.TryGetPGOType(gate).GetPGOSampleType();
217 if (sampleType->IsString()) {
218 log_ += " [left type: string, right type: string]";
219 } else if (sampleType->HasNumber()) {
220 if (sampleType->IsInt()) {
221 log_ += " [left type: int, right type: int]";
222 } else {
223 if (sampleType->IsIntOverFlow()) {
224 log_ += " [left type: int, right type: int]";
225 } else if (sampleType->IsDouble()) {
226 log_ += " [left type: double, right type: double]";
227 } else {
228 log_ += " [left type: number, right type: number]";
229 }
230 }
231 } else {
232 GateRef left = acc_.GetValueIn(gate, 0);
233 GateRef right = acc_.GetValueIn(gate, 1);
234 GateType leftType = acc_.GetGateType(left);
235 GateType rightType = acc_.GetGateType(right);
236 if (leftType.IsIntType()) {
237 log_ += " [left type: int, ";
238 } else if (leftType.IsDoubleType()) {
239 log_ += " [left type: double, ";
240 } else {
241 log_ += " [left type: number, ";
242 }
243 if (rightType.IsIntType()) {
244 log_ += "right type: int]";
245 } else if (rightType.IsDoubleType()) {
246 log_ += "right type: double]";
247 } else {
248 log_ += "right type: number]";
249 }
250 }
251 } else {
252 GateRef value = acc_.GetValueIn(gate, 0);
253 GateType valueType = acc_.GetGateType(value);
254 if (valueType.IsIntType()) {
255 log_ += " [type: int]";
256 } else if (valueType.IsDoubleType()) {
257 log_ += " [type: double]";
258 } else {
259 log_ += " [type: number]";
260 }
261 }
262 log_ += ", pcOffset: " + std::to_string(pcOffset);
263 log_ += "\n[compiler] ";
264 }
265
PrintPGOTypeLog()266 void PGOTypeLogList::PrintPGOTypeLog()
267 {
268 LOG_COMPILER(INFO) << log_;
269 }
270
271 } // namespace panda::ecmascript::kungfu
272