add ark_multi

Signed-off-by: wengchangcheng <wengchangcheng@huawei.com>
Change-Id: Ic59c4ba75f675081f072fa1af0d97b2e68298ce0
This commit is contained in:
wengchangcheng 2024-02-03 20:37:05 +08:00
parent ccbd92cbfb
commit 38697976a5
4 changed files with 255 additions and 0 deletions

View File

@ -201,6 +201,7 @@ group("ark_toolchain_packages") {
"./tooling:libark_ecma_debugger",
"./tooling/client:libark_client",
"./tooling/client/ark_cli:arkdb",
"./tooling/client/ark_multi:ark_multi",
]
}

View File

@ -89,6 +89,7 @@ group("toolchain") {
deps += [
"$toolchain_root/tooling/client:libark_client",
"$toolchain_root/tooling/client/ark_cli:arkdb",
"$toolchain_root/tooling/client/ark_multi:ark_multi",
]
}
}

View File

@ -0,0 +1,48 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//arkcompiler/toolchain/toolchain.gni")
ohos_executable("ark_multi") {
sources = [ "main.cpp" ]
include_dirs = [
"./",
"../",
"../../base",
"../../../inspector",
"../../../tooling",
"../../../websocket",
"//third_party/cJSON",
"//third_party/libuv/include",
]
deps = [
"$ark_third_party_root/libuv:uv",
sdk_libc_secshared_dep,
]
external_deps = [ "ets_runtime:libark_jsruntime" ]
# hiviewdfx libraries
external_deps += hiviewdfx_ext_deps
deps += hiviewdfx_deps
configs = [ "../../..:ark_toolchain_common_config" ]
install_enable = false
part_name = "toolchain"
subsystem_name = "arkcompiler"
}

View File

@ -0,0 +1,205 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <fstream>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include <securec.h>
#include <uv.h>
#include "ecmascript/base/string_helper.h"
#include "ecmascript/js_runtime_options.h"
#include "ecmascript/napi/include/jsnapi.h"
#include "ecmascript/platform/file.h"
static panda::ecmascript::Mutex g_mutex;
static std::list<std::string> g_files;
static std::list<std::string>::iterator g_iter;
static panda::ecmascript::JSRuntimeOptions g_runtimeOptions;
static uv_async_t *g_exitSignal = nullptr;
static int g_threadCount = 0;
static int g_runningCount = 0;
static constexpr int MAX_THREAD = 1024;
namespace OHOS::ArkCompiler::Toolchain {
bool ExecutePandaFile(panda::ecmascript::EcmaVM *vm,
const panda::ecmascript::JSRuntimeOptions &runtimeOptions,
const std::string &file, const std::string &entry)
{
panda::LocalScope scope(vm);
panda::ecmascript::EcmaContext *context1 = nullptr;
if (runtimeOptions.IsEnableContext()) {
context1 = panda::JSNApi::CreateJSContext(vm);
panda::JSNApi::SwitchCurrentContext(vm, context1);
}
if (runtimeOptions.WasAOTOutputFileSet()) {
panda::JSNApi::LoadAotFile(vm, "");
}
bool ret = panda::JSNApi::Execute(vm, file, entry);
if (runtimeOptions.IsEnableContext()) {
panda::JSNApi::DestroyJSContext(vm, context1);
}
return ret;
}
bool StartThread(uv_loop_t *loop)
{
uv_thread_t tid = 0;
int ret = uv_thread_create(&tid, [] (void* arg) -> void {
while (true) {
g_mutex.Lock();
if (g_iter == g_files.end()) {
g_threadCount--;
if (g_threadCount == 0) {
uv_async_send(g_exitSignal);
}
g_mutex.Unlock();
break;
}
std::string fileName = *g_iter;
std::string fileAbc = fileName.substr(fileName.find_last_of('/') + 1);
std::string entry = fileAbc.substr(0, fileAbc.size() - 4);
g_iter++;
g_runningCount++;
g_mutex.Unlock();
panda::ecmascript::EcmaVM *vm = panda::JSNApi::CreateEcmaVM(g_runtimeOptions);
if (vm == nullptr) {
std::cerr << "Cannot create vm." << std::endl;
return;
}
panda::JSNApi::SetBundle(vm, !g_runtimeOptions.GetMergeAbc());
bool ret = ExecutePandaFile(vm, g_runtimeOptions, fileName, entry);
panda::JSNApi::DestroyJSVM(vm);
auto loop = static_cast<uv_loop_t *>(arg);
auto work = new uv_work_t;
std::string msg;
if (!ret) {
msg = "[FAILED] [" + std::to_string(gettid()) + "] Run " + fileName + " failed!";
} else {
msg = "[PASS] [" + std::to_string(gettid()) + "] Run " + fileName + " success!";
continue;
}
work->data = new char[msg.size() + 1];
if (strncpy_s(static_cast<char*>(work->data), msg.size() + 1, msg.data(), msg.size()) != EOK) {
std::abort();
}
uv_queue_work(loop, work, [] (uv_work_t*) {}, [] (uv_work_t* work, int) {
std::cerr << static_cast<char*>(work->data) << std::endl;
delete static_cast<char*>(work->data);
delete work;
});
}
}, loop);
return ret != 0;
}
int Main(const int argc, const char **argv)
{
auto startTime =
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch())
.count();
std::cerr << "Run begin [" << getpid() << "]" << std::endl;
if (argc < 3) { // 3: at least have three arguments
std::cerr << "At least have three arguments." << std::endl;
return -1;
}
std::string countStr = argv[1];
g_threadCount = std::min(std::stoi(countStr), MAX_THREAD);
std::string filePath = argv[2];
std::string realPath;
if (!panda::ecmascript::RealPath(filePath, realPath, true)) {
std::cerr << "RealPath return fail";
return -1;
}
g_mutex.Lock();
std::string line;
std::ifstream in(realPath);
while (std::getline(in, line)) {
if (line.find_last_of(".abc") == std::string::npos) { // endwith
std::cerr << "Not endwith .abc" << line << std::endl;
std::abort();
}
g_files.emplace_back(line);
}
g_iter = g_files.begin();
g_mutex.Unlock();
bool retOpt = g_runtimeOptions.ParseCommand(argc - 2, argv + 2);
if (!retOpt) {
std::cerr << "ParseCommand failed." << std::endl;
return -1;
}
panda::ecmascript::EcmaVM *vm = panda::JSNApi::CreateEcmaVM(g_runtimeOptions);
if (vm == nullptr) {
std::cerr << "Cannot create vm." << std::endl;
return -1;
}
panda::JSNApi::SetBundle(vm, !g_runtimeOptions.GetMergeAbc());
uv_loop_t* loop = uv_default_loop();
g_exitSignal = new uv_async_t;
g_exitSignal->data = loop;
uv_async_init(loop, g_exitSignal, []([[maybe_unused]] uv_async_t* handle) {
g_mutex.Lock();
assert (g_threadCount == 0);
g_mutex.Unlock();
auto loop = static_cast<uv_loop_t*>(handle->data);
uv_stop(loop);
});
for (int i = 0; i < g_threadCount; i++) {
StartThread(loop);
}
uv_run(loop, UV_RUN_DEFAULT);
uv_close(reinterpret_cast<uv_handle_t*>(g_exitSignal), [] (uv_handle_t* handle) {
if (handle != nullptr) {
delete reinterpret_cast<uv_handle_t*>(handle);
handle = nullptr;
}
});
panda::JSNApi::DestroyJSVM(vm);
auto endTime =
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch())
.count();
g_mutex.Lock();
std::cerr << "Run end, total file count: " << g_runningCount << ", used: " << ((endTime - startTime) / 1000'000'000) << "s." << std::endl;
g_mutex.Unlock();
return 0;
}
} // OHOS::ArkCompiler::Toolchain
int main(int argc, const char **argv)
{
return OHOS::ArkCompiler::Toolchain::Main(argc, argv);
}