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