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