1 /*
2  * Copyright (c) 2023 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_COMPILER_AOT_COMPILER_PREPROCESSOR_H
16 #define ECMASCRIPT_COMPILER_AOT_COMPILER_PREPROCESSOR_H
17 
18 #include "ecmascript/compiler/bytecode_info_collector.h"
19 #include "ecmascript/compiler/compiler_log.h"
20 #include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
21 #include "ecmascript/ecma_vm.h"
22 #include "macros.h"
23 #include "ecmascript/compiler/aot_compilation_env.h"
24 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
25 #include "ecmascript/ohos/ohos_preload_app_info.h"
26 
27 namespace panda::ecmascript::kungfu {
28 class OhosPkgArgs;
29 using PGOProfilerDecoder = pgo::PGOProfilerDecoder;
30 
31 struct AbcFileInfo {
AbcFileInfopanda::ecmascript::kungfu::AbcFileInfo32     explicit AbcFileInfo(std::string extendedFilePath, std::shared_ptr<JSPandaFile> jsPandaFile)
33         : extendedFilePath_(extendedFilePath), jsPandaFile_(jsPandaFile) {}
34     ~AbcFileInfo() = default;
35 
36     std::string extendedFilePath_;
37     std::shared_ptr<JSPandaFile> jsPandaFile_;
38 };
39 
40 class CallMethodFlagMap {
41 public:
CallMethodFlagMap()42     CallMethodFlagMap() {}
43     void SetIsFastCall(CString fileDesc, uint32_t methodOffset, bool isFastCall);
44     bool IsFastCall(CString fileDesc, uint32_t methodOffset) const;
45     void SetIsAotCompile(CString fileDesc, uint32_t methodOffset, bool isAotCompile);
46     bool IsAotCompile(CString fileDesc, uint32_t methodOffset) const;
47     void SetIsJitCompile(CString fileDesc, uint32_t methodOffset, bool isAotCompile);
48     bool IsJitCompile(CString fileDesc, uint32_t methodOffset) const;
49 private:
50     std::map<std::pair<CString, uint32_t>, bool> abcIdMethodIdToIsFastCall_ {};
51     std::map<std::pair<CString, uint32_t>, bool> abcIdMethodIdToIsAotCompile_ {};
52     std::map<std::pair<CString, uint32_t>, bool> abcIdMethodIdToIsJitCompile_ {};
53 };
54 
55 struct CompilationOptions {
56     explicit CompilationOptions(JSRuntimeOptions &runtimeOptions);
57     void ParseOption(const std::string &option, std::map<std::string, std::vector<std::string>> &optionMap) const;
58     std::vector<std::string> SplitString(const std::string &str, const char ch) const;
59     std::string triple_;
60     std::string outputFileName_;
61     size_t optLevel_;
62     size_t relocMode_;
63     std::string logOption_;
64     std::string logMethodsList_;
65     bool compilerLogTime_;
66     bool deviceIsScreenOff_;
67     size_t maxAotMethodSize_;
68     size_t maxMethodsInModule_;
69     uint32_t hotnessThreshold_;
70     int32_t deviceThermalLevel_ {0};
71     std::string profilerIn_;
72     std::string optBCRange_;
73     bool needMerge_ {false};
74     bool isEnableArrayBoundsCheckElimination_ {true};
75     bool isEnableTypeLowering_ {true};
76     bool isEnableEarlyElimination_ {true};
77     bool isEnableLaterElimination_ {true};
78     bool isEnableValueNumbering_ {true};
79     bool isEnableOptInlining_ {true};
80     bool isEnableOptString_ {true};
81     bool isEnableOptPGOType_ {true};
82     bool isEnableOptTrackField_ {true};
83     bool isEnableOptLoopPeeling_ {true};
84     bool isEnableOptLoopInvariantCodeMotion_ {false};
85     bool isEnableOptConstantFolding_ {true};
86     bool isEnableLexenvSpecialization_ {false};
87     bool isEnableNativeInline_ {true};
88     bool isEnablePGOHCRLowering_ {false};
89     bool isEnableLoweringBuiltin_ {true};
90     bool isEnableOptBranchProfiling_ {true};
91     bool isEnableEscapeAnalysis_ {false};
92     bool isEnableInductionVariableAnalysis_ {false};
93     bool isEnableVerifierPass_ {true};
94     bool isEnableBaselinePgo_ {false};
95     std::map<std::string, std::vector<std::string>> optionSelectMethods_;
96     std::map<std::string, std::vector<std::string>> optionSkipMethods_;
97 };
98 
99 class AotCompilerPreprocessor {
100 public:
AotCompilerPreprocessor(EcmaVM *vm, JSRuntimeOptions &runtimeOptions, std::map<std::string, std::shared_ptr<OhosPkgArgs>> &pkgsArgs, PGOProfilerDecoder &profilerDecoder, arg_list_t &pandaFileNames)101     AotCompilerPreprocessor(EcmaVM *vm, JSRuntimeOptions &runtimeOptions,
102                             std::map<std::string, std::shared_ptr<OhosPkgArgs>> &pkgsArgs,
103                             PGOProfilerDecoder &profilerDecoder, arg_list_t &pandaFileNames)
104         : vm_(vm),
105           runtimeOptions_(runtimeOptions),
106           pkgsArgs_(pkgsArgs),
107           profilerDecoder_(profilerDecoder),
108           pandaFileNames_(pandaFileNames),
109           aotCompilationEnv_(vm) {};
110 
111     ~AotCompilerPreprocessor() = default;
112 
113     bool HandleTargetCompilerMode(CompilationOptions &cOptions);
114 
115     bool HandlePandaFileNames(const int argc, const char **argv);
116 
117     void AOTInitialize();
118 
119     void DoPreAnalysis(CompilationOptions &cOptions);
120 
121     void AnalyzeGraphs(JSPandaFile *jsPandaFile, BytecodeInfoCollector &collector, CompilationOptions &cOptions);
122 
123     void AnalyzeGraph(BCInfo &bytecodeInfo, CompilationOptions &cOptions, BytecodeInfoCollector &collector,
124                       MethodLiteral *methodLiteral, MethodPcInfo &methodPCInfo);
125 
126     void Process(CompilationOptions &cOptions);
127 
128     uint32_t GenerateAbcFileInfos();
129 
130     void GenerateBytecodeInfoCollectors(const CompilationOptions &cOptions);
131 
132     bool HandleMergedPgoFile(uint32_t checksum);
133 
134     void GeneratePGOTypes();
135 
136     void SnapshotInitialize();
137 
138     bool FilterOption(const std::map<std::string, std::vector<std::string>> &optionMap,
139                       const std::string &recordName, const std::string &methodName) const;
140 
141     bool IsSkipMethod(const JSPandaFile *jsPandaFile, const BCInfo &bytecodeInfo,
142                       const CString &recordName, const MethodLiteral *methodLiteral,
143                       const MethodPcInfo &methodPCInfo, const std::string &methodName,
144                       CompilationOptions &cOptions) const;
145 
146     void GenerateMethodMap(CompilationOptions &cOptions);
147 
148     bool MethodHasTryCatch(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral) const;
149 
150     bool HasSkipMethod(const CVector<std::string> &methodList, const std::string &methodName) const;
151 
152     bool ForbidenRebuildAOT(std::string &fileName) const;
153 
154     bool HasPreloadAotFile() const;
155 
156     bool HasExistsAOTFiles(CompilationOptions &cOptions) const;
157 
SetIsFastCall(CString fileDesc, uint32_t methodOffset, bool isFastCall)158     void SetIsFastCall(CString fileDesc, uint32_t methodOffset, bool isFastCall)
159     {
160         callMethodFlagMap_.SetIsFastCall(fileDesc, methodOffset, isFastCall);
161     }
162 
IsFastCall(CString fileDesc, uint32_t methodOffset)163     bool IsFastCall(CString fileDesc, uint32_t methodOffset)
164     {
165         return callMethodFlagMap_.IsFastCall(fileDesc, methodOffset);
166     }
167 
SetIsAotCompile(CString fileDesc, uint32_t methodOffset, bool isAotCompile)168     void SetIsAotCompile(CString fileDesc, uint32_t methodOffset, bool isAotCompile)
169     {
170         callMethodFlagMap_.SetIsAotCompile(fileDesc, methodOffset, isAotCompile);
171     }
172 
GetIsAotCompile(CString fileDesc, uint32_t methodOffset)173     bool GetIsAotCompile(CString fileDesc, uint32_t methodOffset)
174     {
175         return callMethodFlagMap_.IsAotCompile(fileDesc, methodOffset);
176     }
177 
178     std::string GetMainPkgArgsAppSignature() const;
179 
GetCompilerResult()180     bool GetCompilerResult()
181     {
182         // The size of fileInfos is not equal to pandaFiles size, set compiler result to false
183         return fileInfos_.size() == pandaFileNames_.size();
184     }
185 
GetAbcFileInfo() const186     const CVector<AbcFileInfo>& GetAbcFileInfo() const
187     {
188         return fileInfos_;
189     }
190 
GetBcInfoCollectors() const191     const CVector<std::unique_ptr<BytecodeInfoCollector>>& GetBcInfoCollectors() const
192     {
193         return bcInfoCollectors_;
194     }
195 
GetMainPkgArgs() const196     std::shared_ptr<OhosPkgArgs> GetMainPkgArgs() const
197     {
198         if (pkgsArgs_.empty()) {
199             return nullptr;
200         }
201         return pkgsArgs_.at(mainPkgName_);
202     }
203 
GetPkgsArgs() const204     const std::map<std::string, std::shared_ptr<OhosPkgArgs>> &GetPkgsArgs() const
205     {
206         return pkgsArgs_;
207     }
GetCallMethodFlagMap()208     CallMethodFlagMap *GetCallMethodFlagMap()
209     {
210         return &callMethodFlagMap_;
211     }
212 
GetHelper()213     static std::string GetHelper()
214     {
215         std::string str;
216         str.append(COMPILER_HELP_HEAD_MSG);
217         str.append(HELP_OPTION_MSG);
218         return str;
219     }
220 
221 private:
222     NO_COPY_SEMANTIC(AotCompilerPreprocessor);
223     NO_MOVE_SEMANTIC(AotCompilerPreprocessor);
224     void HandleTargetModeInfo(CompilationOptions &cOptions);
225 
226     std::shared_ptr<JSPandaFile> CreateAndVerifyJSPandaFile(const std::string &fileName);
227 
228     void ResolveModule(const JSPandaFile *jsPandaFile, const std::string &fileName);
229 
OutCompiledMethodsRange() const230     bool OutCompiledMethodsRange() const
231     {
232         static uint32_t compiledMethodsCount = 0;
233         ++compiledMethodsCount;
234         return compiledMethodsCount < runtimeOptions_.GetCompilerMethodsRange().first ||
235             runtimeOptions_.GetCompilerMethodsRange().second <= compiledMethodsCount;
236     }
237 
238     EcmaVM *vm_;
239     JSRuntimeOptions &runtimeOptions_;
240     std::map<std::string, std::shared_ptr<OhosPkgArgs>> &pkgsArgs_;
241     std::string mainPkgName_;
242     PGOProfilerDecoder &profilerDecoder_;
243     arg_list_t &pandaFileNames_;
244     CVector<AbcFileInfo> fileInfos_;
245     CVector<std::unique_ptr<BytecodeInfoCollector>> bcInfoCollectors_;
246     CallMethodFlagMap callMethodFlagMap_;
247     AOTCompilationEnv aotCompilationEnv_;
248     CVector<std::string> irreducibleMethods_;
249     friend class OhosPkgArgs;
250 };
251 }  // namespace panda::ecmascript::kungfu
252 #endif  // ECMASCRIPT_COMPILER_AOT_COMPILER_PREPROCESSOR_H
253