• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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