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 <signal.h> // NOLINTNEXTLINE(modernize-deprecated-headers)
19 #include <vector>
20
21 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
22 #include "ecmascript/base/string_helper.h"
23 #include "ecmascript/compiler/pass_manager.h"
24 #include "ecmascript/compiler/compiler_log.h"
25 #include "ecmascript/ecma_string.h"
26 #include "ecmascript/ecma_vm.h"
27 #include "ecmascript/js_runtime_options.h"
28 #include "ecmascript/jspandafile/js_pandafile_manager.h"
29 #include "ecmascript/log.h"
30 #include "ecmascript/napi/include/jsnapi.h"
31 #include "ecmascript/platform/file.h"
32
33 namespace panda::ecmascript::kungfu {
GetHelper()34 std::string GetHelper()
35 {
36 std::string str;
37 str.append(COMPILER_HELP_HEAD_MSG);
38 str.append(HELP_OPTION_MSG);
39 return str;
40 }
41
AOTInitialize(EcmaVM * vm)42 void AOTInitialize(EcmaVM *vm)
43 {
44 BytecodeStubCSigns::Initialize();
45 CommonStubCSigns::Initialize();
46 RuntimeStubCSigns::Initialize();
47 vm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->Initialize();
48 }
49
CreateAndVerifyJSPandaFile(const JSRuntimeOptions & runtimeOptions,const std::string & fileName,EcmaVM * vm)50 JSPandaFile *CreateAndVerifyJSPandaFile(const JSRuntimeOptions &runtimeOptions, const std::string &fileName, EcmaVM *vm)
51 {
52 JSPandaFileManager *jsPandaFileManager = JSPandaFileManager::GetInstance();
53 std::shared_ptr<JSPandaFile> jsPandaFile = nullptr;
54 if (runtimeOptions.IsTargetCompilerMode()) {
55 std::string hapPath = runtimeOptions.GetHapPath();
56 uint32_t offset = runtimeOptions.GetHapAbcOffset();
57 uint32_t size = runtimeOptions.GetHapAbcSize();
58 if (size == 0) {
59 LOG_ECMA(ERROR) << "buffer is empty in target compiler mode!";
60 return nullptr;
61 }
62 std::string realPath;
63 if (!RealPath(hapPath, realPath, false)) {
64 LOG_ECMA(ERROR) << "realpath for hap path failed!";
65 return nullptr;
66 }
67 MemMap fileMapMem = FileMap(realPath.c_str(), FILE_RDONLY, PAGE_PROT_READ);
68 if (fileMapMem.GetOriginAddr() == nullptr) {
69 LOG_ECMA(ERROR) << "File mmap failed";
70 return nullptr;
71 }
72 uint8_t *buffer = reinterpret_cast<uint8_t *>(fileMapMem.GetOriginAddr()) + offset;
73 jsPandaFile = jsPandaFileManager->OpenJSPandaFileFromBuffer(buffer, size, fileName.c_str());
74 FileUnMap(fileMapMem);
75 fileMapMem.Reset();
76 } else {
77 jsPandaFile = jsPandaFileManager->OpenJSPandaFile(fileName.c_str());
78 }
79 if (jsPandaFile == nullptr) {
80 LOG_ECMA(ERROR) << "open file " << fileName << " error";
81 return nullptr;
82 }
83
84 if (!jsPandaFile->IsNewVersion()) {
85 LOG_COMPILER(ERROR) << "AOT only support panda file with new ISA, while the '" <<
86 fileName << "' file is the old version";
87 return nullptr;
88 }
89
90 jsPandaFileManager->AddJSPandaFileVm(vm, jsPandaFile);
91 return jsPandaFile.get();
92 }
93
Main(const int argc,const char ** argv)94 int Main(const int argc, const char **argv)
95 {
96 auto startTime =
97 std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch())
98 .count();
99 std::string entrypoint = "init::func_main_0";
100 LOG_ECMA(DEBUG) << "Print ark_aot_compiler received args:";
101 for (int i = 0; i < argc; i++) {
102 LOG_ECMA(DEBUG) << argv[i];
103 }
104
105 int newArgc = argc;
106 if (argc < 2) { // 2: at least have two arguments
107 LOG_COMPILER(ERROR) << GetHelper();
108 return -1;
109 }
110
111 std::string files = argv[argc - 1];
112 if (!base::StringHelper::EndsWith(files, ".abc")) {
113 LOG_COMPILER(ERROR) << "The last argument must be abc file" << std::endl;
114 LOG_COMPILER(ERROR) << GetHelper();
115 return 1;
116 }
117
118 newArgc--;
119 JSRuntimeOptions runtimeOptions;
120 bool retOpt = runtimeOptions.ParseCommand(newArgc, argv);
121 if (!retOpt) {
122 LOG_COMPILER(ERROR) << GetHelper();
123 return 1;
124 }
125
126 if (runtimeOptions.IsStartupTime()) {
127 LOG_COMPILER(DEBUG) << "Startup start time: " << startTime;
128 }
129
130 bool ret = true;
131 // ark_aot_compiler running need disable asm interpreter to disable the loading of AOT files.
132 runtimeOptions.SetEnableAsmInterpreter(false);
133 runtimeOptions.DisableReportModuleResolvingFailure();
134 runtimeOptions.SetOptionsForTargetCompilation();
135 EcmaVM *vm = JSNApi::CreateEcmaVM(runtimeOptions);
136 if (vm == nullptr) {
137 LOG_COMPILER(ERROR) << "Cannot Create vm";
138 return -1;
139 }
140
141 {
142 LocalScope scope(vm);
143 std::string delimiter = GetFileDelimiter();
144 arg_list_t pandaFileNames = base::StringHelper::SplitString(files, delimiter);
145
146 std::string triple = runtimeOptions.GetTargetTriple();
147 if (runtimeOptions.GetAOTOutputFile().empty()) {
148 runtimeOptions.SetAOTOutputFile("aot_file");
149 }
150 std::string outputFileName = runtimeOptions.GetAOTOutputFile();
151 size_t optLevel = runtimeOptions.GetOptLevel();
152 size_t relocMode = runtimeOptions.GetRelocMode();
153 std::string logOption = runtimeOptions.GetCompilerLogOption();
154 std::string logMethodsList = runtimeOptions.GetMethodsListForLog();
155 bool compilerLogTime = runtimeOptions.IsEnableCompilerLogTime();
156 size_t maxAotMethodSize = runtimeOptions.GetMaxAotMethodSize();
157 size_t maxMethodsInModule = runtimeOptions.GetCompilerModuleMethods();
158 bool isEnableTypeLowering = runtimeOptions.IsEnableTypeLowering();
159 bool isEnableEarlyElimination = runtimeOptions.IsEnableEarlyElimination();
160 bool isEnableLaterElimination = runtimeOptions.IsEnableLaterElimination();
161 bool isEnableValueNumbering = runtimeOptions.IsEnableValueNumbering();
162 bool isEnableOptInlining = runtimeOptions.IsEnableOptInlining();
163 bool isEnableTypeInfer = isEnableTypeLowering ||
164 vm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->AssertTypes();
165 bool isEnableOptPGOType = runtimeOptions.IsEnableOptPGOType();
166 bool isEnableOptTrackField = runtimeOptions.IsEnableOptTrackField();
167 bool isEnableOptLoopPeeling = runtimeOptions.IsEnableOptLoopPeeling();
168
169 PassOptions passOptions(isEnableTypeLowering, isEnableEarlyElimination, isEnableLaterElimination,
170 isEnableValueNumbering, isEnableTypeInfer, isEnableOptInlining,
171 isEnableOptPGOType, isEnableOptTrackField, isEnableOptLoopPeeling);
172
173 uint32_t hotnessThreshold = runtimeOptions.GetPGOHotnessThreshold();
174 AOTInitialize(vm);
175
176 CompilerLog log(logOption);
177 log.SetEnableCompilerLogTime(compilerLogTime);
178 AotMethodLogList logList(logMethodsList);
179 AOTFileGenerator generator(&log, &logList, vm, triple);
180 std::string profilerIn(runtimeOptions.GetPGOProfilerPath());
181
182 if (runtimeOptions.WasSetEntryPoint()) {
183 entrypoint = runtimeOptions.GetEntryPoint();
184 }
185 PassManager passManager(vm, entrypoint, triple, optLevel, relocMode, &log, &logList, maxAotMethodSize,
186 maxMethodsInModule, profilerIn, hotnessThreshold, &passOptions);
187 for (const auto &fileName : pandaFileNames) {
188 auto extendedFilePath = panda::os::file::File::GetExtendedFilePath(fileName);
189 LOG_COMPILER(INFO) << "AOT compile: " << extendedFilePath;
190 JSPandaFile *jsPandaFile = CreateAndVerifyJSPandaFile(runtimeOptions, extendedFilePath, vm);
191 if (passManager.Compile(jsPandaFile, extendedFilePath, generator) == false) {
192 ret = false;
193 continue;
194 }
195 }
196 generator.SaveAOTFile(outputFileName + AOTFileManager::FILE_EXTENSION_AN);
197 generator.SaveSnapshotFile();
198 log.Print();
199 }
200
201 LOG_COMPILER(INFO) << (ret ? "ts aot compile success" : "ts aot compile failed");
202 JSNApi::DestroyJSVM(vm);
203 return ret ? 0 : -1;
204 }
205 } // namespace panda::ecmascript::kungfu
206
main(const int argc,const char ** argv)207 int main(const int argc, const char **argv)
208 {
209 auto result = panda::ecmascript::kungfu::Main(argc, argv);
210 return result;
211 }
212