1 /*
2  * Copyright (c) 2021-2024 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 <semaphore.h>
17 #include "ecmascript/napi/include/dfx_jsnapi.h"
18 
19 #include "ecmascript/base/block_hook_scope.h"
20 #include "ecmascript/builtins/builtins_ark_tools.h"
21 #include "ecmascript/checkpoint/thread_state_transition.h"
22 #include "ecmascript/debugger/debugger_api.h"
23 #include "ecmascript/debugger/js_debugger_manager.h"
24 #include "ecmascript/dfx/stackinfo/js_stackinfo.h"
25 #include "ecmascript/dfx/tracing/tracing.h"
26 #include "ecmascript/mem/heap-inl.h"
27 #include "ecmascript/jit/jit.h"
28 #include "ecmascript/dfx/vm_thread_control.h"
29 
30 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
31 #include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
32 #include "ecmascript/dfx/cpu_profiler/samples_record.h"
33 #endif
34 #if defined(ENABLE_DUMP_IN_FAULTLOG)
35 #include "faultloggerd_client.h"
36 #include "uv.h"
37 #endif
38 
39 namespace panda {
40 using ecmascript::CString;
41 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
42 using BuiltinsArkTools = ecmascript::builtins::BuiltinsArkTools;
43 using ecmascript::CpuProfiler;
44 #endif
45 using ecmascript::EcmaString;
46 using ecmascript::JSTaggedValue;
47 using ecmascript::GCStats;
48 template<typename T>
49 using JSHandle = ecmascript::JSHandle<T>;
50 using ecmascript::FileStream;
51 using ecmascript::FileDescriptorStream;
52 using ecmascript::CMap;
53 using ecmascript::Tracing;
54 using ecmascript::DumpSnapShotOption;
55 sem_t g_heapdumpCnt;
56 
DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const std::string &path, [[maybe_unused]] const DumpSnapShotOption &dumpOption)57 void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const std::string &path,
58                                  [[maybe_unused]] const DumpSnapShotOption &dumpOption)
59 {
60 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
61     FileStream stream(path);
62     DumpHeapSnapshot(vm, &stream, dumpOption);
63 #else
64     LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
65 #endif
66 }
67 
68 // IDE interface.
DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream *stream, [[maybe_unused]] const DumpSnapShotOption &dumpOption, [[maybe_unused]] Progress *progress)69 void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream *stream,
70                                  [[maybe_unused]] const DumpSnapShotOption &dumpOption,
71                                  [[maybe_unused]] Progress *progress)
72 {
73 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
74     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
75         const_cast<EcmaVM *>(vm));
76     heapProfile->DumpHeapSnapshot(stream, dumpOption, progress);
77 #else
78     LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
79 #endif
80 }
81 
82 [[maybe_unused]] static uint8_t killCount = 0;
83 
DumpCpuProfile([[maybe_unused]] const EcmaVM *vm)84 void DFXJSNApi::DumpCpuProfile([[maybe_unused]] const EcmaVM *vm)
85 {
86 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
87 #if defined(ENABLE_DUMP_IN_FAULTLOG)
88 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
89     // for CpuProfiler kill contral
90     if (DFXJSNApi::StopCpuProfilerForColdStart(vm)) {
91         return;
92     }
93 
94     (void)killCount;
95     if (DFXJSNApi::CpuProfilerSamplingAnyTime(vm)) {
96         killCount++;
97         return;
98     }
99 #endif // ECMASCRIPT_SUPPORT_CPUPROFILER
100 #endif // ENABLE_DUMP_IN_FAULTLOG
101 #endif // ECMASCRIPT_SUPPORT_SNAPSHOT
102 }
103 
104 // kill -39.
DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const DumpSnapShotOption &dumpOption)105 void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm,
106                                  [[maybe_unused]] const DumpSnapShotOption &dumpOption)
107 {
108 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
109 #if defined(ENABLE_DUMP_IN_FAULTLOG)
110     sem_wait(&g_heapdumpCnt);
111     auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
112     options.SwitchStartGlobalLeakCheck();
113     if (options.EnableGlobalLeakCheck() && options.IsStartGlobalLeakCheck()) {
114         int32_t stackTraceFd = RequestFileDescriptor(static_cast<int32_t>(FaultLoggerType::JS_STACKTRACE));
115         if (stackTraceFd < 0) {
116             options.SwitchStartGlobalLeakCheck();
117         } else {
118             vm->GetJSThread()->SetStackTraceFd(stackTraceFd);
119         }
120     }
121 
122     // Write in faultlog for heap leak.
123     int32_t fd;
124     if (dumpOption.isDumpOOM && dumpOption.dumpFormat == DumpFormat::BINARY) {
125         fd = RequestFileDescriptor(static_cast<int32_t>(FaultLoggerType::JS_RAW_SNAPSHOT));
126     } else {
127         fd = RequestFileDescriptor(static_cast<int32_t>(FaultLoggerType::JS_HEAP_SNAPSHOT));
128     }
129     if (fd < 0) {
130         LOG_ECMA(ERROR) << "Write FD failed, fd" << fd;
131         return;
132     }
133     FileDescriptorStream stream(fd);
134     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
135         const_cast<EcmaVM *>(vm));
136     heapProfile->DumpHeapSnapshot(&stream, dumpOption);
137 
138     sem_post(&g_heapdumpCnt);
139 #endif // ENABLE_DUMP_IN_FAULTLOG
140 #else
141     LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
142 #endif // ECMASCRIPT_SUPPORT_SNAPSHOT
143 }
144 
145 // tid = 0: dump all vm; tid != 0: dump tid vm, hidumper.
DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const DumpSnapShotOption &dumpOption, [[maybe_unused]] uint32_t tid)146 void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm,
147                                  [[maybe_unused]] const DumpSnapShotOption &dumpOption, [[maybe_unused]] uint32_t tid)
148 {
149     const int THREAD_COUNT = 1;
150     if (vm->IsWorkerThread()) {
151         LOG_ECMA(ERROR) << "this is a workthread!";
152         return;
153     }
154     sem_init(&g_heapdumpCnt, 0, THREAD_COUNT);
155     uint32_t curTid = vm->GetTid();
156     LOG_ECMA(INFO) << "DumpHeapSnapshot tid " << tid << " curTid " << curTid;
157     DumpHeapSnapshotWithVm(vm, dumpOption, tid);
158 }
159 
DumpHeapSnapshotWithVm([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const DumpSnapShotOption &dumpOption, [[maybe_unused]] uint32_t tid)160 void DFXJSNApi::DumpHeapSnapshotWithVm([[maybe_unused]] const EcmaVM *vm,
161                                        [[maybe_unused]] const DumpSnapShotOption &dumpOption,
162                                        [[maybe_unused]] uint32_t tid)
163 {
164 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
165 #if defined(ENABLE_DUMP_IN_FAULTLOG)
166     uv_loop_t *loop = reinterpret_cast<uv_loop_t *>(vm->GetLoop());
167     if (loop == nullptr || uv_loop_alive(loop) == 0) {
168         LOG_ECMA(ERROR) << "loop nullptr or uv_loop_alive dead";
169         return;
170     }
171     struct DumpForSnapShotStruct *dumpStruct = new DumpForSnapShotStruct();
172     dumpStruct->vm = vm;
173     dumpStruct->dumpOption = dumpOption;
174     uv_work_t *work = new(std::nothrow) uv_work_t;
175     if (work == nullptr) {
176         LOG_ECMA(ERROR) << "work nullptr";
177         delete dumpStruct;
178         return;
179     }
180     work->data = static_cast<void *>(dumpStruct);
181 
182     uint32_t curTid = vm->GetTid();
183     int ret = 0;
184     if (tid == 0 || tid == curTid) {
185         ret = uv_queue_work(loop, work, [](uv_work_t *) {}, [](uv_work_t *work, int32_t) {
186             struct DumpForSnapShotStruct *dump = static_cast<struct DumpForSnapShotStruct *>(work->data);
187             DFXJSNApi::GetHeapPrepare(dump->vm);
188             DumpSnapShotOption dumpOption = dump->dumpOption;
189             DumpHeapSnapshot(dump->vm, dumpOption);
190             delete dump;
191             delete work;
192         });
193     } else {
194         delete dumpStruct;
195         delete work;
196     }
197 
198     // dump worker vm
199     const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
200         uint32_t curTid = workerVm->GetTid();
201         LOG_ECMA(INFO) << "DumpHeapSnapshot workthread curTid " << curTid;
202         DumpHeapSnapshotWithVm(workerVm, dumpOption, tid);
203         return;
204     });
205 
206     if (ret != 0) {
207         LOG_ECMA(ERROR) << "uv_queue_work fail ret " << ret;
208         delete dumpStruct;
209         delete work;
210     }
211 #endif
212 #endif
213 }
214 
GenerateHeapSnapshotByBinFile([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] std::string &inputFilePath, [[maybe_unused]] std::string &outputPath)215 void DFXJSNApi::GenerateHeapSnapshotByBinFile([[maybe_unused]] const EcmaVM *vm,
216                                               [[maybe_unused]] std::string &inputFilePath,
217                                               [[maybe_unused]] std::string &outputPath)
218 {
219 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
220     auto *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(const_cast<EcmaVM *>(vm));
221     heapProfile->GenerateHeapSnapshot(inputFilePath, outputPath);
222 #else
223     LOG_ECMA(ERROR) << "Not support GenerateHeapSnapshotByBinFile";
224 #endif // ECMASCRIPT_SUPPORT_SNAPSHOT
225 }
226 
227 // tid = 0: TriggerGC all vm; tid != 0: TriggerGC tid vm
TriggerGC([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] uint32_t tid)228 void DFXJSNApi::TriggerGC([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] uint32_t tid)
229 {
230     if (vm->IsWorkerThread()) {
231         LOG_ECMA(ERROR) << "this is a workthread!";
232         return;
233     }
234     // triggerGC host vm
235     uint32_t curTid = vm->GetTid();
236     LOG_ECMA(INFO) << "TriggerGC tid " << tid << " curTid " << curTid;
237     if (tid == 0 || tid == curTid) {
238         TriggerGCWithVm(vm);
239     }
240     // triggerGC worker vm
241     const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
242         curTid = workerVm->GetTid();
243         LOG_ECMA(INFO) << "TriggerGC tid " << tid << " curTid " << curTid;
244         if (tid == 0 || tid == curTid) {
245             TriggerGCWithVm(workerVm);
246             return;
247         }
248     });
249     // triggerSharedFullGC
250     TriggerSharedGCWithVm(vm);
251 }
252 
TriggerSharedGCWithVm([[maybe_unused]] const EcmaVM *vm)253 void DFXJSNApi::TriggerSharedGCWithVm([[maybe_unused]] const EcmaVM *vm)
254 {
255 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
256 #if defined(ENABLE_DUMP_IN_FAULTLOG)
257     uv_loop_t *loop = reinterpret_cast<uv_loop_t *>(vm->GetLoop());
258     if (loop == nullptr) {
259         LOG_ECMA(ERROR) << "loop nullptr";
260         return;
261     }
262     if (uv_loop_alive(loop) == 0) {
263         LOG_ECMA(ERROR) << "uv_loop_alive dead";
264         return;
265     }
266     uv_work_t *work = new(std::nothrow) uv_work_t;
267     if (work == nullptr) {
268         LOG_ECMA(FATAL) << "DFXJSNApi::TriggerGCWithVm:work is nullptr";
269         return;
270     }
271     work->data = static_cast<void *>(const_cast<EcmaVM *>(vm));
272     int ret = uv_queue_work(loop, work, [](uv_work_t *) {}, [](uv_work_t *work, int32_t) {
273         EcmaVM *vm = static_cast<EcmaVM *>(work->data);
274         ecmascript::SharedHeap* sHeap = ecmascript::SharedHeap::GetInstance();
275         JSThread *thread = vm->GetJSThread();
276         ecmascript::ThreadManagedScope managedScope(thread);
277         sHeap->CollectGarbage<ecmascript::TriggerGCType::SHARED_FULL_GC,
278             ecmascript::GCReason::TRIGGER_BY_MEM_TOOLS>(thread);
279         delete work;
280     });
281     if (ret != 0) {
282         LOG_ECMA(ERROR) << "uv_queue_work fail ret " << ret;
283         delete work;
284     }
285 #endif
286 #endif
287 }
288 
TriggerGCWithVm([[maybe_unused]] const EcmaVM *vm)289 void DFXJSNApi::TriggerGCWithVm([[maybe_unused]] const EcmaVM *vm)
290 {
291 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
292 #if defined(ENABLE_DUMP_IN_FAULTLOG)
293     uv_loop_t *loop = reinterpret_cast<uv_loop_t *>(vm->GetLoop());
294     if (loop == nullptr) {
295         LOG_ECMA(ERROR) << "loop nullptr";
296         return;
297     }
298     if (uv_loop_alive(loop) == 0) {
299         LOG_ECMA(ERROR) << "uv_loop_alive dead";
300         return;
301     }
302     uv_work_t *work = new(std::nothrow) uv_work_t;
303     if (work == nullptr) {
304         LOG_ECMA(FATAL) << "DFXJSNApi::TriggerGCWithVm:work is nullptr";
305         return;
306     }
307     work->data = static_cast<void *>(const_cast<EcmaVM *>(vm));
308     int ret = uv_queue_work(loop, work, [](uv_work_t *) {}, [](uv_work_t *work, int32_t) {
309         EcmaVM *vm = static_cast<EcmaVM *>(work->data);
310         ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
311         vm->CollectGarbage(ecmascript::TriggerGCType::FULL_GC, ecmascript::GCReason::TRIGGER_BY_MEM_TOOLS);
312         delete work;
313     });
314     if (ret != 0) {
315         LOG_ECMA(ERROR) << "uv_queue_work fail ret " << ret;
316         delete work;
317     }
318 #endif
319 #endif
320 }
321 
DestroyHeapProfiler([[maybe_unused]] const EcmaVM *vm)322 void DFXJSNApi::DestroyHeapProfiler([[maybe_unused]] const EcmaVM *vm)
323 {
324 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
325     ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
326     ecmascript::HeapProfilerInterface::Destroy(const_cast<EcmaVM *>(vm));
327 #else
328     LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
329 #endif
330 }
331 
BuildNativeAndJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr)332 bool DFXJSNApi::BuildNativeAndJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr)
333 {
334     stackTraceStr = ecmascript::JsStackInfo::BuildJsStackTrace(vm->GetAssociatedJSThread(), true);
335     if (stackTraceStr.empty()) {
336         return false;
337     }
338     return true;
339 }
340 
BuildJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr)341 bool DFXJSNApi::BuildJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr)
342 {
343     stackTraceStr = ecmascript::JsStackInfo::BuildJsStackTrace(vm->GetAssociatedJSThread(), false);
344     if (stackTraceStr.empty()) {
345         return false;
346     }
347     return true;
348 }
349 
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)350 bool DFXJSNApi::StartHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] double timeInterval,
351                                   [[maybe_unused]] bool isVmMode, [[maybe_unused]] Stream *stream,
352                                   [[maybe_unused]] bool traceAllocation, [[maybe_unused]] bool newThread)
353 {
354 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
355     ecmascript::base::BlockHookScope blockScope;
356     ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
357     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
358         const_cast<EcmaVM *>(vm));
359     return heapProfile->StartHeapTracking(timeInterval, isVmMode, stream, traceAllocation, newThread);
360 #else
361     LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
362     return false;
363 #endif
364 }
365 
UpdateHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream *stream)366 bool DFXJSNApi::UpdateHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream *stream)
367 {
368 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
369     ecmascript::base::BlockHookScope blockScope;
370     ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
371     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
372         const_cast<EcmaVM *>(vm));
373     return heapProfile->UpdateHeapTracking(stream);
374 #else
375     LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
376     return false;
377 #endif
378 }
379 
StopHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const std::string &filePath, [[maybe_unused]] bool newThread)380 bool DFXJSNApi::StopHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const std::string &filePath,
381                                  [[maybe_unused]] bool newThread)
382 {
383 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
384     FileStream stream(filePath);
385     return StopHeapTracking(vm, &stream, nullptr, newThread);
386 #else
387     LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
388     return false;
389 #endif
390 }
391 
StopHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream* stream, [[maybe_unused]] Progress *progress, [[maybe_unused]] bool newThread)392 bool DFXJSNApi::StopHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream* stream,
393                                  [[maybe_unused]] Progress *progress, [[maybe_unused]] bool newThread)
394 {
395 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
396     ecmascript::base::BlockHookScope blockScope;
397     ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
398     bool result = false;
399     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
400         const_cast<EcmaVM *>(vm));
401     result = heapProfile->StopHeapTracking(stream, progress, newThread);
402     ecmascript::HeapProfilerInterface::Destroy(const_cast<EcmaVM *>(vm));
403     return result;
404 #else
405     LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
406     return false;
407 #endif
408 }
409 
PrintStatisticResult(const EcmaVM *vm)410 void DFXJSNApi::PrintStatisticResult(const EcmaVM *vm)
411 {
412     ecmascript::GCStats gcstats(vm->GetHeap());
413     gcstats.PrintStatisticResult();
414 }
415 
StartRuntimeStat(EcmaVM *vm)416 void DFXJSNApi::StartRuntimeStat(EcmaVM *vm)
417 {
418     vm->GetJSThread()->GetCurrentEcmaContext()->SetRuntimeStatEnable(true);
419 }
420 
StopRuntimeStat(EcmaVM *vm)421 void DFXJSNApi::StopRuntimeStat(EcmaVM *vm)
422 {
423     vm->GetJSThread()->GetCurrentEcmaContext()->SetRuntimeStatEnable(false);
424 }
425 
GetArrayBufferSize(const EcmaVM *vm)426 size_t DFXJSNApi::GetArrayBufferSize(const EcmaVM *vm)
427 {
428     ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
429     return vm->GetHeap()->GetArrayBufferSize();
430 }
431 
GetHeapTotalSize(const EcmaVM *vm)432 size_t DFXJSNApi::GetHeapTotalSize(const EcmaVM *vm)
433 {
434     return vm->GetHeap()->GetCommittedSize();
435 }
436 
GetHeapUsedSize(const EcmaVM *vm)437 size_t DFXJSNApi::GetHeapUsedSize(const EcmaVM *vm)
438 {
439     ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
440     return vm->GetHeap()->GetLiveObjectSize();
441 }
442 
GetHeapObjectSize(const EcmaVM *vm)443 size_t DFXJSNApi::GetHeapObjectSize(const EcmaVM *vm)
444 {
445     return vm->GetHeap()->GetHeapObjectSize();
446 }
447 
GetHeapLimitSize(const EcmaVM *vm)448 size_t DFXJSNApi::GetHeapLimitSize(const EcmaVM *vm)
449 {
450     return vm->GetHeap()->GetHeapLimitSize();
451 }
452 
GetProcessHeapLimitSize()453 size_t DFXJSNApi::GetProcessHeapLimitSize()
454 {
455     return ecmascript::MemMapAllocator::GetInstance()->GetCapacity();
456 }
457 
GetGCCount(const EcmaVM *vm)458 size_t DFXJSNApi::GetGCCount(const EcmaVM *vm)
459 {
460     if (vm->IsWorkerThread()) {
461         return vm->GetEcmaGCStats()->GetGCCount();
462     }
463     return vm->GetEcmaGCStats()->GetGCCount() +
464         ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetGCCount();
465 }
466 
GetGCDuration(const EcmaVM *vm)467 size_t DFXJSNApi::GetGCDuration(const EcmaVM *vm)
468 {
469     if (vm->IsWorkerThread()) {
470         return vm->GetEcmaGCStats()->GetGCDuration();
471     }
472     return vm->GetEcmaGCStats()->GetGCDuration() +
473         ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetGCDuration();
474 }
475 
GetAccumulatedAllocateSize(const EcmaVM *vm)476 size_t DFXJSNApi::GetAccumulatedAllocateSize(const EcmaVM *vm)
477 {
478     if (vm->IsWorkerThread()) {
479         return vm->GetEcmaGCStats()->GetAccumulatedAllocateSize();
480     }
481     return vm->GetEcmaGCStats()->GetAccumulatedAllocateSize() +
482         ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetAccumulatedAllocateSize();
483 }
484 
GetAccumulatedFreeSize(const EcmaVM *vm)485 size_t DFXJSNApi::GetAccumulatedFreeSize(const EcmaVM *vm)
486 {
487     if (vm->IsWorkerThread()) {
488         return vm->GetEcmaGCStats()->GetAccumulatedFreeSize();
489     }
490     return vm->GetEcmaGCStats()->GetAccumulatedFreeSize() +
491         ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetAccumulatedFreeSize();
492 }
493 
GetFullGCLongTimeCount(const EcmaVM *vm)494 size_t DFXJSNApi::GetFullGCLongTimeCount(const EcmaVM *vm)
495 {
496     return vm->GetEcmaGCStats()->GetFullGCLongTimeCount();
497 }
498 
GetHeapPrepare(const EcmaVM *vm)499 void DFXJSNApi::GetHeapPrepare(const EcmaVM *vm)
500 {
501     ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
502     const_cast<ecmascript::Heap *>(vm->GetHeap())->GetHeapPrepare();
503 }
504 
SetJsDumpThresholds([[maybe_unused]] EcmaVM *vm, [[maybe_unused]] size_t thresholds)505 void DFXJSNApi::SetJsDumpThresholds([[maybe_unused]] EcmaVM *vm, [[maybe_unused]] size_t thresholds)
506 {
507 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT) && defined(PANDA_TARGET_OHOS) && defined(ENABLE_HISYSEVENT)
508     vm->GetHeap()->SetJsDumpThresholds(thresholds);
509 #else
510     LOG_ECMA(ERROR) << "Not support set jsdump thresholds";
511 #endif
512 }
513 
SetAppFreezeFilterCallback(const EcmaVM *vm, AppFreezeFilterCallback cb)514 void DFXJSNApi::SetAppFreezeFilterCallback(const EcmaVM *vm, AppFreezeFilterCallback cb)
515 {
516     const_cast<ecmascript::Heap *>(vm->GetHeap())->SetAppFreezeFilterCallback(cb);
517     ecmascript::SharedHeap* sHeap = ecmascript::SharedHeap::GetInstance();
518     sHeap->SetAppFreezeFilterCallback(cb);
519 }
520 
NotifyApplicationState(EcmaVM *vm, bool inBackground)521 void DFXJSNApi::NotifyApplicationState(EcmaVM *vm, bool inBackground)
522 {
523     ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
524     const_cast<ecmascript::Heap *>(vm->GetHeap())->ChangeGCParams(inBackground);
525     ecmascript::Jit::GetInstance()->ChangeTaskPoolState(inBackground);
526 }
527 
NotifyIdleStatusControl(const EcmaVM *vm, std::function<void(bool)> callback)528 void DFXJSNApi::NotifyIdleStatusControl(const EcmaVM *vm, std::function<void(bool)> callback)
529 {
530     const_cast<ecmascript::Heap *>(vm->GetHeap())->InitializeIdleStatusControl(callback);
531 }
532 
NotifyIdleTime(const EcmaVM *vm, int idleMicroSec)533 void DFXJSNApi::NotifyIdleTime(const EcmaVM *vm, int idleMicroSec)
534 {
535     ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
536     const_cast<ecmascript::Heap *>(vm->GetHeap())->TriggerIdleCollection(idleMicroSec);
537 }
538 
NotifyMemoryPressure(EcmaVM *vm, bool inHighMemoryPressure)539 void DFXJSNApi::NotifyMemoryPressure(EcmaVM *vm, bool inHighMemoryPressure)
540 {
541     const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyMemoryPressure(inHighMemoryPressure);
542 }
543 
NotifyFinishColdStart(EcmaVM *vm, bool isConvinced)544 void DFXJSNApi::NotifyFinishColdStart(EcmaVM *vm, bool isConvinced)
545 {
546     ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
547     if (isConvinced) {
548         const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyFinishColdStart();
549     } else {
550         const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyFinishColdStartSoon();
551     }
552 }
553 
NotifyHighSensitive(EcmaVM *vm, bool isStart)554 void DFXJSNApi::NotifyHighSensitive(EcmaVM *vm, bool isStart)
555 {
556     const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyHighSensitive(isStart);
557 }
558 
StopCpuProfilerForColdStart([[maybe_unused]] const EcmaVM *vm)559 bool DFXJSNApi::StopCpuProfilerForColdStart([[maybe_unused]] const EcmaVM *vm)
560 {
561 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
562     bool success = false;
563     auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
564     if (options.EnableCpuProfilerColdStartMainThread()) {
565         success = true;
566         DFXJSNApi::StopCpuProfilerForFile(vm);
567     }
568 
569     if (options.EnableCpuProfilerColdStartWorkerThread()) {
570         success = true;
571         const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
572             if (workerVm->GetJSThread()->GetIsProfiling()) {
573                 DFXJSNApi::StopCpuProfilerForFile(workerVm);
574             }
575         });
576     }
577 
578     return success;
579 #else
580     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
581     return false;
582 #endif
583 }
584 
585 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
CpuProfilerAnyTimeMainThread(const EcmaVM *vm)586 void DFXJSNApi::CpuProfilerAnyTimeMainThread(const EcmaVM *vm)
587 {
588     const uint8_t KILL_COUNT_FACTOR = 2;
589     if (killCount % KILL_COUNT_FACTOR == 0) {
590         uint8_t fileCount = killCount / KILL_COUNT_FACTOR + 1;
591         LOG_ECMA(INFO) << "Start CpuProfiler Any Time Main Thread, killCount = " << killCount;
592         std::string fileName = ConvertToStdString(const_cast<EcmaVM *>(vm)->GetBundleName())
593                                + "_" + std::to_string(fileCount) + ".cpuprofile";
594         if (!BuiltinsArkTools::CreateFile(fileName)) {
595             LOG_ECMA(ERROR) << "createFile failed " << fileName;
596         } else {
597             DFXJSNApi::StartCpuProfilerForFile(vm, fileName, CpuProfiler::INTERVAL_OF_INNER_START);
598         }
599     } else {
600         LOG_ECMA(INFO) << "Stop CpuProfiler Any Time Main Thread, killCount = " << killCount;
601         if (vm->GetJSThread()->GetIsProfiling()) {
602             DFXJSNApi::StopCpuProfilerForFile(vm);
603         }
604     }
605 }
606 #endif
607 
CpuProfilerSamplingAnyTime([[maybe_unused]] const EcmaVM *vm)608 bool DFXJSNApi::CpuProfilerSamplingAnyTime([[maybe_unused]] const EcmaVM *vm)
609 {
610 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
611     (void)killCount;
612     bool success = false;
613     const uint8_t KILL_COUNT_FACTOR = 2;
614     auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
615     if (options.EnableCpuProfilerAnyTimeMainThread()) {
616         success = true;
617         CpuProfilerAnyTimeMainThread(vm);
618     }
619 
620     if (options.EnableCpuProfilerAnyTimeWorkerThread()) {
621         success = true;
622         if (killCount % KILL_COUNT_FACTOR == 0) {
623             uint8_t fileCount = killCount / KILL_COUNT_FACTOR + 1;
624             LOG_ECMA(INFO) << "Start CpuProfiler Any Time Worker Thread, killCount = " << killCount;
625             const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
626                 auto *thread = workerVm->GetAssociatedJSThread();
627                 std::string fileName = ConvertToStdString(workerVm->GetBundleName()) + "_"
628                                        + std::to_string(thread->GetThreadId()) + "_"
629                                        + std::to_string(fileCount) + ".cpuprofile";
630                 if (!BuiltinsArkTools::CreateFile(fileName)) {
631                     LOG_ECMA(ERROR) << "createFile failed " << fileName;
632                 } else {
633                     thread->SetCpuProfileName(fileName);
634                     thread->SetNeedProfiling(true);
635                 }
636             });
637         } else {
638             LOG_ECMA(INFO) << "Stop CpuProfiler Any Time Worker Thread, killCount = " << killCount;
639             const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
640                 auto *thread = workerVm->GetAssociatedJSThread();
641                 if (thread->GetIsProfiling()) {
642                     DFXJSNApi::StopCpuProfilerForFile(workerVm);
643                 }
644                 thread->SetNeedProfiling(false);
645             });
646         }
647     }
648 
649     return success;
650 #else
651     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
652     return false;
653 #endif
654 }
655 
StartCpuProfilerForFile([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const std::string &fileName, [[maybe_unused]] int interval)656 bool DFXJSNApi::StartCpuProfilerForFile([[maybe_unused]] const EcmaVM *vm,
657                                         [[maybe_unused]] const std::string &fileName,
658                                         [[maybe_unused]] int interval)
659 {
660 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
661     LOG_ECMA(INFO) << "DFXJSNApi::StartCpuProfilerForFile, vm = " << vm;
662     if (interval <= 0) {
663         LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForFile, interval <= 0";
664         return false;
665     }
666     if (vm == nullptr) {
667         LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForFile, vm == nullptr";
668         return false;
669     }
670     CpuProfiler *profiler = vm->GetProfiler();
671     if (profiler == nullptr) {
672         profiler = new CpuProfiler(vm, interval);
673         const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
674     }
675     return profiler->StartCpuProfilerForFile(fileName);
676 #else
677     LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForFile, not support cpu profiler";
678     return false;
679 #endif
680 }
681 
StopCpuProfilerForFile([[maybe_unused]] const EcmaVM *vm)682 void DFXJSNApi::StopCpuProfilerForFile([[maybe_unused]] const EcmaVM *vm)
683 {
684 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
685     LOG_ECMA(INFO) << "DFXJSNApi::StopCpuProfilerForFile, vm = " << vm;
686     if (vm == nullptr) {
687         LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForFile, vm == nullptr";
688         return;
689     }
690     CpuProfiler *profiler = vm->GetProfiler();
691     if (profiler == nullptr) {
692         LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForFile, profiler == nullptr";
693         return;
694     }
695     bool result = profiler->StopCpuProfilerForFile();
696     if (!result) {
697         LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForFile failed";
698         return;
699     }
700     delete profiler;
701     profiler = nullptr;
702     const_cast<EcmaVM *>(vm)->SetProfiler(nullptr);
703 #else
704     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
705 #endif
706 }
707 
StartCpuProfilerForInfo([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int interval)708 bool DFXJSNApi::StartCpuProfilerForInfo([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int interval)
709 {
710 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
711     LOG_ECMA(INFO) << "DFXJSNApi::StartCpuProfilerForInfo, vm = " << vm;
712     if (interval <= 0) {
713         LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForInfo, interval <= 0";
714         return false;
715     }
716     if (vm == nullptr) {
717         LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForInfo, vm == nullptr";
718         return false;
719     }
720     CpuProfiler *profiler = vm->GetProfiler();
721     if (profiler == nullptr) {
722         profiler = new CpuProfiler(vm, interval);
723         const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
724     }
725     return profiler->StartCpuProfilerForInfo();
726 #else
727     LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForInfo, not support cpu profiler";
728     return false;
729 #endif
730 }
731 
StopCpuProfilerForInfo([[maybe_unused]] const EcmaVM *vm)732 std::unique_ptr<ProfileInfo> DFXJSNApi::StopCpuProfilerForInfo([[maybe_unused]] const EcmaVM *vm)
733 {
734 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
735     LOG_ECMA(INFO) << "DFXJSNApi::StopCpuProfilerForInfo, vm = " << vm;
736     if (vm == nullptr) {
737         LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForInfo, vm == nullptr";
738         return nullptr;
739     }
740     CpuProfiler *profiler = vm->GetProfiler();
741     if (profiler == nullptr) {
742         LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForInfo, profiler == nullptr";
743         return nullptr;
744     }
745     std::unique_ptr<ProfileInfo> profileInfo;
746     bool result = profiler->StopCpuProfilerForInfo(profileInfo);
747     if (!result) {
748         LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForInfo failed";
749         return nullptr;
750     }
751     delete profiler;
752     profiler = nullptr;
753     const_cast<EcmaVM *>(vm)->SetProfiler(nullptr);
754     return profileInfo;
755 #else
756     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
757     return nullptr;
758 #endif
759 }
760 
SetCpuSamplingInterval([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int interval)761 void DFXJSNApi::SetCpuSamplingInterval([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int interval)
762 {
763 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
764     if (interval < 0) {
765         LOG_ECMA(ERROR) << "Sampling interval is illegal";
766         return;
767     }
768     LOG_ECMA(INFO) << "SetCpuProfilerSamplingInterval, Sampling interval is: " << interval;
769     if (vm == nullptr) {
770         return;
771     }
772     CpuProfiler *profiler = vm->GetProfiler();
773     if (profiler == nullptr) {
774         profiler = new CpuProfiler(vm, interval);
775         const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
776         return;
777     }
778     profiler->SetCpuSamplingInterval(interval);
779 #else
780     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
781 #endif
782 }
783 
EnableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM, int32_t threshold)784 void DFXJSNApi::EnableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM, int32_t threshold)
785 {
786     ecmaVM->GetJsDebuggerManager()->EnableSerializationTimeoutCheck();
787     ecmaVM->GetJsDebuggerManager()->SetSerializationCheckThreshold(threshold);
788 }
789 
DisableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM)790 void DFXJSNApi::DisableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM)
791 {
792     ecmaVM->GetJsDebuggerManager()->DisableSerializationTimeoutCheck();
793 }
794 
SuspendVM([[maybe_unused]] const EcmaVM *vm)795 bool DFXJSNApi::SuspendVM([[maybe_unused]] const EcmaVM *vm)
796 {
797 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
798     ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
799     return vmThreadControl->NotifyVMThreadSuspension();
800 #else
801     LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
802     return false;
803 #endif
804 }
805 
ResumeVM([[maybe_unused]] const EcmaVM *vm)806 void DFXJSNApi::ResumeVM([[maybe_unused]] const EcmaVM *vm)
807 {
808 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
809     ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
810     vmThreadControl->ResumeVM();
811 #else
812     LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
813 #endif
814 }
815 
IsSuspended([[maybe_unused]] const EcmaVM *vm)816 bool DFXJSNApi::IsSuspended([[maybe_unused]] const EcmaVM *vm)
817 {
818 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
819     ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
820     return vmThreadControl->IsSuspended();
821 #else
822     LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
823     return false;
824 #endif
825 }
826 
TerminateExecution(const EcmaVM *vm)827 void DFXJSNApi::TerminateExecution(const EcmaVM *vm)
828 {
829     ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
830     vmThreadControl->RequestTerminateExecution();
831 }
832 
CheckSafepoint([[maybe_unused]] const EcmaVM *vm)833 bool DFXJSNApi::CheckSafepoint([[maybe_unused]] const EcmaVM *vm)
834 {
835 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
836     ecmascript::JSThread* thread = vm->GetJSThread();
837     return thread->CheckSafepoint();
838 #else
839     LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
840     return false;
841 #endif
842 }
843 
BuildJsStackInfoList(const EcmaVM *hostVm, uint32_t tid, std::vector<JsFrameInfo>& jsFrames)844 bool DFXJSNApi::BuildJsStackInfoList(const EcmaVM *hostVm, uint32_t tid, std::vector<JsFrameInfo>& jsFrames)
845 {
846     EcmaVM *vm;
847     if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
848         vm = const_cast<EcmaVM*>(hostVm);
849     } else {
850         vm = const_cast<EcmaVM*>(hostVm)->GetWorkerVm(tid);
851         if (vm == nullptr) {
852             return false;
853         }
854     }
855     jsFrames = ecmascript::JsStackInfo::BuildJsStackInfo(vm->GetAssociatedJSThread());
856     if (jsFrames.size() > 0) {
857         return true;
858     }
859     return false;
860 }
861 
GetObjectHash(const EcmaVM *vm, Local<JSValueRef> nativeObject)862 int32_t DFXJSNApi::GetObjectHash(const EcmaVM *vm, Local<JSValueRef> nativeObject)
863 {
864     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(nativeObject);
865     return ecmascript::tooling::DebuggerApi::GetObjectHash(vm, obj);
866 }
867 
StartSampling([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] uint64_t samplingInterval)868 bool DFXJSNApi::StartSampling([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] uint64_t samplingInterval)
869 {
870 #if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
871     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
872         const_cast<EcmaVM *>(vm));
873     return heapProfile->StartHeapSampling(samplingInterval);
874 #else
875     LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
876     return false;
877 #endif
878 }
879 
GetAllocationProfile([[maybe_unused]] const EcmaVM *vm)880 const SamplingInfo *DFXJSNApi::GetAllocationProfile([[maybe_unused]] const EcmaVM *vm)
881 {
882 #if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
883     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
884         const_cast<EcmaVM *>(vm));
885     return heapProfile->GetAllocationProfile();
886 #else
887     LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
888     return nullptr;
889 #endif
890 }
891 
StopSampling([[maybe_unused]] const EcmaVM *vm)892 void DFXJSNApi::StopSampling([[maybe_unused]] const EcmaVM *vm)
893 {
894 #if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
895     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
896         const_cast<EcmaVM *>(vm));
897     heapProfile->StopHeapSampling();
898 #else
899     LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
900 #endif
901 }
902 
903 // release or debug hap : aa start -p 'dumpheap'
904 //                        aa start -p 'profile'
StartProfiler(EcmaVM *vm, const ProfilerOption &option, int tid, int32_t instanceId, const DebuggerPostTask &debuggerPostTask, bool isDebugApp)905 bool DFXJSNApi::StartProfiler(EcmaVM *vm, const ProfilerOption &option, int tid,
906                               int32_t instanceId, const DebuggerPostTask &debuggerPostTask, bool isDebugApp)
907 {
908     LOG_ECMA(INFO) << "DFXJSNApi::StartProfiler, type = " << (int)option.profilerType
909         << ", tid = " << tid << ", isDebugApp = " << isDebugApp;
910     JSNApi::DebugOption debugOption;
911     debugOption.libraryPath = option.libraryPath;
912     if (option.profilerType == ProfilerType::CPU_PROFILER) {
913         debugOption.isDebugMode = false;
914         if (JSNApi::NotifyDebugMode(tid, vm, debugOption, instanceId, debuggerPostTask, isDebugApp)) {
915             return StartCpuProfilerForInfo(vm, option.interval);
916         } else {
917             LOG_ECMA(ERROR) << "DFXJSNApi::StartProfiler, NotifyDebugMode failed";
918             return false;
919         }
920     } else {
921         debugOption.isDebugMode = true;
922         return JSNApi::NotifyDebugMode(tid, vm, debugOption, instanceId, debuggerPostTask, isDebugApp);
923     }
924 }
925 
ResumeVMById(EcmaVM *hostVm, uint32_t tid)926 void DFXJSNApi::ResumeVMById(EcmaVM *hostVm, uint32_t tid)
927 {
928     if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
929         ResumeVM(hostVm);
930     } else {
931         hostVm->ResumeWorkerVm(tid);
932     }
933 }
934 
SuspendVMById(EcmaVM *hostVm, uint32_t tid)935 bool DFXJSNApi::SuspendVMById(EcmaVM *hostVm, uint32_t tid)
936 {
937     bool success = false;
938     if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
939         success = SuspendVM(hostVm);
940         LOG_ECMA(INFO) << "The main thread, SuspendVMById succeeded: " << success;
941         return success;
942     } else {
943         success = hostVm->SuspendWorkerVm(tid);
944         LOG_ECMA(INFO) << "The worker thread, SuspendVMById succeeded: " << success;
945         return success;
946     }
947 }
948 
StartTracing([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] std::string &categories)949 bool DFXJSNApi::StartTracing([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] std::string &categories)
950 {
951 #if defined(ECMASCRIPT_SUPPORT_TRACING)
952     if (vm == nullptr) {
953         return false;
954     }
955     Tracing *tracing = vm->GetTracing();
956     if (tracing == nullptr) {
957         tracing = new Tracing(vm);
958         const_cast<EcmaVM *>(vm)->SetTracing(tracing);
959     }
960     tracing->StartTracing(categories);
961     return true;
962 #else
963     LOG_ECMA(ERROR) << "Not support arkcompiler tracing";
964     return false;
965 #endif
966 }
967 
StopTracing([[maybe_unused]] const EcmaVM *vm)968 std::unique_ptr<std::vector<TraceEvent>> DFXJSNApi::StopTracing([[maybe_unused]] const EcmaVM *vm)
969 {
970 #if defined(ECMASCRIPT_SUPPORT_TRACING)
971     if (vm == nullptr) {
972         return nullptr;
973     }
974     Tracing *tracing = vm->GetTracing();
975     if (tracing == nullptr) {
976         LOG_ECMA(ERROR) << "StopTracing tracing is nullptr";
977         return nullptr;
978     }
979     auto traceEvents = tracing->StopTracing();
980     if (traceEvents == nullptr) {
981         LOG_ECMA(ERROR) << "trace events is nullptr";
982     }
983     delete tracing;
984     tracing = nullptr;
985     const_cast<EcmaVM *>(vm)->SetTracing(nullptr);
986     return traceEvents;
987 #else
988     LOG_ECMA(ERROR) << "Not support arkcompiler tracing";
989     return nullptr;
990 #endif
991 }
992 
GetTracingBufferUseage([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] double &percentFull, [[maybe_unused]] uint32_t &eventCount, [[maybe_unused]] double &value)993 void DFXJSNApi::GetTracingBufferUseage([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] double &percentFull,
994                                        [[maybe_unused]] uint32_t &eventCount, [[maybe_unused]] double &value)
995 {
996 #if defined(ECMASCRIPT_SUPPORT_TRACING)
997     if (vm == nullptr) {
998         return;
999     }
1000     ecmascript::Tracing *tracing = vm->GetTracing();
1001     if (tracing == nullptr) {
1002         LOG_ECMA(ERROR) << "GetTracingBufferUseage tracing is nullptr";
1003     } else {
1004         tracing->GetBufferUseage(percentFull, eventCount, value);
1005     }
1006 #else
1007     LOG_ECMA(ERROR) << "Not support arkcompiler tracing";
1008 #endif
1009 }
1010 
TranslateJSStackInfo(const EcmaVM *vm, std::string &url, int32_t &line, int32_t &column)1011 void DFXJSNApi::TranslateJSStackInfo(const EcmaVM *vm, std::string &url, int32_t &line, int32_t &column)
1012 {
1013     auto cb = vm->GetSourceMapTranslateCallback();
1014     if (cb == nullptr) {
1015         LOG_ECMA(ERROR) << "Translate failed, callback function is nullptr.";
1016     } else if (!cb(url, line, column)) {
1017         LOG_ECMA(ERROR) << "Translate failed, url: " << url;
1018     }
1019 }
1020 
GetCurrentThreadId()1021 uint32_t DFXJSNApi::GetCurrentThreadId()
1022 {
1023     return JSThread::GetCurrentThreadId();
1024 }
1025 } // namespace panda
1026