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/base/config.h"
20 #include "ecmascript/builtins/builtins_ark_tools.h"
21 #include "ecmascript/checkpoint/thread_state_transition.h"
22 #include "common_components/mutator/mutator_manager.h"
23 #include "ecmascript/debugger/debugger_api.h"
24 #include "ecmascript/debugger/js_debugger_manager.h"
25 #include "ecmascript/dfx/hprof/heap_profiler.h"
26 #include "ecmascript/dfx/stackinfo/async_stack_trace.h"
27 #include "ecmascript/dfx/stackinfo/js_stackinfo.h"
28 #include "ecmascript/dfx/tracing/tracing.h"
29 #include "ecmascript/dfx/vm_thread_control.h"
30 #include "ecmascript/jit/jit.h"
31 #include "ecmascript/jspandafile/js_pandafile_executor.h"
32 #include "ecmascript/mem/heap-inl.h"
33 #include "ecmascript/ohos/ohos_constants.h"
34
35 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
36 #include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
37 #include "ecmascript/dfx/cpu_profiler/samples_record.h"
38 #endif
39 #if defined(ENABLE_DUMP_IN_FAULTLOG)
40 #include "faultloggerd_client.h"
41 #include "uv.h"
42 #endif
43
44 namespace panda {
45 using ecmascript::CString;
46 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
47 using BuiltinsArkTools = ecmascript::builtins::BuiltinsArkTools;
48 using ecmascript::CpuProfiler;
49 #endif
50 using ecmascript::EcmaString;
51 using ecmascript::JSTaggedValue;
52 using ecmascript::GCStats;
53 template<typename T>
54 using JSHandle = ecmascript::JSHandle<T>;
55 using ecmascript::FileStream;
56 using ecmascript::FileDescriptorStream;
57 using ecmascript::CMap;
58 using ecmascript::Tracing;
59 using ecmascript::DumpSnapShotOption;
60 using ecmascript::g_isEnableCMCGC;
61 using ecmascript::JSFunction;
62 using ecmascript::JSPandaFileExecutor;
63 using ecmascript::SourceTextModule;
64
65 sem_t g_heapdumpCnt;
66
DumpHeapSnapshot(const EcmaVM * vm,const std::string & path,const DumpSnapShotOption & dumpOption,const std::function<void (uint8_t)> & callback)67 void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const std::string &path,
68 [[maybe_unused]] const DumpSnapShotOption &dumpOption,
69 const std::function<void(uint8_t)> &callback)
70 {
71 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
72 FileStream stream(path);
73 DumpHeapSnapshot(vm, &stream, dumpOption, nullptr, callback);
74 #else
75 if (callback) {
76 callback(static_cast<uint8_t>(ecmascript::DumpHeapSnapshotStatus::FORK_FAILED));
77 }
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()->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
248 // tid = 0: TriggerGC all vm; tid != 0: TriggerGC tid vm
TriggerGC(const EcmaVM * vm,uint32_t tid)249 void DFXJSNApi::TriggerGC([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] uint32_t tid)
250 {
251 if (vm->IsWorkerThread()) {
252 LOG_ECMA(ERROR) << "this is a workthread!";
253 return;
254 }
255 // triggerGC host vm
256 uint32_t curTid = vm->GetTid();
257 LOG_ECMA(INFO) << "TriggerGC tid " << tid << " curTid " << curTid;
258 if (tid == 0 || tid == curTid) {
259 TriggerGCWithVm(vm);
260 }
261 // triggerGC worker vm
262 const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
263 curTid = workerVm->GetTid();
264 LOG_ECMA(INFO) << "TriggerGC tid " << tid << " curTid " << curTid;
265 if (tid == 0 || tid == curTid) {
266 TriggerGCWithVm(workerVm);
267 return;
268 }
269 });
270 // triggerSharedFullGC
271 TriggerSharedGCWithVm(vm);
272 }
273
TriggerSharedGCWithVm(const EcmaVM * vm)274 void DFXJSNApi::TriggerSharedGCWithVm([[maybe_unused]] const EcmaVM *vm)
275 {
276 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
277 #if defined(ENABLE_DUMP_IN_FAULTLOG)
278 uv_loop_t *loop = reinterpret_cast<uv_loop_t *>(vm->GetLoop());
279 if (loop == nullptr) {
280 LOG_ECMA(ERROR) << "loop nullptr";
281 return;
282 }
283 if (uv_loop_alive(loop) == 0) {
284 LOG_ECMA(ERROR) << "uv_loop_alive dead";
285 return;
286 }
287 uv_work_t *work = new(std::nothrow) uv_work_t;
288 if (work == nullptr) {
289 LOG_ECMA(FATAL) << "DFXJSNApi::TriggerGCWithVm:work is nullptr";
290 return;
291 }
292 work->data = static_cast<void *>(const_cast<EcmaVM *>(vm));
293 int ret = uv_queue_work(loop, work, [](uv_work_t *) {}, [](uv_work_t *work, int32_t) {
294 EcmaVM *vm = static_cast<EcmaVM *>(work->data);
295 ecmascript::SharedHeap* sHeap = ecmascript::SharedHeap::GetInstance();
296 JSThread *thread = vm->GetJSThread();
297 ecmascript::ThreadManagedScope managedScope(thread);
298 sHeap->CollectGarbage<ecmascript::TriggerGCType::SHARED_FULL_GC,
299 ecmascript::GCReason::TRIGGER_BY_MEM_TOOLS>(thread);
300 delete work;
301 });
302 if (ret != 0) {
303 LOG_ECMA(ERROR) << "uv_queue_work fail ret " << ret;
304 delete work;
305 }
306 #endif
307 #endif
308 }
309
TriggerGCWithVm(const EcmaVM * vm)310 void DFXJSNApi::TriggerGCWithVm([[maybe_unused]] const EcmaVM *vm)
311 {
312 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
313 #if defined(ENABLE_DUMP_IN_FAULTLOG)
314 uv_loop_t *loop = reinterpret_cast<uv_loop_t *>(vm->GetLoop());
315 if (loop == nullptr) {
316 LOG_ECMA(ERROR) << "loop nullptr";
317 return;
318 }
319 if (uv_loop_alive(loop) == 0) {
320 LOG_ECMA(ERROR) << "uv_loop_alive dead";
321 return;
322 }
323 uv_work_t *work = new(std::nothrow) uv_work_t;
324 if (work == nullptr) {
325 LOG_ECMA(FATAL) << "DFXJSNApi::TriggerGCWithVm:work is nullptr";
326 return;
327 }
328 work->data = static_cast<void *>(const_cast<EcmaVM *>(vm));
329 int ret = uv_queue_work(loop, work, [](uv_work_t *) {}, [](uv_work_t *work, int32_t) {
330 EcmaVM *vm = static_cast<EcmaVM *>(work->data);
331 ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
332 vm->CollectGarbage(ecmascript::TriggerGCType::FULL_GC, ecmascript::GCReason::TRIGGER_BY_MEM_TOOLS);
333 delete work;
334 });
335 if (ret != 0) {
336 LOG_ECMA(ERROR) << "uv_queue_work fail ret " << ret;
337 delete work;
338 }
339 #endif
340 #endif
341 }
342
DestroyHeapProfiler(const EcmaVM * vm)343 void DFXJSNApi::DestroyHeapProfiler([[maybe_unused]] const EcmaVM *vm)
344 {
345 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
346 ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
347 ecmascript::HeapProfilerInterface::Destroy(const_cast<EcmaVM *>(vm));
348 #else
349 LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
350 #endif
351 }
352
BuildNativeAndJsStackTrace(const EcmaVM * vm,std::string & stackTraceStr)353 bool DFXJSNApi::BuildNativeAndJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr)
354 {
355 stackTraceStr = ecmascript::JsStackInfo::BuildJsStackTrace(vm->GetAssociatedJSThread(), true);
356 if (stackTraceStr.empty()) {
357 return false;
358 }
359 return true;
360 }
361
BuildJsStackTrace(const EcmaVM * vm,std::string & stackTraceStr)362 bool DFXJSNApi::BuildJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr)
363 {
364 JSThread *thread = vm->GetAssociatedJSThread();
365 ecmascript::ThreadManagedScope managedScope(thread);
366 bool needUnbindMutator = false;
367 if (g_isEnableCMCGC) {
368 common::Mutator *mutator = reinterpret_cast<common::Mutator *>(thread->GetThreadHolder()->GetMutator());
369 needUnbindMutator = common::BaseRuntime::GetInstance()->GetMutatorManager().BindMutatorOnly(mutator);
370 }
371 stackTraceStr = ecmascript::JsStackInfo::BuildJsStackTrace(thread, false);
372 if (needUnbindMutator) {
373 common::BaseRuntime::GetInstance()->GetMutatorManager().UnbindMutatorOnly();
374 }
375 if (stackTraceStr.empty()) {
376 return false;
377 }
378 return true;
379 }
380
StartHeapTracking(const EcmaVM * vm,double timeInterval,bool isVmMode,Stream * stream,bool traceAllocation,bool newThread)381 bool DFXJSNApi::StartHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] double timeInterval,
382 [[maybe_unused]] bool isVmMode, [[maybe_unused]] Stream *stream,
383 [[maybe_unused]] bool traceAllocation, [[maybe_unused]] bool newThread)
384 {
385 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
386 ecmascript::base::BlockHookScope blockScope;
387 ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
388 ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
389 const_cast<EcmaVM *>(vm));
390 return heapProfile->StartHeapTracking(timeInterval, isVmMode, stream, traceAllocation, newThread);
391 #else
392 LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
393 return false;
394 #endif
395 }
396
UpdateHeapTracking(const EcmaVM * vm,Stream * stream)397 bool DFXJSNApi::UpdateHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream *stream)
398 {
399 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
400 ecmascript::base::BlockHookScope blockScope;
401 ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
402 ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
403 const_cast<EcmaVM *>(vm));
404 return heapProfile->UpdateHeapTracking(stream);
405 #else
406 LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
407 return false;
408 #endif
409 }
410
StopHeapTracking(const EcmaVM * vm,const std::string & filePath,bool newThread)411 bool DFXJSNApi::StopHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const std::string &filePath,
412 [[maybe_unused]] bool newThread)
413 {
414 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
415 FileStream stream(filePath);
416 return StopHeapTracking(vm, &stream, nullptr, newThread);
417 #else
418 LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
419 return false;
420 #endif
421 }
422
StopHeapTracking(const EcmaVM * vm,Stream * stream,Progress * progress,bool newThread)423 bool DFXJSNApi::StopHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream* stream,
424 [[maybe_unused]] Progress *progress, [[maybe_unused]] bool newThread)
425 {
426 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
427 ecmascript::base::BlockHookScope blockScope;
428 ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
429 bool result = false;
430 ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
431 const_cast<EcmaVM *>(vm));
432 result = heapProfile->StopHeapTracking(stream, progress, newThread);
433 ecmascript::HeapProfilerInterface::Destroy(const_cast<EcmaVM *>(vm));
434 return result;
435 #else
436 LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
437 return false;
438 #endif
439 }
440
PrintStatisticResult(const EcmaVM * vm)441 void DFXJSNApi::PrintStatisticResult(const EcmaVM *vm)
442 {
443 ecmascript::GCStats gcstats(vm->GetHeap());
444 gcstats.PrintStatisticResult();
445 }
446
StartRuntimeStat(EcmaVM * vm)447 void DFXJSNApi::StartRuntimeStat(EcmaVM *vm)
448 {
449 vm->GetJSThread()->GetEcmaVM()->SetRuntimeStatEnable(true);
450 }
451
StopRuntimeStat(EcmaVM * vm)452 void DFXJSNApi::StopRuntimeStat(EcmaVM *vm)
453 {
454 vm->GetJSThread()->GetEcmaVM()->SetRuntimeStatEnable(false);
455 }
456
GetArrayBufferSizeForCMCGC()457 size_t GetArrayBufferSizeForCMCGC()
458 {
459 size_t result = 0;
460 auto visitor = [&result](common::BaseObject *obj) {
461 panda::ecmascript::JSTaggedValue entry = panda::ecmascript::JSTaggedValue(
462 reinterpret_cast<panda::ecmascript::JSTaggedType>(obj));
463 panda::ecmascript::TaggedObject *taggedObj = entry.GetTaggedObject();
464 panda::ecmascript::JSHClass* jsClass = taggedObj->GetClass();
465 result += jsClass->IsArrayBuffer() ? jsClass->GetObjectSize() : 0;
466 };
467 common::Heap::GetHeap().ForEachObject(visitor, true);
468 return result;
469 }
470
GetArrayBufferSize(const EcmaVM * vm)471 size_t DFXJSNApi::GetArrayBufferSize(const EcmaVM *vm)
472 {
473 if (g_isEnableCMCGC) {
474 return GetArrayBufferSizeForCMCGC();
475 }
476 ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
477 return vm->GetHeap()->GetArrayBufferSize();
478 }
479
GetHeapTotalSize(const EcmaVM * vm)480 size_t DFXJSNApi::GetHeapTotalSize(const EcmaVM *vm)
481 {
482 if (g_isEnableCMCGC) {
483 return common::Heap::GetHeap().GetCurrentCapacity();
484 }
485 return vm->GetHeap()->GetCommittedSize();
486 }
487
GetHeapUsedSize(const EcmaVM * vm)488 size_t DFXJSNApi::GetHeapUsedSize(const EcmaVM *vm)
489 {
490 if (g_isEnableCMCGC) {
491 return common::Heap::GetHeap().GetSurvivedSize();
492 }
493 ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
494 return vm->GetHeap()->GetLiveObjectSize();
495 }
496
GetHeapObjectSize(const EcmaVM * vm)497 size_t DFXJSNApi::GetHeapObjectSize(const EcmaVM *vm)
498 {
499 if (g_isEnableCMCGC) {
500 return common::Heap::GetHeap().GetAllocatedSize();
501 }
502 return vm->GetHeap()->GetHeapObjectSize();
503 }
504
GetHeapLimitSize(const EcmaVM * vm)505 size_t DFXJSNApi::GetHeapLimitSize(const EcmaVM *vm)
506 {
507 if (g_isEnableCMCGC) {
508 return common::Heap::GetHeap().GetMaxCapacity();
509 }
510 return vm->GetHeap()->GetHeapLimitSize();
511 }
512
GetProcessHeapLimitSize()513 size_t DFXJSNApi::GetProcessHeapLimitSize()
514 {
515 if (g_isEnableCMCGC) {
516 return common::Heap::GetHeap().GetMaxCapacity();
517 }
518 return ecmascript::MemMapAllocator::GetInstance()->GetCapacity();
519 }
520
GetGCCount(const EcmaVM * vm)521 size_t DFXJSNApi::GetGCCount(const EcmaVM *vm)
522 {
523 if (vm->IsWorkerThread()) {
524 return vm->GetEcmaGCStats()->GetGCCount();
525 }
526 return vm->GetEcmaGCStats()->GetGCCount() +
527 ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetGCCount();
528 }
529
GetGCDuration(const EcmaVM * vm)530 size_t DFXJSNApi::GetGCDuration(const EcmaVM *vm)
531 {
532 if (vm->IsWorkerThread()) {
533 return vm->GetEcmaGCStats()->GetGCDuration();
534 }
535 return vm->GetEcmaGCStats()->GetGCDuration() +
536 ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetGCDuration();
537 }
538
GetAccumulatedAllocateSize(const EcmaVM * vm)539 size_t DFXJSNApi::GetAccumulatedAllocateSize(const EcmaVM *vm)
540 {
541 if (g_isEnableCMCGC) {
542 return common::Heap::GetHeap().GetAccumulatedAllocateSize();
543 }
544 if (vm->IsWorkerThread()) {
545 return vm->GetEcmaGCStats()->GetAccumulatedAllocateSize();
546 }
547 return vm->GetEcmaGCStats()->GetAccumulatedAllocateSize() +
548 ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetAccumulatedAllocateSize();
549 }
550
GetAccumulatedFreeSize(const EcmaVM * vm)551 size_t DFXJSNApi::GetAccumulatedFreeSize(const EcmaVM *vm)
552 {
553 if (g_isEnableCMCGC) {
554 return common::Heap::GetHeap().GetAccumulatedFreeSize();
555 }
556 if (vm->IsWorkerThread()) {
557 return vm->GetEcmaGCStats()->GetAccumulatedFreeSize();
558 }
559 return vm->GetEcmaGCStats()->GetAccumulatedFreeSize() +
560 ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetAccumulatedFreeSize();
561 }
562
GetFullGCLongTimeCount(const EcmaVM * vm)563 size_t DFXJSNApi::GetFullGCLongTimeCount(const EcmaVM *vm)
564 {
565 return vm->GetEcmaGCStats()->GetFullGCLongTimeCount();
566 }
567
GetHeapPrepare(const EcmaVM * vm)568 void DFXJSNApi::GetHeapPrepare(const EcmaVM *vm)
569 {
570 ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
571 const_cast<ecmascript::Heap *>(vm->GetHeap())->GetHeapPrepare();
572 }
573
SetJsDumpThresholds(EcmaVM * vm,size_t thresholds)574 void DFXJSNApi::SetJsDumpThresholds([[maybe_unused]] EcmaVM *vm, [[maybe_unused]] size_t thresholds)
575 {
576 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT) && defined(PANDA_TARGET_OHOS) && defined(ENABLE_HISYSEVENT)
577 vm->GetHeap()->SetJsDumpThresholds(thresholds);
578 #else
579 LOG_ECMA(ERROR) << "Not support set jsdump thresholds";
580 #endif
581 }
582
SetAppFreezeFilterCallback(const EcmaVM * vm,AppFreezeFilterCallback cb)583 void DFXJSNApi::SetAppFreezeFilterCallback([[maybe_unused]] const EcmaVM *vm, AppFreezeFilterCallback cb)
584 {
585 if (ecmascript::Runtime::GetInstance()->GetAppFreezeFilterCallback() == nullptr && cb != nullptr) {
586 ecmascript::Runtime::GetInstance()->SetAppFreezeFilterCallback(cb);
587 }
588 }
589
NotifyApplicationState(EcmaVM * vm,bool inBackground)590 void DFXJSNApi::NotifyApplicationState(EcmaVM *vm, bool inBackground)
591 {
592 ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
593 const_cast<ecmascript::Heap *>(vm->GetHeap())->ChangeGCParams(inBackground);
594 ecmascript::Jit::GetInstance()->ChangeTaskPoolState(inBackground);
595 }
596
NotifyIdleStatusControl(const EcmaVM * vm,std::function<void (bool)> callback)597 void DFXJSNApi::NotifyIdleStatusControl(const EcmaVM *vm, std::function<void(bool)> callback)
598 {
599 const_cast<ecmascript::Heap *>(vm->GetHeap())->InitializeIdleStatusControl(callback);
600 }
601
NotifyIdleTime(const EcmaVM * vm,int idleMicroSec)602 void DFXJSNApi::NotifyIdleTime(const EcmaVM *vm, int idleMicroSec)
603 {
604 ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
605 const_cast<ecmascript::Heap *>(vm->GetHeap())->TriggerIdleCollection(idleMicroSec);
606 }
607
NotifyMemoryPressure(EcmaVM * vm,bool inHighMemoryPressure)608 void DFXJSNApi::NotifyMemoryPressure(EcmaVM *vm, bool inHighMemoryPressure)
609 {
610 const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyMemoryPressure(inHighMemoryPressure);
611 }
612
NotifyFinishColdStart(EcmaVM * vm,bool isConvinced)613 void DFXJSNApi::NotifyFinishColdStart(EcmaVM *vm, [[maybe_unused]] bool isConvinced)
614 {
615 ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
616 }
617
NotifyHighSensitive(EcmaVM * vm,bool isStart)618 void DFXJSNApi::NotifyHighSensitive(EcmaVM *vm, bool isStart)
619 {
620 const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyHighSensitive(isStart);
621 }
622
NotifyWarmStart(EcmaVM * vm)623 void DFXJSNApi::NotifyWarmStart(EcmaVM *vm)
624 {
625 LOG_ECMA(INFO) << "SmartGC: app warm start gc";
626 ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
627 if (AllowWarmStartGcRestrain(vm)) {
628 const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyWarmStartup();
629 }
630 }
631
AllowWarmStartGcRestrain(EcmaVM * vm)632 bool DFXJSNApi::AllowWarmStartGcRestrain(EcmaVM *vm)
633 {
634 common::GCPhase gcPhase = vm->GetJSThread()->GetCMCGCPhase();
635 if (gcPhase > common::GCPhase::GC_PHASE_IDLE) {
636 LOG_ECMA(WARN) << "SmartGC: app warm start gc, but gc phase more than GC_PHASE_IDLE, skip";
637 return false;
638 }
639
640 bool hasFinishedMark = vm->GetJSThread()->IsConcurrentMarkingOrFinished();
641 if (hasFinishedMark) {
642 LOG_ECMA(WARN) << "SmartGC: app warm start gc, but gc mark is concurrent marking or finished, skip";
643 return false;
644 }
645 ecmascript::StartupStatus status = const_cast<ecmascript::Heap *>(vm->GetHeap())->GetStartupStatus();
646 bool isGcRestraining = (status == ecmascript::StartupStatus::ON_STARTUP ||
647 status == ecmascript::StartupStatus::JUST_FINISH_STARTUP);
648 if (isGcRestraining) {
649 LOG_ECMA(WARN) << "SmartGC: app warm start gc, but it is already in GC restraining now, skip";
650 return false;
651 }
652 return true;
653 }
654
StopCpuProfilerForColdStart(const EcmaVM * vm)655 bool DFXJSNApi::StopCpuProfilerForColdStart([[maybe_unused]] const EcmaVM *vm)
656 {
657 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
658 bool success = false;
659 auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
660 if (options.EnableCpuProfilerColdStartMainThread()) {
661 success = true;
662 DFXJSNApi::StopCpuProfilerForFile(vm);
663 }
664
665 if (options.EnableCpuProfilerColdStartWorkerThread()) {
666 success = true;
667 const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
668 if (workerVm->GetJSThread()->GetIsProfiling()) {
669 DFXJSNApi::StopCpuProfilerForFile(workerVm);
670 }
671 });
672 }
673
674 return success;
675 #else
676 LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
677 return false;
678 #endif
679 }
680
681 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
CpuProfilerAnyTimeMainThread(const EcmaVM * vm)682 void DFXJSNApi::CpuProfilerAnyTimeMainThread(const EcmaVM *vm)
683 {
684 const uint8_t KILL_COUNT_FACTOR = 2;
685 if (killCount % KILL_COUNT_FACTOR == 0) {
686 uint8_t fileCount = killCount / KILL_COUNT_FACTOR + 1;
687 LOG_ECMA(INFO) << "Start CpuProfiler Any Time Main Thread, killCount = " << killCount;
688 std::string fileName = ConvertToStdString(const_cast<EcmaVM *>(vm)->GetBundleName())
689 + "_" + std::to_string(fileCount) + ".cpuprofile";
690 if (!BuiltinsArkTools::CreateFile(fileName)) {
691 LOG_ECMA(ERROR) << "createFile failed " << fileName;
692 } else {
693 DFXJSNApi::StartCpuProfilerForFile(vm, fileName, CpuProfiler::INTERVAL_OF_INNER_START);
694 }
695 } else {
696 LOG_ECMA(INFO) << "Stop CpuProfiler Any Time Main Thread, killCount = " << killCount;
697 if (vm->GetJSThread()->GetIsProfiling()) {
698 DFXJSNApi::StopCpuProfilerForFile(vm);
699 }
700 }
701 }
702 #endif
703
CpuProfilerSamplingAnyTime(const EcmaVM * vm)704 bool DFXJSNApi::CpuProfilerSamplingAnyTime([[maybe_unused]] const EcmaVM *vm)
705 {
706 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
707 (void)killCount;
708 bool success = false;
709 const uint8_t KILL_COUNT_FACTOR = 2;
710 auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
711 if (options.EnableCpuProfilerAnyTimeMainThread()) {
712 success = true;
713 CpuProfilerAnyTimeMainThread(vm);
714 }
715
716 if (options.EnableCpuProfilerAnyTimeWorkerThread()) {
717 success = true;
718 if (killCount % KILL_COUNT_FACTOR == 0) {
719 uint8_t fileCount = killCount / KILL_COUNT_FACTOR + 1;
720 LOG_ECMA(INFO) << "Start CpuProfiler Any Time Worker Thread, killCount = " << killCount;
721 const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
722 auto *thread = workerVm->GetAssociatedJSThread();
723 std::string fileName = ConvertToStdString(workerVm->GetBundleName()) + "_"
724 + std::to_string(thread->GetThreadId()) + "_"
725 + std::to_string(fileCount) + ".cpuprofile";
726 if (!BuiltinsArkTools::CreateFile(fileName)) {
727 LOG_ECMA(ERROR) << "createFile failed " << fileName;
728 } else {
729 thread->SetCpuProfileName(fileName);
730 thread->SetNeedProfiling(true);
731 }
732 });
733 } else {
734 LOG_ECMA(INFO) << "Stop CpuProfiler Any Time Worker Thread, killCount = " << killCount;
735 const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
736 auto *thread = workerVm->GetAssociatedJSThread();
737 if (thread->GetIsProfiling()) {
738 DFXJSNApi::StopCpuProfilerForFile(workerVm);
739 }
740 thread->SetNeedProfiling(false);
741 });
742 }
743 }
744
745 return success;
746 #else
747 LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
748 return false;
749 #endif
750 }
751
StartCpuProfilerForFile(const EcmaVM * vm,const std::string & fileName,int interval)752 bool DFXJSNApi::StartCpuProfilerForFile([[maybe_unused]] const EcmaVM *vm,
753 [[maybe_unused]] const std::string &fileName,
754 [[maybe_unused]] int interval)
755 {
756 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
757 LOG_ECMA(INFO) << "DFXJSNApi::StartCpuProfilerForFile, vm = " << vm;
758 if (interval <= 0) {
759 LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForFile, interval <= 0";
760 return false;
761 }
762 if (vm == nullptr) {
763 LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForFile, vm == nullptr";
764 return false;
765 }
766 CpuProfiler *profiler = vm->GetProfiler();
767 if (profiler == nullptr) {
768 profiler = new CpuProfiler(vm, interval);
769 const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
770 }
771 return profiler->StartCpuProfilerForFile(fileName);
772 #else
773 LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForFile, not support cpu profiler";
774 return false;
775 #endif
776 }
777
StopCpuProfilerForFile(const EcmaVM * vm)778 void DFXJSNApi::StopCpuProfilerForFile([[maybe_unused]] const EcmaVM *vm)
779 {
780 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
781 LOG_ECMA(INFO) << "DFXJSNApi::StopCpuProfilerForFile, vm = " << vm;
782 if (vm == nullptr) {
783 LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForFile, vm == nullptr";
784 return;
785 }
786 CpuProfiler *profiler = vm->GetProfiler();
787 if (profiler == nullptr) {
788 LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForFile, profiler == nullptr";
789 return;
790 }
791 bool result = profiler->StopCpuProfilerForFile();
792 if (!result) {
793 LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForFile failed";
794 return;
795 }
796 delete profiler;
797 profiler = nullptr;
798 const_cast<EcmaVM *>(vm)->SetProfiler(nullptr);
799 #else
800 LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
801 #endif
802 }
803
StartCpuProfilerForInfo(const EcmaVM * vm,int interval)804 bool DFXJSNApi::StartCpuProfilerForInfo([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int interval)
805 {
806 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
807 LOG_ECMA(INFO) << "DFXJSNApi::StartCpuProfilerForInfo, vm = " << vm;
808 if (interval <= 0) {
809 LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForInfo, interval <= 0";
810 return false;
811 }
812 if (vm == nullptr) {
813 LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForInfo, vm == nullptr";
814 return false;
815 }
816 CpuProfiler *profiler = vm->GetProfiler();
817 if (profiler == nullptr) {
818 profiler = new CpuProfiler(vm, interval);
819 const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
820 }
821 return profiler->StartCpuProfilerForInfo();
822 #else
823 LOG_ECMA(ERROR) << "DFXJSNApi::StartCpuProfilerForInfo, not support cpu profiler";
824 return false;
825 #endif
826 }
827
StopCpuProfilerForInfo(const EcmaVM * vm)828 std::unique_ptr<ProfileInfo> DFXJSNApi::StopCpuProfilerForInfo([[maybe_unused]] const EcmaVM *vm)
829 {
830 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
831 LOG_ECMA(INFO) << "DFXJSNApi::StopCpuProfilerForInfo, vm = " << vm;
832 if (vm == nullptr) {
833 LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForInfo, vm == nullptr";
834 return nullptr;
835 }
836 CpuProfiler *profiler = vm->GetProfiler();
837 if (profiler == nullptr) {
838 LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForInfo, profiler == nullptr";
839 return nullptr;
840 }
841 std::unique_ptr<ProfileInfo> profileInfo;
842 bool result = profiler->StopCpuProfilerForInfo(profileInfo);
843 if (!result) {
844 LOG_ECMA(ERROR) << "DFXJSNApi::StopCpuProfilerForInfo failed";
845 return nullptr;
846 }
847 delete profiler;
848 profiler = nullptr;
849 const_cast<EcmaVM *>(vm)->SetProfiler(nullptr);
850 return profileInfo;
851 #else
852 LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
853 return nullptr;
854 #endif
855 }
856
SetCpuSamplingInterval(const EcmaVM * vm,int interval)857 void DFXJSNApi::SetCpuSamplingInterval([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int interval)
858 {
859 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
860 if (interval < 0) {
861 LOG_ECMA(ERROR) << "Sampling interval is illegal";
862 return;
863 }
864 LOG_ECMA(INFO) << "SetCpuProfilerSamplingInterval, Sampling interval is: " << interval;
865 if (vm == nullptr) {
866 return;
867 }
868 CpuProfiler *profiler = vm->GetProfiler();
869 if (profiler == nullptr) {
870 profiler = new CpuProfiler(vm, interval);
871 const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
872 return;
873 }
874 profiler->SetCpuSamplingInterval(interval);
875 #else
876 LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
877 #endif
878 }
879
EnableSeriliazationTimeoutCheck(const EcmaVM * ecmaVM,int32_t threshold)880 void DFXJSNApi::EnableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM, int32_t threshold)
881 {
882 ecmaVM->GetJsDebuggerManager()->EnableSerializationTimeoutCheck();
883 ecmaVM->GetJsDebuggerManager()->SetSerializationCheckThreshold(threshold);
884 }
885
DisableSeriliazationTimeoutCheck(const EcmaVM * ecmaVM)886 void DFXJSNApi::DisableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM)
887 {
888 ecmaVM->GetJsDebuggerManager()->DisableSerializationTimeoutCheck();
889 }
890
SuspendVM(const EcmaVM * vm)891 bool DFXJSNApi::SuspendVM([[maybe_unused]] const EcmaVM *vm)
892 {
893 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
894 ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
895 return vmThreadControl->NotifyVMThreadSuspension();
896 #else
897 LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
898 return false;
899 #endif
900 }
901
ResumeVM(const EcmaVM * vm)902 void DFXJSNApi::ResumeVM([[maybe_unused]] const EcmaVM *vm)
903 {
904 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
905 ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
906 vmThreadControl->ResumeVM();
907 #else
908 LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
909 #endif
910 }
911
IsSuspended(const EcmaVM * vm)912 bool DFXJSNApi::IsSuspended([[maybe_unused]] const EcmaVM *vm)
913 {
914 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
915 ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
916 return vmThreadControl->IsSuspended();
917 #else
918 LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
919 return false;
920 #endif
921 }
922
TerminateExecution(const EcmaVM * vm)923 void DFXJSNApi::TerminateExecution(const EcmaVM *vm)
924 {
925 ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
926 vmThreadControl->RequestTerminateExecution();
927 }
928
CheckSafepoint(const EcmaVM * vm)929 bool DFXJSNApi::CheckSafepoint([[maybe_unused]] const EcmaVM *vm)
930 {
931 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
932 ecmascript::JSThread* thread = vm->GetJSThread();
933 return thread->CheckSafepoint();
934 #else
935 LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
936 return false;
937 #endif
938 }
939
BuildJsStackInfoList(const EcmaVM * hostVm,uint32_t tid,std::vector<JsFrameInfo> & jsFrames)940 bool DFXJSNApi::BuildJsStackInfoList(const EcmaVM *hostVm, uint32_t tid, std::vector<JsFrameInfo>& jsFrames)
941 {
942 EcmaVM *vm;
943 if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
944 vm = const_cast<EcmaVM*>(hostVm);
945 } else {
946 vm = const_cast<EcmaVM*>(hostVm)->GetWorkerVm(tid);
947 if (vm == nullptr) {
948 return false;
949 }
950 }
951 jsFrames = ecmascript::JsStackInfo::BuildJsStackInfo(vm->GetAssociatedJSThread());
952 if (jsFrames.size() > 0) {
953 return true;
954 }
955 return false;
956 }
957
958 //When some objects invoke GetObjectHash, the return result is 0.
959 //The GetObjectHashCode function is added to rectify the fault.
GetObjectHash(const EcmaVM * vm,Local<JSValueRef> nativeObject)960 int32_t DFXJSNApi::GetObjectHash(const EcmaVM *vm, Local<JSValueRef> nativeObject)
961 {
962 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(nativeObject);
963 return ecmascript::tooling::DebuggerApi::GetObjectHash(vm, obj);
964 }
965
GetObjectHashCode(const EcmaVM * vm,Local<JSValueRef> nativeObject)966 int32_t DFXJSNApi::GetObjectHashCode(const EcmaVM *vm, Local<JSValueRef> nativeObject)
967 {
968 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(nativeObject);
969 return ecmascript::tooling::DebuggerApi::GetObjectHashCode(vm, obj);
970 }
971
StartSampling(const EcmaVM * vm,uint64_t samplingInterval)972 bool DFXJSNApi::StartSampling([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] uint64_t samplingInterval)
973 {
974 #if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
975 ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
976 const_cast<EcmaVM *>(vm));
977 return heapProfile->StartHeapSampling(samplingInterval);
978 #else
979 LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
980 return false;
981 #endif
982 }
983
GetAllocationProfile(const EcmaVM * vm)984 const SamplingInfo *DFXJSNApi::GetAllocationProfile([[maybe_unused]] const EcmaVM *vm)
985 {
986 #if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
987 ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
988 const_cast<EcmaVM *>(vm));
989 return heapProfile->GetAllocationProfile();
990 #else
991 LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
992 return nullptr;
993 #endif
994 }
995
StopSampling(const EcmaVM * vm)996 void DFXJSNApi::StopSampling([[maybe_unused]] const EcmaVM *vm)
997 {
998 #if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
999 ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
1000 const_cast<EcmaVM *>(vm));
1001 heapProfile->StopHeapSampling();
1002 #else
1003 LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
1004 #endif
1005 }
1006
1007 // release or debug hap : aa start -p 'dumpheap'
1008 // aa start -p 'profile'
StartProfiler(EcmaVM * vm,const ProfilerOption & option,int tid,int32_t instanceId,const DebuggerPostTask & debuggerPostTask,bool isDebugApp)1009 bool DFXJSNApi::StartProfiler(EcmaVM *vm, const ProfilerOption &option, int tid,
1010 int32_t instanceId, const DebuggerPostTask &debuggerPostTask, bool isDebugApp)
1011 {
1012 LOG_ECMA(INFO) << "DFXJSNApi::StartProfiler, type = " << (int)option.profilerType
1013 << ", tid = " << tid << ", isDebugApp = " << isDebugApp;
1014 JSNApi::DebugOption debugOption;
1015 debugOption.libraryPath = option.libraryPath;
1016 if (option.profilerType == ProfilerType::CPU_PROFILER) {
1017 debugOption.isDebugMode = false;
1018 if (JSNApi::NotifyDebugMode(tid, vm, debugOption, instanceId, debuggerPostTask, isDebugApp)) {
1019 return StartCpuProfilerForInfo(vm, option.interval);
1020 } else {
1021 LOG_ECMA(ERROR) << "DFXJSNApi::StartProfiler, NotifyDebugMode failed";
1022 return false;
1023 }
1024 } else {
1025 debugOption.isDebugMode = true;
1026 return JSNApi::NotifyDebugMode(tid, vm, debugOption, instanceId, debuggerPostTask, isDebugApp);
1027 }
1028 }
1029
ResumeVMById(EcmaVM * hostVm,uint32_t tid)1030 void DFXJSNApi::ResumeVMById(EcmaVM *hostVm, uint32_t tid)
1031 {
1032 if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
1033 ResumeVM(hostVm);
1034 } else {
1035 hostVm->ResumeWorkerVm(tid);
1036 }
1037 }
1038
SuspendVMById(EcmaVM * hostVm,uint32_t tid)1039 bool DFXJSNApi::SuspendVMById(EcmaVM *hostVm, uint32_t tid)
1040 {
1041 bool success = false;
1042 if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
1043 success = SuspendVM(hostVm);
1044 LOG_ECMA(INFO) << "The main thread, SuspendVMById succeeded: " << success;
1045 return success;
1046 } else {
1047 success = hostVm->SuspendWorkerVm(tid);
1048 LOG_ECMA(INFO) << "The worker thread, SuspendVMById succeeded: " << success;
1049 return success;
1050 }
1051 }
1052
StartTracing(const EcmaVM * vm,std::string & categories)1053 bool DFXJSNApi::StartTracing([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] std::string &categories)
1054 {
1055 #if defined(ECMASCRIPT_SUPPORT_TRACING)
1056 if (vm == nullptr) {
1057 return false;
1058 }
1059 Tracing *tracing = vm->GetTracing();
1060 if (tracing == nullptr) {
1061 tracing = new Tracing(vm);
1062 const_cast<EcmaVM *>(vm)->SetTracing(tracing);
1063 }
1064 tracing->StartTracing(categories);
1065 return true;
1066 #else
1067 LOG_ECMA(ERROR) << "Not support arkcompiler tracing";
1068 return false;
1069 #endif
1070 }
1071
StopTracing(const EcmaVM * vm)1072 std::unique_ptr<std::vector<TraceEvent>> DFXJSNApi::StopTracing([[maybe_unused]] const EcmaVM *vm)
1073 {
1074 #if defined(ECMASCRIPT_SUPPORT_TRACING)
1075 if (vm == nullptr) {
1076 return nullptr;
1077 }
1078 Tracing *tracing = vm->GetTracing();
1079 if (tracing == nullptr) {
1080 LOG_ECMA(ERROR) << "StopTracing tracing is nullptr";
1081 return nullptr;
1082 }
1083 auto traceEvents = tracing->StopTracing();
1084 if (traceEvents == nullptr) {
1085 LOG_ECMA(ERROR) << "trace events is nullptr";
1086 }
1087 delete tracing;
1088 tracing = nullptr;
1089 const_cast<EcmaVM *>(vm)->SetTracing(nullptr);
1090 return traceEvents;
1091 #else
1092 LOG_ECMA(ERROR) << "Not support arkcompiler tracing";
1093 return nullptr;
1094 #endif
1095 }
1096
GetTracingBufferUseage(const EcmaVM * vm,double & percentFull,uint32_t & eventCount,double & value)1097 void DFXJSNApi::GetTracingBufferUseage([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] double &percentFull,
1098 [[maybe_unused]] uint32_t &eventCount, [[maybe_unused]] double &value)
1099 {
1100 #if defined(ECMASCRIPT_SUPPORT_TRACING)
1101 if (vm == nullptr) {
1102 return;
1103 }
1104 ecmascript::Tracing *tracing = vm->GetTracing();
1105 if (tracing == nullptr) {
1106 LOG_ECMA(ERROR) << "GetTracingBufferUseage tracing is nullptr";
1107 } else {
1108 tracing->GetBufferUseage(percentFull, eventCount, value);
1109 }
1110 #else
1111 LOG_ECMA(ERROR) << "Not support arkcompiler tracing";
1112 #endif
1113 }
1114
TranslateJSStackInfo(const EcmaVM * vm,std::string & url,int32_t & line,int32_t & column,std::string & packageName)1115 void DFXJSNApi::TranslateJSStackInfo(const EcmaVM *vm, std::string &url, int32_t &line, int32_t &column,
1116 std::string &packageName)
1117 {
1118 auto cb = vm->GetSourceMapTranslateCallback();
1119 if (cb == nullptr) {
1120 LOG_ECMA(ERROR) << "Translate failed, callback function is nullptr.";
1121 } else if (!cb(url, line, column, packageName)) {
1122 LOG_ECMA(ERROR) << "Translate failed, url: " << url;
1123 }
1124 }
1125
GetCurrentThreadId()1126 uint32_t DFXJSNApi::GetCurrentThreadId()
1127 {
1128 return JSThread::GetCurrentThreadId();
1129 }
1130
RegisterAsyncDetectCallBack(const EcmaVM * vm)1131 void DFXJSNApi::RegisterAsyncDetectCallBack(const EcmaVM *vm)
1132 {
1133 vm->GetAsyncStackTrace()->RegisterAsyncDetectCallBack();
1134 }
1135
GetMainThreadStackTrace(const EcmaVM * vm,std::string & stackTraceStr)1136 void DFXJSNApi::GetMainThreadStackTrace(const EcmaVM *vm, std::string &stackTraceStr)
1137 {
1138 auto thread = vm->GetJSThread();
1139 if (thread->IsMainThread()) {
1140 stackTraceStr = ecmascript::JsStackInfo::BuildJsStackTrace(
1141 thread, false, false, ecmascript::JS_STACK_TRACE_DEPTH_MAX);
1142 } else {
1143 ecmascript::ThreadManagedScope runningScope(thread);
1144 ecmascript::SuspendAllScope suspendScope(thread);
1145 auto mainThread = ecmascript::Runtime::GetInstance()->GetMainThread();
1146 stackTraceStr = ecmascript::JsStackInfo::BuildJsStackTrace(
1147 mainThread, false, false, ecmascript::JS_STACK_TRACE_DEPTH_MAX);
1148 }
1149 auto sourceMapcb = vm->GetSourceMapCallback();
1150 if (sourceMapcb != nullptr && !stackTraceStr.empty()) {
1151 stackTraceStr = sourceMapcb(stackTraceStr);
1152 }
1153 }
1154
SetJsRawHeapCropLevel(CropLevel level)1155 void DFXJSNApi::SetJsRawHeapCropLevel(CropLevel level)
1156 {
1157 // SetJsRawHeapCropLevel
1158 ecmascript::Runtime::GetInstance()->SetRawHeapDumpCropLevel(level);
1159 LOG_ECMA(INFO) << "Set raw heap dump level " << static_cast<int>(level);
1160 }
1161
FindFunctionForHook(const EcmaVM * vm,const std::string & recordName,const std::string & namespaceName,const std::string & className,const std::string & funcName)1162 JSHandle<JSTaggedValue> DFXJSNApi::FindFunctionForHook(const EcmaVM *vm, const std::string &recordName,
1163 const std::string &namespaceName, const std::string &className,
1164 const std::string &funcName)
1165 {
1166 JSThread *thread = vm->GetJSThread();
1167 return SourceTextModule::FindFuncInModuleForHook(thread, recordName, namespaceName, className, funcName);
1168 }
1169
ReplaceFunctionForHook(const EcmaVM * vm,JSHandle<JSTaggedValue> & target,JSHandle<JSTaggedValue> & hook,JSHandle<JSTaggedValue> & backup)1170 void DFXJSNApi::ReplaceFunctionForHook(const EcmaVM *vm, JSHandle<JSTaggedValue> &target,
1171 JSHandle<JSTaggedValue> &hook, JSHandle<JSTaggedValue> &backup)
1172 {
1173 if (!target->IsJSFunction() || !hook->IsJSFunction() || !backup->IsJSFunction()) {
1174 return;
1175 }
1176
1177 JSThread *thread = vm->GetJSThread();
1178 JSHandle<JSFunction> targetFunc = JSHandle<JSFunction>::Cast(target);
1179 JSHandle<JSFunction> hookFunc = JSHandle<JSFunction>::Cast(hook);
1180 JSHandle<JSFunction> backupFunc = JSHandle<JSFunction>::Cast(backup);
1181
1182 JSFunction::ReplaceFunctionForHook(thread, backupFunc, targetFunc);
1183 JSFunction::ReplaceFunctionForHook(thread, targetFunc, hookFunc);
1184 }
1185
LoadHookModule(const EcmaVM * vm)1186 bool DFXJSNApi::LoadHookModule(const EcmaVM *vm)
1187 {
1188 const CString path(ecmascript::ohos::OhosConstants::HOOK_FILE_PATH);
1189 return JSPandaFileExecutor::ExecuteInsecureAbcFile(vm->GetJSThread(), path);
1190 }
1191 } // namespace panda