1b1994897Sopenharmony_ci/** 2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License. 5b1994897Sopenharmony_ci * You may obtain a copy of the License at 6b1994897Sopenharmony_ci * 7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8b1994897Sopenharmony_ci * 9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and 13b1994897Sopenharmony_ci * limitations under the License. 14b1994897Sopenharmony_ci */ 15b1994897Sopenharmony_ci 16b1994897Sopenharmony_ci#include "include/runtime.h" 17b1994897Sopenharmony_ci#include "include/thread.h" 18b1994897Sopenharmony_ci#include "include/thread_scopes.h" 19b1994897Sopenharmony_ci#include "runtime/include/locks.h" 20b1994897Sopenharmony_ci#include "runtime/include/method-inl.h" 21b1994897Sopenharmony_ci#include "runtime/include/class.h" 22b1994897Sopenharmony_ci#include "utils/pandargs.h" 23b1994897Sopenharmony_ci#include "compiler/compiler_options.h" 24b1994897Sopenharmony_ci#include "compiler/compiler_logger.h" 25b1994897Sopenharmony_ci#include "compiler_events_gen.h" 26b1994897Sopenharmony_ci#include "mem/mem_stats.h" 27b1994897Sopenharmony_ci#include "libpandabase/os/mutex.h" 28b1994897Sopenharmony_ci#include "libpandabase/os/native_stack.h" 29b1994897Sopenharmony_ci#include "generated/base_options.h" 30b1994897Sopenharmony_ci 31b1994897Sopenharmony_ci#include "ark_version.h" 32b1994897Sopenharmony_ci 33b1994897Sopenharmony_ci#include "verification/jobs/thread_pool.h" 34b1994897Sopenharmony_ci#include "verification/jobs/cache.h" 35b1994897Sopenharmony_ci 36b1994897Sopenharmony_ci#include "utils/span.h" 37b1994897Sopenharmony_ci 38b1994897Sopenharmony_ci#include "utils/logger.h" 39b1994897Sopenharmony_ci 40b1994897Sopenharmony_ci#include <limits> 41b1994897Sopenharmony_ci#include <iostream> 42b1994897Sopenharmony_ci#include <vector> 43b1994897Sopenharmony_ci#include <chrono> 44b1994897Sopenharmony_ci#include <ctime> 45b1994897Sopenharmony_ci#include <csignal> 46b1994897Sopenharmony_ci 47b1994897Sopenharmony_cinamespace panda { 48b1994897Sopenharmony_ciconst panda_file::File *GetPandaFile(const ClassLinker &class_linker, std::string_view file_name) 49b1994897Sopenharmony_ci{ 50b1994897Sopenharmony_ci const panda_file::File *res = nullptr; 51b1994897Sopenharmony_ci class_linker.EnumerateBootPandaFiles([&res, file_name](const panda_file::File &pf) { 52b1994897Sopenharmony_ci if (pf.GetFilename() == file_name) { 53b1994897Sopenharmony_ci res = &pf; 54b1994897Sopenharmony_ci return false; 55b1994897Sopenharmony_ci } 56b1994897Sopenharmony_ci return true; 57b1994897Sopenharmony_ci }); 58b1994897Sopenharmony_ci return res; 59b1994897Sopenharmony_ci} 60b1994897Sopenharmony_ci 61b1994897Sopenharmony_civoid BlockSignals() 62b1994897Sopenharmony_ci{ 63b1994897Sopenharmony_ci#if defined(PANDA_TARGET_UNIX) 64b1994897Sopenharmony_ci sigset_t set; 65b1994897Sopenharmony_ci if (sigemptyset(&set) == -1) { 66b1994897Sopenharmony_ci LOG(ERROR, RUNTIME) << "sigemptyset failed"; 67b1994897Sopenharmony_ci return; 68b1994897Sopenharmony_ci } 69b1994897Sopenharmony_ci int rc = 0; 70b1994897Sopenharmony_ci#ifdef PANDA_TARGET_MOBILE 71b1994897Sopenharmony_ci rc += sigaddset(&set, SIGPIPE); 72b1994897Sopenharmony_ci rc += sigaddset(&set, SIGQUIT); 73b1994897Sopenharmony_ci rc += sigaddset(&set, SIGUSR1); 74b1994897Sopenharmony_ci rc += sigaddset(&set, SIGUSR2); 75b1994897Sopenharmony_ci#endif // PANDA_TARGET_MOBILE 76b1994897Sopenharmony_ci if (rc < 0) { 77b1994897Sopenharmony_ci LOG(ERROR, RUNTIME) << "sigaddset failed"; 78b1994897Sopenharmony_ci return; 79b1994897Sopenharmony_ci } 80b1994897Sopenharmony_ci 81b1994897Sopenharmony_ci if (os::native_stack::g_PandaThreadSigmask(SIG_BLOCK, &set, nullptr) != 0) { 82b1994897Sopenharmony_ci LOG(ERROR, RUNTIME) << "g_PandaThreadSigmask failed"; 83b1994897Sopenharmony_ci } 84b1994897Sopenharmony_ci#endif // PANDA_TARGET_UNIX 85b1994897Sopenharmony_ci} 86b1994897Sopenharmony_ci 87b1994897Sopenharmony_civoid PrintHelp(const panda::PandArgParser &pa_parser) 88b1994897Sopenharmony_ci{ 89b1994897Sopenharmony_ci std::cerr << pa_parser.GetErrorString() << std::endl; 90b1994897Sopenharmony_ci std::cerr << "Usage: " 91b1994897Sopenharmony_ci << "panda" 92b1994897Sopenharmony_ci << " [OPTIONS] [file] [entrypoint] -- [arguments]" << std::endl; 93b1994897Sopenharmony_ci std::cerr << std::endl; 94b1994897Sopenharmony_ci std::cerr << "optional arguments:" << std::endl; 95b1994897Sopenharmony_ci std::cerr << pa_parser.GetHelpString() << std::endl; 96b1994897Sopenharmony_ci} 97b1994897Sopenharmony_ci 98b1994897Sopenharmony_cibool PrepareArguments(panda::PandArgParser *pa_parser, const RuntimeOptions &runtime_options, 99b1994897Sopenharmony_ci const panda::PandArg<std::string> &file, const panda::PandArg<std::string> &entrypoint, 100b1994897Sopenharmony_ci const panda::PandArg<bool> &help, int argc, const char **argv) 101b1994897Sopenharmony_ci{ 102b1994897Sopenharmony_ci auto start_time = 103b1994897Sopenharmony_ci std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()) 104b1994897Sopenharmony_ci .count(); 105b1994897Sopenharmony_ci 106b1994897Sopenharmony_ci if (!pa_parser->Parse(argc, argv)) { 107b1994897Sopenharmony_ci PrintHelp(*pa_parser); 108b1994897Sopenharmony_ci return false; 109b1994897Sopenharmony_ci } 110b1994897Sopenharmony_ci 111b1994897Sopenharmony_ci if (runtime_options.IsVersion()) { 112b1994897Sopenharmony_ci PrintPandaVersion(); 113b1994897Sopenharmony_ci return false; 114b1994897Sopenharmony_ci } 115b1994897Sopenharmony_ci 116b1994897Sopenharmony_ci if (file.GetValue().empty() || entrypoint.GetValue().empty() || help.GetValue()) { 117b1994897Sopenharmony_ci PrintHelp(*pa_parser); 118b1994897Sopenharmony_ci return false; 119b1994897Sopenharmony_ci } 120b1994897Sopenharmony_ci 121b1994897Sopenharmony_ci if (runtime_options.IsStartupTime()) { 122b1994897Sopenharmony_ci std::cout << "\n" 123b1994897Sopenharmony_ci << "Startup start time: " << start_time << std::endl; 124b1994897Sopenharmony_ci } 125b1994897Sopenharmony_ci 126b1994897Sopenharmony_ci auto runtime_options_err = runtime_options.Validate(); 127b1994897Sopenharmony_ci if (runtime_options_err) { 128b1994897Sopenharmony_ci std::cerr << "Error: " << runtime_options_err.value().GetMessage() << std::endl; 129b1994897Sopenharmony_ci return false; 130b1994897Sopenharmony_ci } 131b1994897Sopenharmony_ci 132b1994897Sopenharmony_ci auto compiler_options_err = compiler::options.Validate(); 133b1994897Sopenharmony_ci if (compiler_options_err) { 134b1994897Sopenharmony_ci std::cerr << "Error: " << compiler_options_err.value().GetMessage() << std::endl; 135b1994897Sopenharmony_ci return false; 136b1994897Sopenharmony_ci } 137b1994897Sopenharmony_ci 138b1994897Sopenharmony_ci return true; 139b1994897Sopenharmony_ci} 140b1994897Sopenharmony_ci 141b1994897Sopenharmony_ciint ExecutePandaFile(panda::PandArg<bool> &options, panda::PandArgParser &pa_parser, panda::PandArg<std::string> &file, 142b1994897Sopenharmony_ci panda::PandArg<std::string> &entrypoint, RuntimeOptions &runtime_options) 143b1994897Sopenharmony_ci{ 144b1994897Sopenharmony_ci if (!Runtime::Create(runtime_options)) { 145b1994897Sopenharmony_ci std::cerr << "Error: cannot create runtime" << std::endl; 146b1994897Sopenharmony_ci return -1; 147b1994897Sopenharmony_ci } 148b1994897Sopenharmony_ci 149b1994897Sopenharmony_ci int ret = 0; 150b1994897Sopenharmony_ci 151b1994897Sopenharmony_ci if (options.GetValue()) { 152b1994897Sopenharmony_ci std::cout << pa_parser.GetRegularArgs() << std::endl; 153b1994897Sopenharmony_ci } 154b1994897Sopenharmony_ci 155b1994897Sopenharmony_ci std::string file_name = file.GetValue(); 156b1994897Sopenharmony_ci std::string entry = entrypoint.GetValue(); 157b1994897Sopenharmony_ci 158b1994897Sopenharmony_ci auto &runtime = *Runtime::GetCurrent(); 159b1994897Sopenharmony_ci auto &verif_opts = runtime.GetVerificationOptions(); 160b1994897Sopenharmony_ci ASSERT(!verif_opts.IsOnlyVerify()); 161b1994897Sopenharmony_ci 162b1994897Sopenharmony_ci if (verif_opts.IsEnabled()) { 163b1994897Sopenharmony_ci verifier::ThreadPool::GetCache()->FastAPI().ProcessFiles(runtime.GetClassLinker()->GetBootPandaFiles()); 164b1994897Sopenharmony_ci } 165b1994897Sopenharmony_ci 166b1994897Sopenharmony_ci arg_list_t arguments = pa_parser.GetRemainder(); 167b1994897Sopenharmony_ci auto res = runtime.ExecutePandaFile(file_name, entry, arguments); 168b1994897Sopenharmony_ci if (!res) { 169b1994897Sopenharmony_ci std::cerr << "Cannot execute panda file '" << file_name << "' with entry '" << entry << "'" << std::endl; 170b1994897Sopenharmony_ci ret = -1; 171b1994897Sopenharmony_ci } else { 172b1994897Sopenharmony_ci ret = res.Value(); 173b1994897Sopenharmony_ci } 174b1994897Sopenharmony_ci 175b1994897Sopenharmony_ci if (runtime_options.IsPrintMemoryStatistics()) { 176b1994897Sopenharmony_ci std::cout << runtime.GetMemoryStatistics(); 177b1994897Sopenharmony_ci } 178b1994897Sopenharmony_ci if (runtime_options.IsPrintGcStatistics()) { 179b1994897Sopenharmony_ci std::cout << runtime.GetFinalStatistics(); 180b1994897Sopenharmony_ci } 181b1994897Sopenharmony_ci if (!Runtime::Destroy()) { 182b1994897Sopenharmony_ci std::cerr << "Error: cannot destroy runtime" << std::endl; 183b1994897Sopenharmony_ci return -1; 184b1994897Sopenharmony_ci } 185b1994897Sopenharmony_ci pa_parser.DisableTail(); 186b1994897Sopenharmony_ci return ret; 187b1994897Sopenharmony_ci} 188b1994897Sopenharmony_ci 189b1994897Sopenharmony_ciint Main(int argc, const char **argv) 190b1994897Sopenharmony_ci{ 191b1994897Sopenharmony_ci BlockSignals(); 192b1994897Sopenharmony_ci Span<const char *> sp(argv, argc); 193b1994897Sopenharmony_ci RuntimeOptions runtime_options(sp[0]); 194b1994897Sopenharmony_ci base_options::Options base_options(sp[0]); 195b1994897Sopenharmony_ci panda::PandArgParser pa_parser; 196b1994897Sopenharmony_ci 197b1994897Sopenharmony_ci panda::PandArg<bool> help("help", false, "Print this message and exit"); 198b1994897Sopenharmony_ci panda::PandArg<bool> options("options", false, "Print compiler and runtime options"); 199b1994897Sopenharmony_ci // tail arguments 200b1994897Sopenharmony_ci panda::PandArg<std::string> file("file", "", "path to pandafile"); 201b1994897Sopenharmony_ci panda::PandArg<std::string> entrypoint("entrypoint", "", "full name of entrypoint function or method"); 202b1994897Sopenharmony_ci 203b1994897Sopenharmony_ci runtime_options.AddOptions(&pa_parser); 204b1994897Sopenharmony_ci base_options.AddOptions(&pa_parser); 205b1994897Sopenharmony_ci compiler::options.AddOptions(&pa_parser); 206b1994897Sopenharmony_ci 207b1994897Sopenharmony_ci pa_parser.Add(&help); 208b1994897Sopenharmony_ci pa_parser.Add(&options); 209b1994897Sopenharmony_ci pa_parser.PushBackTail(&file); 210b1994897Sopenharmony_ci pa_parser.PushBackTail(&entrypoint); 211b1994897Sopenharmony_ci pa_parser.EnableTail(); 212b1994897Sopenharmony_ci pa_parser.EnableRemainder(); 213b1994897Sopenharmony_ci 214b1994897Sopenharmony_ci if (!panda::PrepareArguments(&pa_parser, runtime_options, file, entrypoint, help, argc, argv)) { 215b1994897Sopenharmony_ci return 1; 216b1994897Sopenharmony_ci } 217b1994897Sopenharmony_ci 218b1994897Sopenharmony_ci compiler::options.AdjustCpuFeatures(false); 219b1994897Sopenharmony_ci 220b1994897Sopenharmony_ci Logger::Initialize(base_options); 221b1994897Sopenharmony_ci 222b1994897Sopenharmony_ci runtime_options.SetVerificationMode(runtime_options.IsVerificationEnabled() ? VerificationMode::ON_THE_FLY 223b1994897Sopenharmony_ci : VerificationMode::DISABLED); 224b1994897Sopenharmony_ci 225b1994897Sopenharmony_ci panda::compiler::CompilerLogger::SetComponents(panda::compiler::options.GetCompilerLog()); 226b1994897Sopenharmony_ci if (compiler::options.IsCompilerEnableEvents()) { 227b1994897Sopenharmony_ci panda::compiler::EventWriter::Init(panda::compiler::options.GetCompilerEventsPath()); 228b1994897Sopenharmony_ci } 229b1994897Sopenharmony_ci 230b1994897Sopenharmony_ci auto boot_panda_files = runtime_options.GetBootPandaFiles(); 231b1994897Sopenharmony_ci 232b1994897Sopenharmony_ci if (runtime_options.GetPandaFiles().empty()) { 233b1994897Sopenharmony_ci boot_panda_files.push_back(file.GetValue()); 234b1994897Sopenharmony_ci } else { 235b1994897Sopenharmony_ci auto panda_files = runtime_options.GetPandaFiles(); 236b1994897Sopenharmony_ci auto found_iter = std::find_if(panda_files.begin(), panda_files.end(), 237b1994897Sopenharmony_ci [&](auto &file_name) { return file_name == file.GetValue(); }); 238b1994897Sopenharmony_ci if (found_iter == panda_files.end()) { 239b1994897Sopenharmony_ci panda_files.push_back(file.GetValue()); 240b1994897Sopenharmony_ci runtime_options.SetPandaFiles(panda_files); 241b1994897Sopenharmony_ci } 242b1994897Sopenharmony_ci } 243b1994897Sopenharmony_ci 244b1994897Sopenharmony_ci runtime_options.SetBootPandaFiles(boot_panda_files); 245b1994897Sopenharmony_ci 246b1994897Sopenharmony_ci return ExecutePandaFile(options, pa_parser, file, entrypoint, runtime_options); 247b1994897Sopenharmony_ci} 248b1994897Sopenharmony_ci} // namespace panda 249b1994897Sopenharmony_ci 250b1994897Sopenharmony_ciint main(int argc, const char **argv) 251b1994897Sopenharmony_ci{ 252b1994897Sopenharmony_ci return panda::Main(argc, argv); 253b1994897Sopenharmony_ci} 254