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