1 /*
2 * Copyright (c) 2021 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 <chrono>
17 #include <iostream>
18 #include <memory>
19
20 #include "ecmascript/base/string_helper.h"
21 #include "ecmascript/checkpoint/thread_state_transition.h"
22 #include "ecmascript/compiler/aot_compilation_env.h"
23 #include "ecmascript/compiler/aot_compiler_preprocessor.h"
24 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
25 #include "ecmascript/compiler/pass_manager.h"
26 #include "ecmascript/ecma_string.h"
27 #include "ecmascript/js_runtime_options.h"
28 #include "ecmascript/log.h"
29 #include "ecmascript/log_wrapper.h"
30 #include "ecmascript/napi/include/jsnapi.h"
31 #include "ecmascript/ohos/enable_aot_list_helper.h"
32 #include "ecmascript/ohos/ohos_pkg_args.h"
33 #include "ecmascript/platform/aot_crash_info.h"
34 #include "ecmascript/platform/file.h"
35 #include "ecmascript/platform/filesystem.h"
36
37 #include "ecmascript/compiler/aot_compiler_stats.h"
38
39 namespace panda::ecmascript::kungfu {
40 namespace {
41 /**
42 * @param ErrCode return code of ark_aot_compiler
43 * @attention it must sync with RetStatusOfCompiler of
44 * "ets_runtime/compiler_service/include/aot_compiler_constants.h"
45 */
46 enum ErrCode {
47 ERR_OK = (0), // IMPORTANT: Only if aot compiler SUCCESS and save an/ai SUCCESS, return ERR_OK.
48 ERR_FAIL = (-1),
49 ERR_HELP = (1),
50 ERR_NO_AP = (2),
51 ERR_MERGE_AP = (3),
52 ERR_CHECK_VERSION = (4),
53 ERR_AN_EMPTY = (5),
54 ERR_AN_FAIL = (6),
55 ERR_AI_FAIL = (7),
56 };
57
CheckVersion(JSRuntimeOptions& runtimeOptions, AotCompilerStats& compilerStats, bool isPgoMerged)58 bool CheckVersion(JSRuntimeOptions& runtimeOptions, AotCompilerStats& compilerStats, bool isPgoMerged)
59 {
60 if (runtimeOptions.IsCheckPgoVersion()) {
61 if (!isPgoMerged) {
62 LOG_COMPILER(ERROR) << "CheckVersion ap and abc may not match";
63 compilerStats.SetPgoFileLegal(false);
64 }
65 if (runtimeOptions.IsTargetCompilerMode()) {
66 compilerStats.PrintCompilerStatsLog();
67 }
68 return true;
69 }
70 return false;
71 }
72
IsExistsPkgInfo(AotCompilerPreprocessor &cPreprocessor)73 bool IsExistsPkgInfo(AotCompilerPreprocessor &cPreprocessor)
74 {
75 if (cPreprocessor.GetMainPkgArgs()) {
76 return true;
77 }
78 return false;
79 }
80 } // namespace
81
Main(const int argc, const char **argv)82 int Main(const int argc, const char **argv)
83 {
84 if (argc < 2) { // 2: at least have two arguments
85 LOG_COMPILER(ERROR) << AotCompilerPreprocessor::GetHelper();
86 return ERR_FAIL;
87 }
88
89 JSRuntimeOptions runtimeOptions;
90 bool retOpt = runtimeOptions.ParseCommand(argc, argv);
91 if (!retOpt) {
92 LOG_COMPILER(ERROR) << AotCompilerPreprocessor::GetHelper();
93 return ERR_HELP;
94 }
95
96 bool ret = true;
97 // ark_aot_compiler running need disable asm interpreter to disable the loading of AOT files.
98 runtimeOptions.SetEnableAsmInterpreter(false);
99 runtimeOptions.SetOptionsForTargetCompilation();
100 EcmaVM *vm = JSNApi::CreateEcmaVM(runtimeOptions);
101 if (vm == nullptr) {
102 LOG_COMPILER(ERROR) << "Cannot Create vm";
103 return ERR_FAIL;
104 }
105
106 {
107 AOTCompilationEnv aotCompilationEnv(vm);
108 ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
109 LocalScope scope(vm);
110 arg_list_t pandaFileNames {};
111 std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
112 CompilationOptions cOptions(runtimeOptions);
113
114 CompilerLog log(cOptions.logOption_);
115 log.SetEnableCompilerLogTime(cOptions.compilerLogTime_);
116 AotMethodLogList logList(cOptions.logMethodsList_);
117 PGOProfilerDecoder profilerDecoder;
118
119 AotCompilerPreprocessor cPreprocessor(vm, runtimeOptions, pkgArgsMap, profilerDecoder, pandaFileNames);
120 if (!cPreprocessor.HandleTargetCompilerMode(cOptions) || !cPreprocessor.HandlePandaFileNames(argc, argv)) {
121 return ERR_HELP;
122 }
123
124 if (IsExistsPkgInfo(cPreprocessor)) {
125 if (AotCrashInfo::IsAotEscaped(cPreprocessor.GetMainPkgArgs()->GetPgoDir())) {
126 LOG_COMPILER(ERROR) << "Stop compile AOT because there are multiple crashes";
127 return ERR_FAIL;
128 }
129 }
130 if (runtimeOptions.IsPartialCompilerMode() && cOptions.profilerIn_.empty()) {
131 // no need to compile in partial mode without any ap files.
132 return ERR_NO_AP;
133 }
134
135 AotCompilerStats compilerStats;
136 std::string bundleName = "";
137 if (cPreprocessor.GetMainPkgArgs()) {
138 bundleName = cPreprocessor.GetMainPkgArgs()->GetBundleName();
139 }
140 compilerStats.SetBundleName(bundleName);
141 compilerStats.SetAotFilePath(cOptions.outputFileName_);
142 compilerStats.SetPgoPath(cOptions.profilerIn_);
143 compilerStats.StartCompiler();
144 profilerDecoder.SetHotnessThreshold(cOptions.hotnessThreshold_);
145 profilerDecoder.SetInPath(cOptions.profilerIn_);
146 cPreprocessor.AOTInitialize();
147 uint32_t checksum = cPreprocessor.GenerateAbcFileInfos();
148
149 if (runtimeOptions.IsTargetCompilerMode() && (cPreprocessor.HasExistsAOTFiles(cOptions) ||
150 cPreprocessor.HasPreloadAotFile())) {
151 LOG_COMPILER(ERROR) << "The AOT file already exists and will not be compiled anymore";
152 return ERR_OK;
153 }
154
155 ret = cPreprocessor.GetCompilerResult();
156 // Notice: lx move load pandaFileHead and verify before GeneralAbcFileInfos.
157 // need support multiple abc
158 auto isPgoMerged = cPreprocessor.HandleMergedPgoFile(checksum);
159 if (CheckVersion(runtimeOptions, compilerStats, isPgoMerged)) {
160 return ERR_CHECK_VERSION;
161 }
162 std::string appSignature = cPreprocessor.GetMainPkgArgsAppSignature();
163 if (!isPgoMerged) {
164 AOTFileGenerator::SaveEmptyAOTFile(
165 cOptions.outputFileName_ + AOTFileManager::FILE_EXTENSION_AN, appSignature, true);
166 AOTFileGenerator::SaveEmptyAOTFile(
167 cOptions.outputFileName_ + AOTFileManager::FILE_EXTENSION_AI, appSignature, false);
168 return ERR_MERGE_AP;
169 }
170 cPreprocessor.Process(cOptions);
171
172 PassOptions::Builder optionsBuilder;
173 PassOptions passOptions =
174 optionsBuilder.EnableArrayBoundsCheckElimination(cOptions.isEnableArrayBoundsCheckElimination_)
175 .EnableTypeLowering(cOptions.isEnableTypeLowering_)
176 .EnableEarlyElimination(cOptions.isEnableEarlyElimination_)
177 .EnableLaterElimination(cOptions.isEnableLaterElimination_)
178 .EnableValueNumbering(cOptions.isEnableValueNumbering_)
179 .EnableOptInlining(cOptions.isEnableOptInlining_)
180 .EnableOptString(cOptions.isEnableOptString_)
181 .EnableOptPGOType(cOptions.isEnableOptPGOType_)
182 .EnableOptTrackField(cOptions.isEnableOptTrackField_)
183 .EnableOptLoopPeeling(cOptions.isEnableOptLoopPeeling_)
184 .EnableOptLoopInvariantCodeMotion(cOptions.isEnableOptLoopInvariantCodeMotion_)
185 .EnableOptConstantFolding(cOptions.isEnableOptConstantFolding_)
186 .EnableLexenvSpecialization(cOptions.isEnableLexenvSpecialization_)
187 .EnableInlineNative(cOptions.isEnableNativeInline_)
188 .EnableLoweringBuiltin(cOptions.isEnableLoweringBuiltin_)
189 .EnableOptBranchProfiling(cOptions.isEnableOptBranchProfiling_)
190 .EnableEscapeAnalysis(cOptions.isEnableEscapeAnalysis_)
191 .EnableInductionVariableAnalysis(cOptions.isEnableInductionVariableAnalysis_)
192 .EnableVerifierPass(cOptions.isEnableVerifierPass_)
193 .Build();
194
195 PassManager passManager(&aotCompilationEnv,
196 cOptions.triple_,
197 cOptions.optLevel_,
198 cOptions.relocMode_,
199 &log,
200 &logList,
201 cOptions.maxAotMethodSize_,
202 cOptions.maxMethodsInModule_,
203 profilerDecoder,
204 &passOptions,
205 cPreprocessor.GetCallMethodFlagMap(),
206 cPreprocessor.GetAbcFileInfo(),
207 cPreprocessor.GetBcInfoCollectors(),
208 cOptions.optBCRange_);
209
210 bool isEnableLiteCG = runtimeOptions.IsCompilerEnableLiteCG();
211 if (ohos::EnableAotJitListHelper::GetInstance()->IsEnableAot(bundleName)) {
212 isEnableLiteCG = true;
213 }
214 vm->GetJSOptions().SetCompilerEnableLiteCG(isEnableLiteCG);
215 compilerStats.SetIsLiteCg(isEnableLiteCG);
216
217 AOTFileGenerator generator(&log, &logList, &aotCompilationEnv, cOptions.triple_, isEnableLiteCG);
218
219 passManager.CompileValidFiles(generator, ret, compilerStats);
220 if (compilerStats.GetCompilerMethodCount() == 0) {
221 return runtimeOptions.IsPartialCompilerMode() ? ERR_AN_EMPTY : ERR_OK;
222 }
223 if (!generator.SaveAOTFile(cOptions.outputFileName_ + AOTFileManager::FILE_EXTENSION_AN, appSignature)) {
224 return ERR_AN_FAIL;
225 }
226 if (!generator.SaveSnapshotFile()) {
227 return ERR_AI_FAIL;
228 }
229 log.Print();
230 if (runtimeOptions.IsTargetCompilerMode()) {
231 compilerStats.PrintCompilerStatsLog();
232 }
233 if (IsExistsPkgInfo(cPreprocessor)) {
234 ohos::EnableAotJitListHelper::GetInstance()->AddEnableListCount(
235 ret, cPreprocessor.GetMainPkgArgs()->GetPgoDir());
236 }
237 }
238
239 if (vm->GetJSOptions().IsEnableCompilerLogSnapshot()) {
240 vm->PrintAOTSnapShotStats();
241 }
242 LOG_COMPILER(INFO) << (ret ? "ts aot compile success" : "ts aot compile failed");
243 JSNApi::DestroyJSVM(vm);
244 return ret ? ERR_OK : ERR_FAIL;
245 }
246 } // namespace panda::ecmascript::kungfu
247
main(const int argc, const char **argv)248 int main(const int argc, const char **argv)
249 {
250 auto result = panda::ecmascript::kungfu::Main(argc, argv);
251 return result;
252 }
253