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