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