• 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 <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