• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 "include/runtime.h"
17 #include "include/thread.h"
18 #include "include/thread_scopes.h"
19 #include "runtime/include/locks.h"
20 #include "runtime/include/method-inl.h"
21 #include "runtime/include/class.h"
22 #include "utils/pandargs.h"
23 #include "compiler/compiler_options.h"
24 #include "compiler/compiler_logger.h"
25 #include "compiler_events_gen.h"
26 #include "mem/mem_stats.h"
27 #include "libpandabase/os/mutex.h"
28 #include "libpandabase/os/native_stack.h"
29 #include "generated/base_options.h"
30 
31 #include "ark_version.h"
32 
33 #include "utils/span.h"
34 
35 #include "utils/logger.h"
36 
37 #include <limits>
38 #include <iostream>
39 #include <vector>
40 #include <chrono>
41 #include <ctime>
42 #include <csignal>
43 
44 namespace panda {
GetPandaFile(const ClassLinker & classLinker,std::string_view fileName)45 const panda_file::File *GetPandaFile(const ClassLinker &classLinker, std::string_view fileName)
46 {
47     const panda_file::File *res = nullptr;
48     classLinker.EnumerateBootPandaFiles([&res, fileName](const panda_file::File &pf) {
49         if (pf.GetFilename() == fileName) {
50             res = &pf;
51             return false;
52         }
53         return true;
54     });
55     return res;
56 }
57 
PrintHelp(const panda::PandArgParser & paParser)58 void PrintHelp(const panda::PandArgParser &paParser)
59 {
60     std::cerr << paParser.GetErrorString() << std::endl;
61     std::cerr << "Usage: "
62               << "panda"
63               << " [OPTIONS] [file] [entrypoint] -- [arguments]" << std::endl;
64     std::cerr << std::endl;
65     std::cerr << "optional arguments:" << std::endl;
66     std::cerr << paParser.GetHelpString() << std::endl;
67 }
68 
PrepareArguments(panda::PandArgParser * paParser,const RuntimeOptions & runtimeOptions,const panda::PandArg<std::string> & file,const panda::PandArg<std::string> & entrypoint,const panda::PandArg<bool> & help,int argc,const char ** argv)69 bool PrepareArguments(panda::PandArgParser *paParser, const RuntimeOptions &runtimeOptions,
70                       const panda::PandArg<std::string> &file, const panda::PandArg<std::string> &entrypoint,
71                       const panda::PandArg<bool> &help, int argc, const char **argv)
72 {
73     auto startTime =
74         std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch())
75             .count();
76 
77     if (!paParser->Parse(argc, argv)) {
78         PrintHelp(*paParser);
79         return false;
80     }
81 
82     if (runtimeOptions.IsVersion()) {
83         PrintPandaVersion();
84         return false;
85     }
86 
87     if (file.GetValue().empty() || entrypoint.GetValue().empty() || help.GetValue()) {
88         PrintHelp(*paParser);
89         return false;
90     }
91 
92     if (runtimeOptions.IsStartupTime()) {
93         std::cout << "\n"
94                   << "Startup start time: " << startTime << std::endl;
95     }
96 
97     auto runtimeOptionsErr = runtimeOptions.Validate();
98     if (runtimeOptionsErr) {
99         std::cerr << "Error: " << runtimeOptionsErr.value().GetMessage() << std::endl;
100         return false;
101     }
102 
103     auto compilerOptionsErr = compiler::g_options.Validate();
104     if (compilerOptionsErr) {
105         std::cerr << "Error: " << compilerOptionsErr.value().GetMessage() << std::endl;
106         return false;
107     }
108 
109     return true;
110 }
111 
Main(int argc,const char ** argv)112 int Main(int argc, const char **argv)
113 {
114     Span<const char *> sp(argv, argc);
115     RuntimeOptions runtimeOptions(sp[0]);
116     base_options::Options baseOptions(sp[0]);
117     panda::PandArgParser paParser;
118 
119     panda::PandArg<bool> help("help", false, "Print this message and exit");
120     panda::PandArg<bool> options("options", false, "Print compiler and runtime options");
121     // tail arguments
122     panda::PandArg<std::string> file("file", "", "path to pandafile");
123     panda::PandArg<std::string> entrypoint("entrypoint", "", "full name of entrypoint function or method");
124 
125     runtimeOptions.AddOptions(&paParser);
126     baseOptions.AddOptions(&paParser);
127     compiler::g_options.AddOptions(&paParser);
128 
129     paParser.Add(&help);
130     paParser.Add(&options);
131     paParser.PushBackTail(&file);
132     paParser.PushBackTail(&entrypoint);
133     paParser.EnableTail();
134     paParser.EnableRemainder();
135 
136     if (!panda::PrepareArguments(&paParser, runtimeOptions, file, entrypoint, help, argc, argv)) {
137         return 1;
138     }
139 
140     compiler::g_options.AdjustCpuFeatures(false);
141 
142     Logger::Initialize(baseOptions);
143 
144     runtimeOptions.SetVerificationMode(VerificationModeFromString(
145         static_cast<Options>(runtimeOptions).GetVerificationMode()));  // NOLINT(cppcoreguidelines-slicing)
146     if (runtimeOptions.IsVerificationEnabled()) {
147         if (!runtimeOptions.WasSetVerificationMode()) {
148             runtimeOptions.SetVerificationMode(VerificationMode::AHEAD_OF_TIME);
149         }
150     }
151 
152     arg_list_t arguments = paParser.GetRemainder();
153 
154     panda::compiler::CompilerLogger::SetComponents(panda::compiler::g_options.GetCompilerLog());
155     if (compiler::g_options.IsCompilerEnableEvents()) {
156         panda::compiler::EventWriter::Init(panda::compiler::g_options.GetCompilerEventsPath());
157     }
158 
159     auto bootPandaFiles = runtimeOptions.GetBootPandaFiles();
160 
161     if (runtimeOptions.GetPandaFiles().empty()) {
162         bootPandaFiles.push_back(file.GetValue());
163     } else {
164         auto pandaFiles = runtimeOptions.GetPandaFiles();
165         auto foundIter = std::find_if(pandaFiles.begin(), pandaFiles.end(),
166                                       [&](auto &fileName) { return fileName == file.GetValue(); });
167         if (foundIter == pandaFiles.end()) {
168             pandaFiles.push_back(file.GetValue());
169             runtimeOptions.SetPandaFiles(pandaFiles);
170         }
171     }
172 
173     runtimeOptions.SetBootPandaFiles(bootPandaFiles);
174 
175     if (!Runtime::Create(runtimeOptions)) {
176         std::cerr << "Error: cannot create runtime" << std::endl;
177         return -1;
178     }
179 
180     int ret = 0;
181 
182     if (options.GetValue()) {
183         std::cout << paParser.GetRegularArgs() << std::endl;
184     }
185 
186     std::string fileName = file.GetValue();
187     std::string entry = entrypoint.GetValue();
188 
189     auto &runtime = *Runtime::GetCurrent();
190 
191     auto res = runtime.ExecutePandaFile(fileName, entry, arguments);
192     if (!res) {
193         std::cerr << "Cannot execute panda file '" << fileName << "' with entry '" << entry << "'" << std::endl;
194         ret = -1;
195     } else {
196         ret = res.Value();
197     }
198 
199     if (runtimeOptions.IsPrintMemoryStatistics()) {
200         std::cout << runtime.GetMemoryStatistics();
201     }
202     if (runtimeOptions.IsPrintGcStatistics()) {
203         std::cout << runtime.GetFinalStatistics();
204     }
205     if (!Runtime::Destroy()) {
206         std::cerr << "Error: cannot destroy runtime" << std::endl;
207         return -1;
208     }
209     paParser.DisableTail();
210     return ret;
211 }
212 }  // namespace panda
213 
main(int argc,const char ** argv)214 int main(int argc, const char **argv)
215 {
216     return panda::Main(argc, argv);
217 }
218