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