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 39namespace panda::ecmascript::kungfu { 40namespace { 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 */ 46enum 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 58bool 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 73bool IsExistsPkgInfo(AotCompilerPreprocessor &cPreprocessor) 74{ 75 if (cPreprocessor.GetMainPkgArgs()) { 76 return true; 77 } 78 return false; 79} 80} // namespace 81 82int 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 248int main(const int argc, const char **argv) 249{ 250 auto result = panda::ecmascript::kungfu::Main(argc, argv); 251 return result; 252} 253