1e509ee18Sopenharmony_ci/* 2e509ee18Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3e509ee18Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e509ee18Sopenharmony_ci * you may not use this file except in compliance with the License. 5e509ee18Sopenharmony_ci * You may obtain a copy of the License at 6e509ee18Sopenharmony_ci * 7e509ee18Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e509ee18Sopenharmony_ci * 9e509ee18Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e509ee18Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e509ee18Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e509ee18Sopenharmony_ci * See the License for the specific language governing permissions and 13e509ee18Sopenharmony_ci * limitations under the License. 14e509ee18Sopenharmony_ci */ 15e509ee18Sopenharmony_ci 16e509ee18Sopenharmony_ci#include <fstream> 17e509ee18Sopenharmony_ci#include <iostream> 18e509ee18Sopenharmony_ci#include <string> 19e509ee18Sopenharmony_ci#include <thread> 20e509ee18Sopenharmony_ci#include <vector> 21e509ee18Sopenharmony_ci 22e509ee18Sopenharmony_ci#include <securec.h> 23e509ee18Sopenharmony_ci#include <uv.h> 24e509ee18Sopenharmony_ci 25e509ee18Sopenharmony_ci#include "ecmascript/base/string_helper.h" 26e509ee18Sopenharmony_ci#include "ecmascript/js_runtime_options.h" 27e509ee18Sopenharmony_ci#include "ecmascript/napi/include/jsnapi.h" 28e509ee18Sopenharmony_ci#include "ecmascript/platform/file.h" 29e509ee18Sopenharmony_ci#include "tooling/utils/utils.h" 30e509ee18Sopenharmony_ci#ifdef PANDA_TARGET_MACOS 31e509ee18Sopenharmony_ci#include <unistd.h> 32e509ee18Sopenharmony_ci#include <sys/syscall.h> 33e509ee18Sopenharmony_ci#endif 34e509ee18Sopenharmony_cistatic panda::ecmascript::Mutex g_mutex; 35e509ee18Sopenharmony_cistatic std::list<std::string> g_files; 36e509ee18Sopenharmony_cistatic std::list<std::string>::iterator g_iter; 37e509ee18Sopenharmony_cistatic panda::ecmascript::JSRuntimeOptions g_runtimeOptions; 38e509ee18Sopenharmony_cistatic uv_async_t *g_exitSignal = nullptr; 39e509ee18Sopenharmony_cistatic int g_threadCount = 0; 40e509ee18Sopenharmony_cistatic int g_runningCount = 0; 41e509ee18Sopenharmony_ci 42e509ee18Sopenharmony_cistatic constexpr int MAX_THREAD = 1024; 43e509ee18Sopenharmony_ci 44e509ee18Sopenharmony_cinamespace OHOS::ArkCompiler::Toolchain { 45e509ee18Sopenharmony_cibool ExecutePandaFile(panda::ecmascript::EcmaVM *vm, 46e509ee18Sopenharmony_ci const panda::ecmascript::JSRuntimeOptions &runtimeOptions, 47e509ee18Sopenharmony_ci const std::string &file, const std::string &entry) 48e509ee18Sopenharmony_ci{ 49e509ee18Sopenharmony_ci panda::LocalScope scope(vm); 50e509ee18Sopenharmony_ci 51e509ee18Sopenharmony_ci panda::ecmascript::EcmaContext *context1 = nullptr; 52e509ee18Sopenharmony_ci if (runtimeOptions.IsEnableContext()) { 53e509ee18Sopenharmony_ci context1 = panda::JSNApi::CreateJSContext(vm); 54e509ee18Sopenharmony_ci panda::JSNApi::SwitchCurrentContext(vm, context1); 55e509ee18Sopenharmony_ci } 56e509ee18Sopenharmony_ci 57e509ee18Sopenharmony_ci if (runtimeOptions.WasAOTOutputFileSet()) { 58e509ee18Sopenharmony_ci panda::JSNApi::LoadAotFile(vm, ""); 59e509ee18Sopenharmony_ci } 60e509ee18Sopenharmony_ci 61e509ee18Sopenharmony_ci bool ret = panda::JSNApi::Execute(vm, file, entry); 62e509ee18Sopenharmony_ci 63e509ee18Sopenharmony_ci if (runtimeOptions.IsEnableContext()) { 64e509ee18Sopenharmony_ci panda::JSNApi::DestroyJSContext(vm, context1); 65e509ee18Sopenharmony_ci } 66e509ee18Sopenharmony_ci 67e509ee18Sopenharmony_ci return ret; 68e509ee18Sopenharmony_ci} 69e509ee18Sopenharmony_ci 70e509ee18Sopenharmony_cistd::pair<std::string, std::string> GetNextPara() 71e509ee18Sopenharmony_ci{ 72e509ee18Sopenharmony_ci std::string fileName = *g_iter; 73e509ee18Sopenharmony_ci std::string fileAbc = fileName.substr(fileName.find_last_of('/') + 1); 74e509ee18Sopenharmony_ci std::string entry = fileAbc.substr(0, fileAbc.size() - 4); 75e509ee18Sopenharmony_ci g_iter++; 76e509ee18Sopenharmony_ci g_runningCount++; 77e509ee18Sopenharmony_ci return {fileName, entry}; 78e509ee18Sopenharmony_ci} 79e509ee18Sopenharmony_ci 80e509ee18Sopenharmony_cistd::string GetMsg(int ret, std::string& msg, std::string& fileName) 81e509ee18Sopenharmony_ci{ 82e509ee18Sopenharmony_ci if (!ret) { 83e509ee18Sopenharmony_ci#ifdef PANDA_TARGET_MACOS 84e509ee18Sopenharmony_ci msg = "[FAILED] [" + std::to_string(syscall(SYS_thread_selfid)) + "] Run " + 85e509ee18Sopenharmony_ci fileName + " failed!"; 86e509ee18Sopenharmony_ci#else 87e509ee18Sopenharmony_ci msg = "[FAILED] [" + std::to_string(gettid()) + "] Run " + fileName + " failed!"; 88e509ee18Sopenharmony_ci#endif 89e509ee18Sopenharmony_ci } else { 90e509ee18Sopenharmony_ci#ifdef PANDA_TARGET_MACOS 91e509ee18Sopenharmony_ci msg = "[PASS] [" + std::to_string(syscall(SYS_thread_selfid)) + "] Run " + 92e509ee18Sopenharmony_ci fileName + " success!"; 93e509ee18Sopenharmony_ci#else 94e509ee18Sopenharmony_ci msg = "[PASS] [" + std::to_string(gettid()) + "] Run " + fileName + " success!"; 95e509ee18Sopenharmony_ci#endif 96e509ee18Sopenharmony_ci } 97e509ee18Sopenharmony_ci return msg; 98e509ee18Sopenharmony_ci} 99e509ee18Sopenharmony_ci 100e509ee18Sopenharmony_cibool StartThread(uv_loop_t *loop) 101e509ee18Sopenharmony_ci{ 102e509ee18Sopenharmony_ci uv_thread_t tid = 0; 103e509ee18Sopenharmony_ci int ret = uv_thread_create(&tid, [] (void* arg) -> void { 104e509ee18Sopenharmony_ci while (true) { 105e509ee18Sopenharmony_ci g_mutex.Lock(); 106e509ee18Sopenharmony_ci if (g_iter == g_files.end()) { 107e509ee18Sopenharmony_ci g_threadCount--; 108e509ee18Sopenharmony_ci if (g_threadCount == 0) { 109e509ee18Sopenharmony_ci uv_async_send(g_exitSignal); 110e509ee18Sopenharmony_ci } 111e509ee18Sopenharmony_ci g_mutex.Unlock(); 112e509ee18Sopenharmony_ci break; 113e509ee18Sopenharmony_ci } 114e509ee18Sopenharmony_ci auto [fileName, entry] = GetNextPara(); 115e509ee18Sopenharmony_ci g_mutex.Unlock(); 116e509ee18Sopenharmony_ci panda::ecmascript::EcmaVM *vm = panda::JSNApi::CreateEcmaVM(g_runtimeOptions); 117e509ee18Sopenharmony_ci if (vm == nullptr) { 118e509ee18Sopenharmony_ci std::cerr << "Cannot create vm." << std::endl; 119e509ee18Sopenharmony_ci return; 120e509ee18Sopenharmony_ci } 121e509ee18Sopenharmony_ci panda::JSNApi::SetBundle(vm, !g_runtimeOptions.GetMergeAbc()); 122e509ee18Sopenharmony_ci bool ret = ExecutePandaFile(vm, g_runtimeOptions, fileName, entry); 123e509ee18Sopenharmony_ci panda::JSNApi::DestroyJSVM(vm); 124e509ee18Sopenharmony_ci auto loop = static_cast<uv_loop_t *>(arg); 125e509ee18Sopenharmony_ci auto work = new uv_work_t; 126e509ee18Sopenharmony_ci std::string msg = GetMsg(ret, msg, fileName); 127e509ee18Sopenharmony_ci work->data = new char[msg.size() + 1]; 128e509ee18Sopenharmony_ci if (strncpy_s(static_cast<char*>(work->data), msg.size() + 1, msg.data(), msg.size()) != EOK) { 129e509ee18Sopenharmony_ci delete[] static_cast<char*>(work->data); 130e509ee18Sopenharmony_ci delete work; 131e509ee18Sopenharmony_ci std::abort(); 132e509ee18Sopenharmony_ci } 133e509ee18Sopenharmony_ci uv_queue_work(loop, work, [] (uv_work_t*) {}, [] (uv_work_t* work, int) { 134e509ee18Sopenharmony_ci std::cerr << static_cast<char*>(work->data) << std::endl; 135e509ee18Sopenharmony_ci delete[] static_cast<char*>(work->data); 136e509ee18Sopenharmony_ci delete work; 137e509ee18Sopenharmony_ci }); 138e509ee18Sopenharmony_ci } 139e509ee18Sopenharmony_ci }, loop); 140e509ee18Sopenharmony_ci return ret != 0; 141e509ee18Sopenharmony_ci} 142e509ee18Sopenharmony_ci 143e509ee18Sopenharmony_ciint Main(const int argc, const char **argv) 144e509ee18Sopenharmony_ci{ 145e509ee18Sopenharmony_ci auto startTime = 146e509ee18Sopenharmony_ci std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()) 147e509ee18Sopenharmony_ci .count(); 148e509ee18Sopenharmony_ci 149e509ee18Sopenharmony_ci std::cerr << "Run begin [" << getpid() << "]" << std::endl; 150e509ee18Sopenharmony_ci if (argc < 3) { // 3: at least have three arguments 151e509ee18Sopenharmony_ci std::cerr << "At least have three arguments." << std::endl; 152e509ee18Sopenharmony_ci return -1; 153e509ee18Sopenharmony_ci } 154e509ee18Sopenharmony_ci 155e509ee18Sopenharmony_ci std::string countStr = argv[1]; 156e509ee18Sopenharmony_ci int32_t count; 157e509ee18Sopenharmony_ci if (!Utils::StrToInt32(countStr, count)) { 158e509ee18Sopenharmony_ci std::cerr << "The argument about the number of threads is incorrect." << std::endl; 159e509ee18Sopenharmony_ci return -1; 160e509ee18Sopenharmony_ci } 161e509ee18Sopenharmony_ci g_threadCount = std::min(count, MAX_THREAD); 162e509ee18Sopenharmony_ci 163e509ee18Sopenharmony_ci std::string filePath = argv[2]; 164e509ee18Sopenharmony_ci std::string realPath; 165e509ee18Sopenharmony_ci if (!panda::ecmascript::RealPath(filePath, realPath, true)) { 166e509ee18Sopenharmony_ci std::cerr << "RealPath return fail"; 167e509ee18Sopenharmony_ci return -1; 168e509ee18Sopenharmony_ci } 169e509ee18Sopenharmony_ci 170e509ee18Sopenharmony_ci g_mutex.Lock(); 171e509ee18Sopenharmony_ci std::string line; 172e509ee18Sopenharmony_ci std::ifstream in(realPath); 173e509ee18Sopenharmony_ci while (std::getline(in, line)) { 174e509ee18Sopenharmony_ci if (line.find_last_of(".abc") == std::string::npos) { // endwith 175e509ee18Sopenharmony_ci std::cerr << "Not endwith .abc" << line << std::endl; 176e509ee18Sopenharmony_ci std::abort(); 177e509ee18Sopenharmony_ci } 178e509ee18Sopenharmony_ci g_files.emplace_back(line); 179e509ee18Sopenharmony_ci } 180e509ee18Sopenharmony_ci g_iter = g_files.begin(); 181e509ee18Sopenharmony_ci g_mutex.Unlock(); 182e509ee18Sopenharmony_ci 183e509ee18Sopenharmony_ci bool retOpt = g_runtimeOptions.ParseCommand(argc - 2, argv + 2); 184e509ee18Sopenharmony_ci if (!retOpt) { 185e509ee18Sopenharmony_ci std::cerr << "ParseCommand failed." << std::endl; 186e509ee18Sopenharmony_ci return -1; 187e509ee18Sopenharmony_ci } 188e509ee18Sopenharmony_ci panda::ecmascript::EcmaVM *vm = panda::JSNApi::CreateEcmaVM(g_runtimeOptions); 189e509ee18Sopenharmony_ci if (vm == nullptr) { 190e509ee18Sopenharmony_ci std::cerr << "Cannot create vm." << std::endl; 191e509ee18Sopenharmony_ci return -1; 192e509ee18Sopenharmony_ci } 193e509ee18Sopenharmony_ci panda::JSNApi::SetBundle(vm, !g_runtimeOptions.GetMergeAbc()); 194e509ee18Sopenharmony_ci 195e509ee18Sopenharmony_ci uv_loop_t* loop = uv_default_loop(); 196e509ee18Sopenharmony_ci g_exitSignal = new uv_async_t; 197e509ee18Sopenharmony_ci g_exitSignal->data = loop; 198e509ee18Sopenharmony_ci uv_async_init(loop, g_exitSignal, []([[maybe_unused]] uv_async_t* handle) { 199e509ee18Sopenharmony_ci g_mutex.Lock(); 200e509ee18Sopenharmony_ci assert (g_threadCount == 0); 201e509ee18Sopenharmony_ci g_mutex.Unlock(); 202e509ee18Sopenharmony_ci auto loop = static_cast<uv_loop_t*>(handle->data); 203e509ee18Sopenharmony_ci uv_stop(loop); 204e509ee18Sopenharmony_ci }); 205e509ee18Sopenharmony_ci 206e509ee18Sopenharmony_ci int threadCountLocal = g_threadCount; 207e509ee18Sopenharmony_ci for (int i = 0; i < threadCountLocal; i++) { 208e509ee18Sopenharmony_ci StartThread(loop); 209e509ee18Sopenharmony_ci } 210e509ee18Sopenharmony_ci 211e509ee18Sopenharmony_ci uv_run(loop, UV_RUN_DEFAULT); 212e509ee18Sopenharmony_ci 213e509ee18Sopenharmony_ci uv_close(reinterpret_cast<uv_handle_t*>(g_exitSignal), [] (uv_handle_t* handle) { 214e509ee18Sopenharmony_ci if (handle != nullptr) { 215e509ee18Sopenharmony_ci delete reinterpret_cast<uv_handle_t*>(handle); 216e509ee18Sopenharmony_ci handle = nullptr; 217e509ee18Sopenharmony_ci } 218e509ee18Sopenharmony_ci }); 219e509ee18Sopenharmony_ci panda::JSNApi::DestroyJSVM(vm); 220e509ee18Sopenharmony_ci 221e509ee18Sopenharmony_ci auto endTime = 222e509ee18Sopenharmony_ci std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()) 223e509ee18Sopenharmony_ci .count(); 224e509ee18Sopenharmony_ci 225e509ee18Sopenharmony_ci g_mutex.Lock(); 226e509ee18Sopenharmony_ci const long long timeUnit = 1000'000'000; 227e509ee18Sopenharmony_ci std::cerr << "Run end, total file count: " << g_runningCount << ", used: " 228e509ee18Sopenharmony_ci << ((endTime - startTime) / timeUnit) << "s." << std::endl; 229e509ee18Sopenharmony_ci g_mutex.Unlock(); 230e509ee18Sopenharmony_ci return 0; 231e509ee18Sopenharmony_ci} 232e509ee18Sopenharmony_ci} // OHOS::ArkCompiler::Toolchain 233e509ee18Sopenharmony_ci 234e509ee18Sopenharmony_ciint main(int argc, const char **argv) 235e509ee18Sopenharmony_ci{ 236e509ee18Sopenharmony_ci return OHOS::ArkCompiler::Toolchain::Main(argc, argv); 237e509ee18Sopenharmony_ci} 238