mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-27 04:00:37 +00:00
952dd2e92e
Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IAUM1T Signed-off-by: xiongluo <xiongluo@huawei.com> Change-Id: I7b893c0042489d9330058942b8c05bb7c45f3df5
1026 lines
35 KiB
C++
1026 lines
35 KiB
C++
/*
|
|
* Copyright (c) 2021-2024 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 <semaphore.h>
|
|
#include "ecmascript/napi/include/dfx_jsnapi.h"
|
|
|
|
#include "ecmascript/base/block_hook_scope.h"
|
|
#include "ecmascript/builtins/builtins_ark_tools.h"
|
|
#include "ecmascript/checkpoint/thread_state_transition.h"
|
|
#include "ecmascript/debugger/debugger_api.h"
|
|
#include "ecmascript/debugger/js_debugger_manager.h"
|
|
#include "ecmascript/dfx/stackinfo/js_stackinfo.h"
|
|
#include "ecmascript/dfx/tracing/tracing.h"
|
|
#include "ecmascript/mem/heap-inl.h"
|
|
#include "ecmascript/jit/jit.h"
|
|
#include "ecmascript/dfx/vm_thread_control.h"
|
|
|
|
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
|
#include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
|
|
#include "ecmascript/dfx/cpu_profiler/samples_record.h"
|
|
#endif
|
|
#if defined(ENABLE_DUMP_IN_FAULTLOG)
|
|
#include "faultloggerd_client.h"
|
|
#include "uv.h"
|
|
#endif
|
|
|
|
namespace panda {
|
|
using ecmascript::CString;
|
|
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
|
using BuiltinsArkTools = ecmascript::builtins::BuiltinsArkTools;
|
|
using ecmascript::CpuProfiler;
|
|
#endif
|
|
using ecmascript::EcmaString;
|
|
using ecmascript::JSTaggedValue;
|
|
using ecmascript::GCStats;
|
|
template<typename T>
|
|
using JSHandle = ecmascript::JSHandle<T>;
|
|
using ecmascript::FileStream;
|
|
using ecmascript::FileDescriptorStream;
|
|
using ecmascript::CMap;
|
|
using ecmascript::Tracing;
|
|
using ecmascript::DumpSnapShotOption;
|
|
sem_t g_heapdumpCnt;
|
|
|
|
void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const std::string &path,
|
|
[[maybe_unused]] const DumpSnapShotOption &dumpOption)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
FileStream stream(path);
|
|
DumpHeapSnapshot(vm, &stream, dumpOption);
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
|
|
#endif
|
|
}
|
|
|
|
// IDE interface.
|
|
void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream *stream,
|
|
[[maybe_unused]] const DumpSnapShotOption &dumpOption,
|
|
[[maybe_unused]] Progress *progress)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
|
|
const_cast<EcmaVM *>(vm));
|
|
heapProfile->DumpHeapSnapshot(stream, dumpOption, progress);
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
|
|
#endif
|
|
}
|
|
|
|
[[maybe_unused]] static uint8_t killCount = 0;
|
|
|
|
void DFXJSNApi::DumpCpuProfile([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
#if defined(ENABLE_DUMP_IN_FAULTLOG)
|
|
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
|
// for CpuProfiler kill contral
|
|
if (DFXJSNApi::StopCpuProfilerForColdStart(vm)) {
|
|
return;
|
|
}
|
|
|
|
(void)killCount;
|
|
if (DFXJSNApi::CpuProfilerSamplingAnyTime(vm)) {
|
|
killCount++;
|
|
return;
|
|
}
|
|
#endif // ECMASCRIPT_SUPPORT_CPUPROFILER
|
|
#endif // ENABLE_DUMP_IN_FAULTLOG
|
|
#endif // ECMASCRIPT_SUPPORT_SNAPSHOT
|
|
}
|
|
|
|
// kill -39.
|
|
void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm,
|
|
[[maybe_unused]] const DumpSnapShotOption &dumpOption)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
#if defined(ENABLE_DUMP_IN_FAULTLOG)
|
|
sem_wait(&g_heapdumpCnt);
|
|
auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
|
|
options.SwitchStartGlobalLeakCheck();
|
|
if (options.EnableGlobalLeakCheck() && options.IsStartGlobalLeakCheck()) {
|
|
int32_t stackTraceFd = RequestFileDescriptor(static_cast<int32_t>(FaultLoggerType::JS_STACKTRACE));
|
|
if (stackTraceFd < 0) {
|
|
options.SwitchStartGlobalLeakCheck();
|
|
} else {
|
|
vm->GetJSThread()->SetStackTraceFd(stackTraceFd);
|
|
}
|
|
}
|
|
|
|
// Write in faultlog for heap leak.
|
|
int32_t fd;
|
|
if (dumpOption.isDumpOOM && dumpOption.dumpFormat == DumpFormat::BINARY) {
|
|
fd = RequestFileDescriptor(static_cast<int32_t>(FaultLoggerType::JS_RAW_SNAPSHOT));
|
|
} else {
|
|
fd = RequestFileDescriptor(static_cast<int32_t>(FaultLoggerType::JS_HEAP_SNAPSHOT));
|
|
}
|
|
if (fd < 0) {
|
|
LOG_ECMA(ERROR) << "Write FD failed, fd" << fd;
|
|
return;
|
|
}
|
|
FileDescriptorStream stream(fd);
|
|
ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
|
|
const_cast<EcmaVM *>(vm));
|
|
heapProfile->DumpHeapSnapshot(&stream, dumpOption);
|
|
|
|
sem_post(&g_heapdumpCnt);
|
|
#endif // ENABLE_DUMP_IN_FAULTLOG
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
|
|
#endif // ECMASCRIPT_SUPPORT_SNAPSHOT
|
|
}
|
|
|
|
// tid = 0: dump all vm; tid != 0: dump tid vm, hidumper.
|
|
void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm,
|
|
[[maybe_unused]] const DumpSnapShotOption &dumpOption, [[maybe_unused]] uint32_t tid)
|
|
{
|
|
const int THREAD_COUNT = 1;
|
|
if (vm->IsWorkerThread()) {
|
|
LOG_ECMA(ERROR) << "this is a workthread!";
|
|
return;
|
|
}
|
|
sem_init(&g_heapdumpCnt, 0, THREAD_COUNT);
|
|
uint32_t curTid = vm->GetTid();
|
|
LOG_ECMA(INFO) << "DumpHeapSnapshot tid " << tid << " curTid " << curTid;
|
|
DumpHeapSnapshotWithVm(vm, dumpOption, tid);
|
|
}
|
|
|
|
void DFXJSNApi::DumpHeapSnapshotWithVm([[maybe_unused]] const EcmaVM *vm,
|
|
[[maybe_unused]] const DumpSnapShotOption &dumpOption,
|
|
[[maybe_unused]] uint32_t tid)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
#if defined(ENABLE_DUMP_IN_FAULTLOG)
|
|
uv_loop_t *loop = reinterpret_cast<uv_loop_t *>(vm->GetLoop());
|
|
if (loop == nullptr || uv_loop_alive(loop) == 0) {
|
|
LOG_ECMA(ERROR) << "loop nullptr or uv_loop_alive dead";
|
|
return;
|
|
}
|
|
struct DumpForSnapShotStruct *dumpStruct = new DumpForSnapShotStruct();
|
|
dumpStruct->vm = vm;
|
|
dumpStruct->dumpOption = dumpOption;
|
|
uv_work_t *work = new(std::nothrow) uv_work_t;
|
|
if (work == nullptr) {
|
|
LOG_ECMA(ERROR) << "work nullptr";
|
|
delete dumpStruct;
|
|
return;
|
|
}
|
|
work->data = static_cast<void *>(dumpStruct);
|
|
|
|
uint32_t curTid = vm->GetTid();
|
|
int ret = 0;
|
|
if (tid == 0 || tid == curTid) {
|
|
ret = uv_queue_work(loop, work, [](uv_work_t *) {}, [](uv_work_t *work, int32_t) {
|
|
struct DumpForSnapShotStruct *dump = static_cast<struct DumpForSnapShotStruct *>(work->data);
|
|
DFXJSNApi::GetHeapPrepare(dump->vm);
|
|
DumpSnapShotOption dumpOption = dump->dumpOption;
|
|
DumpHeapSnapshot(dump->vm, dumpOption);
|
|
delete dump;
|
|
delete work;
|
|
});
|
|
} else {
|
|
delete dumpStruct;
|
|
delete work;
|
|
}
|
|
|
|
// dump worker vm
|
|
const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
|
|
uint32_t curTid = workerVm->GetTid();
|
|
LOG_ECMA(INFO) << "DumpHeapSnapshot workthread curTid " << curTid;
|
|
DumpHeapSnapshotWithVm(workerVm, dumpOption, tid);
|
|
return;
|
|
});
|
|
|
|
if (ret != 0) {
|
|
LOG_ECMA(ERROR) << "uv_queue_work fail ret " << ret;
|
|
delete dumpStruct;
|
|
delete work;
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
void DFXJSNApi::GenerateHeapSnapshotByBinFile([[maybe_unused]] const EcmaVM *vm,
|
|
[[maybe_unused]] std::string &inputFilePath,
|
|
[[maybe_unused]] std::string &outputPath)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
auto *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(const_cast<EcmaVM *>(vm));
|
|
heapProfile->GenerateHeapSnapshot(inputFilePath, outputPath);
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support GenerateHeapSnapshotByBinFile";
|
|
#endif // ECMASCRIPT_SUPPORT_SNAPSHOT
|
|
}
|
|
|
|
// tid = 0: TriggerGC all vm; tid != 0: TriggerGC tid vm
|
|
void DFXJSNApi::TriggerGC([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] uint32_t tid)
|
|
{
|
|
if (vm->IsWorkerThread()) {
|
|
LOG_ECMA(ERROR) << "this is a workthread!";
|
|
return;
|
|
}
|
|
// triggerGC host vm
|
|
uint32_t curTid = vm->GetTid();
|
|
LOG_ECMA(INFO) << "TriggerGC tid " << tid << " curTid " << curTid;
|
|
if (tid == 0 || tid == curTid) {
|
|
TriggerGCWithVm(vm);
|
|
}
|
|
// triggerGC worker vm
|
|
const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
|
|
curTid = workerVm->GetTid();
|
|
LOG_ECMA(INFO) << "TriggerGC tid " << tid << " curTid " << curTid;
|
|
if (tid == 0 || tid == curTid) {
|
|
TriggerGCWithVm(workerVm);
|
|
return;
|
|
}
|
|
});
|
|
// triggerSharedFullGC
|
|
TriggerSharedGCWithVm(vm);
|
|
}
|
|
|
|
void DFXJSNApi::TriggerSharedGCWithVm([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
#if defined(ENABLE_DUMP_IN_FAULTLOG)
|
|
uv_loop_t *loop = reinterpret_cast<uv_loop_t *>(vm->GetLoop());
|
|
if (loop == nullptr) {
|
|
LOG_ECMA(ERROR) << "loop nullptr";
|
|
return;
|
|
}
|
|
if (uv_loop_alive(loop) == 0) {
|
|
LOG_ECMA(ERROR) << "uv_loop_alive dead";
|
|
return;
|
|
}
|
|
uv_work_t *work = new(std::nothrow) uv_work_t;
|
|
if (work == nullptr) {
|
|
LOG_ECMA(FATAL) << "DFXJSNApi::TriggerGCWithVm:work is nullptr";
|
|
return;
|
|
}
|
|
work->data = static_cast<void *>(const_cast<EcmaVM *>(vm));
|
|
int ret = uv_queue_work(loop, work, [](uv_work_t *) {}, [](uv_work_t *work, int32_t) {
|
|
EcmaVM *vm = static_cast<EcmaVM *>(work->data);
|
|
ecmascript::SharedHeap* sHeap = ecmascript::SharedHeap::GetInstance();
|
|
JSThread *thread = vm->GetJSThread();
|
|
ecmascript::ThreadManagedScope managedScope(thread);
|
|
sHeap->CollectGarbage<ecmascript::TriggerGCType::SHARED_FULL_GC,
|
|
ecmascript::GCReason::TRIGGER_BY_MEM_TOOLS>(thread);
|
|
delete work;
|
|
});
|
|
if (ret != 0) {
|
|
LOG_ECMA(ERROR) << "uv_queue_work fail ret " << ret;
|
|
delete work;
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
void DFXJSNApi::TriggerGCWithVm([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
#if defined(ENABLE_DUMP_IN_FAULTLOG)
|
|
uv_loop_t *loop = reinterpret_cast<uv_loop_t *>(vm->GetLoop());
|
|
if (loop == nullptr) {
|
|
LOG_ECMA(ERROR) << "loop nullptr";
|
|
return;
|
|
}
|
|
if (uv_loop_alive(loop) == 0) {
|
|
LOG_ECMA(ERROR) << "uv_loop_alive dead";
|
|
return;
|
|
}
|
|
uv_work_t *work = new(std::nothrow) uv_work_t;
|
|
if (work == nullptr) {
|
|
LOG_ECMA(FATAL) << "DFXJSNApi::TriggerGCWithVm:work is nullptr";
|
|
return;
|
|
}
|
|
work->data = static_cast<void *>(const_cast<EcmaVM *>(vm));
|
|
int ret = uv_queue_work(loop, work, [](uv_work_t *) {}, [](uv_work_t *work, int32_t) {
|
|
EcmaVM *vm = static_cast<EcmaVM *>(work->data);
|
|
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
|
|
vm->CollectGarbage(ecmascript::TriggerGCType::FULL_GC, ecmascript::GCReason::TRIGGER_BY_MEM_TOOLS);
|
|
delete work;
|
|
});
|
|
if (ret != 0) {
|
|
LOG_ECMA(ERROR) << "uv_queue_work fail ret " << ret;
|
|
delete work;
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
void DFXJSNApi::DestroyHeapProfiler([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
|
|
ecmascript::HeapProfilerInterface::Destroy(const_cast<EcmaVM *>(vm));
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
|
|
#endif
|
|
}
|
|
|
|
bool DFXJSNApi::BuildNativeAndJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr)
|
|
{
|
|
stackTraceStr = ecmascript::JsStackInfo::BuildJsStackTrace(vm->GetAssociatedJSThread(), true);
|
|
if (stackTraceStr.empty()) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool DFXJSNApi::BuildJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr)
|
|
{
|
|
stackTraceStr = ecmascript::JsStackInfo::BuildJsStackTrace(vm->GetAssociatedJSThread(), false);
|
|
if (stackTraceStr.empty()) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool DFXJSNApi::StartHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] double timeInterval,
|
|
[[maybe_unused]] bool isVmMode, [[maybe_unused]] Stream *stream,
|
|
[[maybe_unused]] bool traceAllocation, [[maybe_unused]] bool newThread)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
ecmascript::base::BlockHookScope blockScope;
|
|
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
|
|
ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
|
|
const_cast<EcmaVM *>(vm));
|
|
return heapProfile->StartHeapTracking(timeInterval, isVmMode, stream, traceAllocation, newThread);
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool DFXJSNApi::UpdateHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream *stream)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
ecmascript::base::BlockHookScope blockScope;
|
|
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
|
|
ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
|
|
const_cast<EcmaVM *>(vm));
|
|
return heapProfile->UpdateHeapTracking(stream);
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool DFXJSNApi::StopHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const std::string &filePath,
|
|
[[maybe_unused]] bool newThread)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
FileStream stream(filePath);
|
|
return StopHeapTracking(vm, &stream, nullptr, newThread);
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool DFXJSNApi::StopHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream* stream,
|
|
[[maybe_unused]] Progress *progress, [[maybe_unused]] bool newThread)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
ecmascript::base::BlockHookScope blockScope;
|
|
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
|
|
bool result = false;
|
|
ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
|
|
const_cast<EcmaVM *>(vm));
|
|
result = heapProfile->StopHeapTracking(stream, progress, newThread);
|
|
ecmascript::HeapProfilerInterface::Destroy(const_cast<EcmaVM *>(vm));
|
|
return result;
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
void DFXJSNApi::PrintStatisticResult(const EcmaVM *vm)
|
|
{
|
|
ecmascript::GCStats gcstats(vm->GetHeap());
|
|
gcstats.PrintStatisticResult();
|
|
}
|
|
|
|
void DFXJSNApi::StartRuntimeStat(EcmaVM *vm)
|
|
{
|
|
vm->GetJSThread()->GetCurrentEcmaContext()->SetRuntimeStatEnable(true);
|
|
}
|
|
|
|
void DFXJSNApi::StopRuntimeStat(EcmaVM *vm)
|
|
{
|
|
vm->GetJSThread()->GetCurrentEcmaContext()->SetRuntimeStatEnable(false);
|
|
}
|
|
|
|
size_t DFXJSNApi::GetArrayBufferSize(const EcmaVM *vm)
|
|
{
|
|
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
|
|
return vm->GetHeap()->GetArrayBufferSize();
|
|
}
|
|
|
|
size_t DFXJSNApi::GetHeapTotalSize(const EcmaVM *vm)
|
|
{
|
|
return vm->GetHeap()->GetCommittedSize();
|
|
}
|
|
|
|
size_t DFXJSNApi::GetHeapUsedSize(const EcmaVM *vm)
|
|
{
|
|
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
|
|
return vm->GetHeap()->GetLiveObjectSize();
|
|
}
|
|
|
|
size_t DFXJSNApi::GetHeapObjectSize(const EcmaVM *vm)
|
|
{
|
|
return vm->GetHeap()->GetHeapObjectSize();
|
|
}
|
|
|
|
size_t DFXJSNApi::GetHeapLimitSize(const EcmaVM *vm)
|
|
{
|
|
return vm->GetHeap()->GetHeapLimitSize();
|
|
}
|
|
|
|
size_t DFXJSNApi::GetProcessHeapLimitSize()
|
|
{
|
|
return ecmascript::MemMapAllocator::GetInstance()->GetCapacity();
|
|
}
|
|
|
|
size_t DFXJSNApi::GetGCCount(const EcmaVM *vm)
|
|
{
|
|
if (vm->IsWorkerThread()) {
|
|
return vm->GetEcmaGCStats()->GetGCCount();
|
|
}
|
|
return vm->GetEcmaGCStats()->GetGCCount() +
|
|
ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetGCCount();
|
|
}
|
|
|
|
size_t DFXJSNApi::GetGCDuration(const EcmaVM *vm)
|
|
{
|
|
if (vm->IsWorkerThread()) {
|
|
return vm->GetEcmaGCStats()->GetGCDuration();
|
|
}
|
|
return vm->GetEcmaGCStats()->GetGCDuration() +
|
|
ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetGCDuration();
|
|
}
|
|
|
|
size_t DFXJSNApi::GetAccumulatedAllocateSize(const EcmaVM *vm)
|
|
{
|
|
if (vm->IsWorkerThread()) {
|
|
return vm->GetEcmaGCStats()->GetAccumulatedAllocateSize();
|
|
}
|
|
return vm->GetEcmaGCStats()->GetAccumulatedAllocateSize() +
|
|
ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetAccumulatedAllocateSize();
|
|
}
|
|
|
|
size_t DFXJSNApi::GetAccumulatedFreeSize(const EcmaVM *vm)
|
|
{
|
|
if (vm->IsWorkerThread()) {
|
|
return vm->GetEcmaGCStats()->GetAccumulatedFreeSize();
|
|
}
|
|
return vm->GetEcmaGCStats()->GetAccumulatedFreeSize() +
|
|
ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetAccumulatedFreeSize();
|
|
}
|
|
|
|
size_t DFXJSNApi::GetFullGCLongTimeCount(const EcmaVM *vm)
|
|
{
|
|
return vm->GetEcmaGCStats()->GetFullGCLongTimeCount();
|
|
}
|
|
|
|
void DFXJSNApi::GetHeapPrepare(const EcmaVM *vm)
|
|
{
|
|
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
|
|
const_cast<ecmascript::Heap *>(vm->GetHeap())->GetHeapPrepare();
|
|
}
|
|
|
|
void DFXJSNApi::SetJsDumpThresholds([[maybe_unused]] EcmaVM *vm, [[maybe_unused]] size_t thresholds)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT) && defined(PANDA_TARGET_OHOS) && defined(ENABLE_HISYSEVENT)
|
|
vm->GetHeap()->SetJsDumpThresholds(thresholds);
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support set jsdump thresholds";
|
|
#endif
|
|
}
|
|
|
|
void DFXJSNApi::SetAppFreezeFilterCallback(const EcmaVM *vm, AppFreezeFilterCallback cb)
|
|
{
|
|
const_cast<ecmascript::Heap *>(vm->GetHeap())->SetAppFreezeFilterCallback(cb);
|
|
ecmascript::SharedHeap* sHeap = ecmascript::SharedHeap::GetInstance();
|
|
sHeap->SetAppFreezeFilterCallback(cb);
|
|
}
|
|
|
|
void DFXJSNApi::NotifyApplicationState(EcmaVM *vm, bool inBackground)
|
|
{
|
|
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
|
|
const_cast<ecmascript::Heap *>(vm->GetHeap())->ChangeGCParams(inBackground);
|
|
ecmascript::Jit::GetInstance()->ChangeTaskPoolState(inBackground);
|
|
}
|
|
|
|
void DFXJSNApi::NotifyIdleStatusControl(const EcmaVM *vm, std::function<void(bool)> callback)
|
|
{
|
|
const_cast<ecmascript::Heap *>(vm->GetHeap())->InitializeIdleStatusControl(callback);
|
|
}
|
|
|
|
void DFXJSNApi::NotifyIdleTime(const EcmaVM *vm, int idleMicroSec)
|
|
{
|
|
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
|
|
const_cast<ecmascript::Heap *>(vm->GetHeap())->TriggerIdleCollection(idleMicroSec);
|
|
}
|
|
|
|
void DFXJSNApi::NotifyMemoryPressure(EcmaVM *vm, bool inHighMemoryPressure)
|
|
{
|
|
const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyMemoryPressure(inHighMemoryPressure);
|
|
}
|
|
|
|
void DFXJSNApi::NotifyFinishColdStart(EcmaVM *vm, bool isConvinced)
|
|
{
|
|
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
|
|
if (isConvinced) {
|
|
const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyFinishColdStart();
|
|
} else {
|
|
const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyFinishColdStartSoon();
|
|
}
|
|
}
|
|
|
|
void DFXJSNApi::NotifyHighSensitive(EcmaVM *vm, bool isStart)
|
|
{
|
|
const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyHighSensitive(isStart);
|
|
}
|
|
|
|
bool DFXJSNApi::StopCpuProfilerForColdStart([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
|
bool success = false;
|
|
auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
|
|
if (options.EnableCpuProfilerColdStartMainThread()) {
|
|
success = true;
|
|
DFXJSNApi::StopCpuProfilerForFile(vm);
|
|
}
|
|
|
|
if (options.EnableCpuProfilerColdStartWorkerThread()) {
|
|
success = true;
|
|
const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
|
|
if (workerVm->GetJSThread()->GetIsProfiling()) {
|
|
DFXJSNApi::StopCpuProfilerForFile(workerVm);
|
|
}
|
|
});
|
|
}
|
|
|
|
return success;
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
|
void DFXJSNApi::CpuProfilerAnyTimeMainThread(const EcmaVM *vm)
|
|
{
|
|
const uint8_t KILL_COUNT_FACTOR = 2;
|
|
if (killCount % KILL_COUNT_FACTOR == 0) {
|
|
uint8_t fileCount = killCount / KILL_COUNT_FACTOR + 1;
|
|
LOG_ECMA(INFO) << "Start CpuProfiler Any Time Main Thread, killCount = " << killCount;
|
|
std::string fileName = ConvertToStdString(const_cast<EcmaVM *>(vm)->GetBundleName())
|
|
+ "_" + std::to_string(fileCount) + ".cpuprofile";
|
|
if (!BuiltinsArkTools::CreateFile(fileName)) {
|
|
LOG_ECMA(ERROR) << "createFile failed " << fileName;
|
|
} else {
|
|
DFXJSNApi::StartCpuProfilerForFile(vm, fileName, CpuProfiler::INTERVAL_OF_INNER_START);
|
|
}
|
|
} else {
|
|
LOG_ECMA(INFO) << "Stop CpuProfiler Any Time Main Thread, killCount = " << killCount;
|
|
if (vm->GetJSThread()->GetIsProfiling()) {
|
|
DFXJSNApi::StopCpuProfilerForFile(vm);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
bool DFXJSNApi::CpuProfilerSamplingAnyTime([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
|
(void)killCount;
|
|
bool success = false;
|
|
const uint8_t KILL_COUNT_FACTOR = 2;
|
|
auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
|
|
if (options.EnableCpuProfilerAnyTimeMainThread()) {
|
|
success = true;
|
|
CpuProfilerAnyTimeMainThread(vm);
|
|
}
|
|
|
|
if (options.EnableCpuProfilerAnyTimeWorkerThread()) {
|
|
success = true;
|
|
if (killCount % KILL_COUNT_FACTOR == 0) {
|
|
uint8_t fileCount = killCount / KILL_COUNT_FACTOR + 1;
|
|
LOG_ECMA(INFO) << "Start CpuProfiler Any Time Worker Thread, killCount = " << killCount;
|
|
const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
|
|
auto *thread = workerVm->GetAssociatedJSThread();
|
|
std::string fileName = ConvertToStdString(workerVm->GetBundleName()) + "_"
|
|
+ std::to_string(thread->GetThreadId()) + "_"
|
|
+ std::to_string(fileCount) + ".cpuprofile";
|
|
if (!BuiltinsArkTools::CreateFile(fileName)) {
|
|
LOG_ECMA(ERROR) << "createFile failed " << fileName;
|
|
} else {
|
|
thread->SetCpuProfileName(fileName);
|
|
thread->SetNeedProfiling(true);
|
|
}
|
|
});
|
|
} else {
|
|
LOG_ECMA(INFO) << "Stop CpuProfiler Any Time Worker Thread, killCount = " << killCount;
|
|
const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
|
|
auto *thread = workerVm->GetAssociatedJSThread();
|
|
if (thread->GetIsProfiling()) {
|
|
DFXJSNApi::StopCpuProfilerForFile(workerVm);
|
|
}
|
|
thread->SetNeedProfiling(false);
|
|
});
|
|
}
|
|
}
|
|
|
|
return success;
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool DFXJSNApi::StartCpuProfilerForFile([[maybe_unused]] const EcmaVM *vm,
|
|
[[maybe_unused]] const std::string &fileName,
|
|
[[maybe_unused]] int interval)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
|
LOG_ECMA(INFO) << "DFXJSNApi::StartCpuProfilerForFile, vm = " << vm;
|
|
if (interval <= 0) {
|
|
LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForFile, interval <= 0";
|
|
return false;
|
|
}
|
|
if (vm == nullptr) {
|
|
LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForFile, vm == nullptr";
|
|
return false;
|
|
}
|
|
CpuProfiler *profiler = vm->GetProfiler();
|
|
if (profiler == nullptr) {
|
|
profiler = new CpuProfiler(vm, interval);
|
|
const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
|
|
}
|
|
return profiler->StartCpuProfilerForFile(fileName);
|
|
#else
|
|
LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForFile, not support cpu profiler";
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
void DFXJSNApi::StopCpuProfilerForFile([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
|
LOG_ECMA(INFO) << "DFXJSNApi::StopCpuProfilerForFile, vm = " << vm;
|
|
if (vm == nullptr) {
|
|
LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForFile, vm == nullptr";
|
|
return;
|
|
}
|
|
CpuProfiler *profiler = vm->GetProfiler();
|
|
if (profiler == nullptr) {
|
|
LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForFile, profiler == nullptr";
|
|
return;
|
|
}
|
|
bool result = profiler->StopCpuProfilerForFile();
|
|
if (!result) {
|
|
LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForFile failed";
|
|
return;
|
|
}
|
|
delete profiler;
|
|
profiler = nullptr;
|
|
const_cast<EcmaVM *>(vm)->SetProfiler(nullptr);
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
|
|
#endif
|
|
}
|
|
|
|
bool DFXJSNApi::StartCpuProfilerForInfo([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int interval)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
|
LOG_ECMA(INFO) << "DFXJSNApi::StartCpuProfilerForInfo, vm = " << vm;
|
|
if (interval <= 0) {
|
|
LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForInfo, interval <= 0";
|
|
return false;
|
|
}
|
|
if (vm == nullptr) {
|
|
LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForInfo, vm == nullptr";
|
|
return false;
|
|
}
|
|
CpuProfiler *profiler = vm->GetProfiler();
|
|
if (profiler == nullptr) {
|
|
profiler = new CpuProfiler(vm, interval);
|
|
const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
|
|
}
|
|
return profiler->StartCpuProfilerForInfo();
|
|
#else
|
|
LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForInfo, not support cpu profiler";
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
std::unique_ptr<ProfileInfo> DFXJSNApi::StopCpuProfilerForInfo([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
|
LOG_ECMA(INFO) << "DFXJSNApi::StopCpuProfilerForInfo, vm = " << vm;
|
|
if (vm == nullptr) {
|
|
LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForInfo, vm == nullptr";
|
|
return nullptr;
|
|
}
|
|
CpuProfiler *profiler = vm->GetProfiler();
|
|
if (profiler == nullptr) {
|
|
LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForInfo, profiler == nullptr";
|
|
return nullptr;
|
|
}
|
|
std::unique_ptr<ProfileInfo> profileInfo;
|
|
bool result = profiler->StopCpuProfilerForInfo(profileInfo);
|
|
if (!result) {
|
|
LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForInfo failed";
|
|
return nullptr;
|
|
}
|
|
delete profiler;
|
|
profiler = nullptr;
|
|
const_cast<EcmaVM *>(vm)->SetProfiler(nullptr);
|
|
return profileInfo;
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
void DFXJSNApi::SetCpuSamplingInterval([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int interval)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
|
if (interval < 0) {
|
|
LOG_ECMA(ERROR) << "Sampling interval is illegal";
|
|
return;
|
|
}
|
|
LOG_ECMA(INFO) << "SetCpuProfilerSamplingInterval, Sampling interval is: " << interval;
|
|
if (vm == nullptr) {
|
|
return;
|
|
}
|
|
CpuProfiler *profiler = vm->GetProfiler();
|
|
if (profiler == nullptr) {
|
|
profiler = new CpuProfiler(vm, interval);
|
|
const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
|
|
return;
|
|
}
|
|
profiler->SetCpuSamplingInterval(interval);
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
|
|
#endif
|
|
}
|
|
|
|
void DFXJSNApi::EnableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM, int32_t threshold)
|
|
{
|
|
ecmaVM->GetJsDebuggerManager()->EnableSerializationTimeoutCheck();
|
|
ecmaVM->GetJsDebuggerManager()->SetSerializationCheckThreshold(threshold);
|
|
}
|
|
|
|
void DFXJSNApi::DisableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM)
|
|
{
|
|
ecmaVM->GetJsDebuggerManager()->DisableSerializationTimeoutCheck();
|
|
}
|
|
|
|
bool DFXJSNApi::SuspendVM([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
|
|
return vmThreadControl->NotifyVMThreadSuspension();
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
void DFXJSNApi::ResumeVM([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
|
|
vmThreadControl->ResumeVM();
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
|
|
#endif
|
|
}
|
|
|
|
bool DFXJSNApi::IsSuspended([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
|
|
return vmThreadControl->IsSuspended();
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
void DFXJSNApi::TerminateExecution(const EcmaVM *vm)
|
|
{
|
|
ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
|
|
vmThreadControl->RequestTerminateExecution();
|
|
}
|
|
|
|
bool DFXJSNApi::CheckSafepoint([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
|
ecmascript::JSThread* thread = vm->GetJSThread();
|
|
return thread->CheckSafepoint();
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool DFXJSNApi::BuildJsStackInfoList(const EcmaVM *hostVm, uint32_t tid, std::vector<JsFrameInfo>& jsFrames)
|
|
{
|
|
EcmaVM *vm;
|
|
if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
|
|
vm = const_cast<EcmaVM*>(hostVm);
|
|
} else {
|
|
vm = const_cast<EcmaVM*>(hostVm)->GetWorkerVm(tid);
|
|
if (vm == nullptr) {
|
|
return false;
|
|
}
|
|
}
|
|
jsFrames = ecmascript::JsStackInfo::BuildJsStackInfo(vm->GetAssociatedJSThread());
|
|
if (jsFrames.size() > 0) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int32_t DFXJSNApi::GetObjectHash(const EcmaVM *vm, Local<JSValueRef> nativeObject)
|
|
{
|
|
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(nativeObject);
|
|
return ecmascript::tooling::DebuggerApi::GetObjectHash(vm, obj);
|
|
}
|
|
|
|
bool DFXJSNApi::StartSampling([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] uint64_t samplingInterval)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
|
|
ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
|
|
const_cast<EcmaVM *>(vm));
|
|
return heapProfile->StartHeapSampling(samplingInterval);
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
const SamplingInfo *DFXJSNApi::GetAllocationProfile([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
|
|
ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
|
|
const_cast<EcmaVM *>(vm));
|
|
return heapProfile->GetAllocationProfile();
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
void DFXJSNApi::StopSampling([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
|
|
ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
|
|
const_cast<EcmaVM *>(vm));
|
|
heapProfile->StopHeapSampling();
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
|
|
#endif
|
|
}
|
|
|
|
// release or debug hap : aa start -p 'dumpheap'
|
|
// aa start -p 'profile'
|
|
bool DFXJSNApi::StartProfiler(EcmaVM *vm, const ProfilerOption &option, int tid,
|
|
int32_t instanceId, const DebuggerPostTask &debuggerPostTask, bool isDebugApp)
|
|
{
|
|
LOG_ECMA(INFO) << "DFXJSNApi::StartProfiler, type = " << (int)option.profilerType
|
|
<< ", tid = " << tid << ", isDebugApp = " << isDebugApp;
|
|
JSNApi::DebugOption debugOption;
|
|
debugOption.libraryPath = option.libraryPath;
|
|
if (option.profilerType == ProfilerType::CPU_PROFILER) {
|
|
debugOption.isDebugMode = false;
|
|
if (JSNApi::NotifyDebugMode(tid, vm, debugOption, instanceId, debuggerPostTask, isDebugApp)) {
|
|
return StartCpuProfilerForInfo(vm, option.interval);
|
|
} else {
|
|
LOG_ECMA(ERROR) << "DFXJSNApi::StartProfiler, NotifyDebugMode failed";
|
|
return false;
|
|
}
|
|
} else {
|
|
debugOption.isDebugMode = true;
|
|
return JSNApi::NotifyDebugMode(tid, vm, debugOption, instanceId, debuggerPostTask, isDebugApp);
|
|
}
|
|
}
|
|
|
|
void DFXJSNApi::ResumeVMById(EcmaVM *hostVm, uint32_t tid)
|
|
{
|
|
if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
|
|
ResumeVM(hostVm);
|
|
} else {
|
|
hostVm->ResumeWorkerVm(tid);
|
|
}
|
|
}
|
|
|
|
bool DFXJSNApi::SuspendVMById(EcmaVM *hostVm, uint32_t tid)
|
|
{
|
|
bool success = false;
|
|
if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
|
|
success = SuspendVM(hostVm);
|
|
LOG_ECMA(INFO) << "The main thread, SuspendVMById succeeded: " << success;
|
|
return success;
|
|
} else {
|
|
success = hostVm->SuspendWorkerVm(tid);
|
|
LOG_ECMA(INFO) << "The worker thread, SuspendVMById succeeded: " << success;
|
|
return success;
|
|
}
|
|
}
|
|
|
|
bool DFXJSNApi::StartTracing([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] std::string &categories)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_TRACING)
|
|
if (vm == nullptr) {
|
|
return false;
|
|
}
|
|
Tracing *tracing = vm->GetTracing();
|
|
if (tracing == nullptr) {
|
|
tracing = new Tracing(vm);
|
|
const_cast<EcmaVM *>(vm)->SetTracing(tracing);
|
|
}
|
|
tracing->StartTracing(categories);
|
|
return true;
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler tracing";
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
std::unique_ptr<std::vector<TraceEvent>> DFXJSNApi::StopTracing([[maybe_unused]] const EcmaVM *vm)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_TRACING)
|
|
if (vm == nullptr) {
|
|
return nullptr;
|
|
}
|
|
Tracing *tracing = vm->GetTracing();
|
|
if (tracing == nullptr) {
|
|
LOG_ECMA(ERROR) << "StopTracing tracing is nullptr";
|
|
return nullptr;
|
|
}
|
|
auto traceEvents = tracing->StopTracing();
|
|
if (traceEvents == nullptr) {
|
|
LOG_ECMA(ERROR) << "trace events is nullptr";
|
|
}
|
|
delete tracing;
|
|
tracing = nullptr;
|
|
const_cast<EcmaVM *>(vm)->SetTracing(nullptr);
|
|
return traceEvents;
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler tracing";
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
void DFXJSNApi::GetTracingBufferUseage([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] double &percentFull,
|
|
[[maybe_unused]] uint32_t &eventCount, [[maybe_unused]] double &value)
|
|
{
|
|
#if defined(ECMASCRIPT_SUPPORT_TRACING)
|
|
if (vm == nullptr) {
|
|
return;
|
|
}
|
|
ecmascript::Tracing *tracing = vm->GetTracing();
|
|
if (tracing == nullptr) {
|
|
LOG_ECMA(ERROR) << "GetTracingBufferUseage tracing is nullptr";
|
|
} else {
|
|
tracing->GetBufferUseage(percentFull, eventCount, value);
|
|
}
|
|
#else
|
|
LOG_ECMA(ERROR) << "Not support arkcompiler tracing";
|
|
#endif
|
|
}
|
|
|
|
void DFXJSNApi::TranslateJSStackInfo(const EcmaVM *vm, std::string &url, int32_t &line, int32_t &column)
|
|
{
|
|
auto cb = vm->GetSourceMapTranslateCallback();
|
|
if (cb == nullptr) {
|
|
LOG_ECMA(ERROR) << "Translate failed, callback function is nullptr.";
|
|
} else if (!cb(url, line, column)) {
|
|
LOG_ECMA(ERROR) << "Translate failed, url: " << url;
|
|
}
|
|
}
|
|
|
|
uint32_t DFXJSNApi::GetCurrentThreadId()
|
|
{
|
|
return JSThread::GetCurrentThreadId();
|
|
}
|
|
} // namespace panda
|