• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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/dfx/hprof/heap_profiler.h"
21 #include "ecmascript/dfx/stackinfo/js_stackinfo.h"
22 #include "ecmascript/ecma_vm.h"
23 #include "ecmascript/mem/c_string.h"
24 #include "ecmascript/mem/heap-inl.h"
25 #include "ecmascript/mem/gc_stats.h"
26 #include "ecmascript/napi/include/jsnapi.h"
27 #include "ecmascript/dfx/hprof/file_stream.h"
28 
29 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
30 #include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
31 #include "ecmascript/dfx/cpu_profiler/samples_record.h"
32 #endif
33 #if defined(ENABLE_DUMP_IN_FAULTLOG)
34 #include "faultloggerd_client.h"
35 #endif
36 
37 namespace panda {
38 using ecmascript::CString;
39 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
40 using BuiltinsArkTools = ecmascript::builtins::BuiltinsArkTools;
41 using ecmascript::CpuProfiler;
42 #endif
43 using ecmascript::EcmaString;
44 using ecmascript::JSTaggedValue;
45 using ecmascript::GCStats;
46 template<typename T>
47 using JSHandle = ecmascript::JSHandle<T>;
48 using ecmascript::FileStream;
49 using ecmascript::FileDescriptorStream;
50 using ecmascript::Stream;
51 using ecmascript::CMap;
52 
DumpHeapSnapshot(const EcmaVM * vm,int dumpFormat,const std::string & path,bool isVmMode,bool isPrivate,bool captureNumericValue)53 void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int dumpFormat,
54                                  [[maybe_unused]] const std::string &path, [[maybe_unused]] bool isVmMode,
55                                  [[maybe_unused]] bool isPrivate, [[maybe_unused]] bool captureNumericValue)
56 {
57 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
58     FileStream stream(path);
59     DumpHeapSnapshot(vm, dumpFormat, &stream, nullptr, isVmMode, isPrivate, captureNumericValue);
60 #else
61     LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
62 #endif
63 }
64 
DumpHeapSnapshot(const EcmaVM * vm,int dumpFormat,Stream * stream,Progress * progress,bool isVmMode,bool isPrivate,bool captureNumericValue)65 void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int dumpFormat,
66                                  [[maybe_unused]] Stream *stream, [[maybe_unused]] Progress *progress,
67                                  [[maybe_unused]] bool isVmMode, [[maybe_unused]] bool isPrivate,
68                                  [[maybe_unused]] bool captureNumericValue)
69 {
70 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
71     ecmascript::base::BlockHookScope blockScope;
72     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
73         const_cast<EcmaVM *>(vm));
74     heapProfile->DumpHeapSnapshot(ecmascript::DumpFormat(dumpFormat), stream, progress,
75                                   isVmMode, isPrivate, captureNumericValue);
76 #else
77     LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
78 #endif
79 }
80 
81 [[maybe_unused]] static uint8_t killCount = 0;
82 
DumpHeapSnapshot(const EcmaVM * vm,int dumpFormat,bool isVmMode,bool isPrivate,bool captureNumericValue)83 void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int dumpFormat,
84                                  [[maybe_unused]] bool isVmMode, [[maybe_unused]] bool isPrivate,
85                                  [[maybe_unused]] bool captureNumericValue)
86 {
87 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
88 #if defined(ENABLE_DUMP_IN_FAULTLOG)
89 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
90     // for CpuProfiler kill contral
91     if (DFXJSNApi::StopCpuProfilerForColdStart(vm)) {
92         return;
93     }
94 
95     (void)killCount;
96     if (DFXJSNApi::CpuProfilerSamplingAnyTime(vm)) {
97         killCount++;
98         return;
99     }
100 #endif // ECMASCRIPT_SUPPORT_CPUPROFILER
101     auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
102     options.SwitchStartGlobalLeakCheck();
103     if (options.EnableGlobalLeakCheck() && options.IsStartGlobalLeakCheck()) {
104         int32_t stackTraceFd = RequestFileDescriptor(static_cast<int32_t>(FaultLoggerType::JS_STACKTRACE));
105         if (stackTraceFd < 0) {
106             options.SwitchStartGlobalLeakCheck();
107         } else {
108             vm->GetJSThread()->SetStackTraceFd(stackTraceFd);
109         }
110     }
111     // Write in faultlog for heap leak.
112     int32_t fd = RequestFileDescriptor(static_cast<int32_t>(FaultLoggerType::JS_HEAP_SNAPSHOT));
113     if (fd < 0) {
114         LOG_ECMA(ERROR) << "Write FD failed, fd" << fd;
115         return;
116     }
117     FileDescriptorStream stream(fd);
118     DumpHeapSnapshot(vm, dumpFormat, &stream, nullptr, isVmMode, isPrivate, captureNumericValue);
119 #endif // ENABLE_DUMP_IN_FAULTLOG
120 #else
121     LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
122 #endif // ECMASCRIPT_SUPPORT_SNAPSHOT
123 }
124 
DestroyHeapProfiler(const EcmaVM * vm)125 void DFXJSNApi::DestroyHeapProfiler([[maybe_unused]] const EcmaVM *vm)
126 {
127 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
128     ecmascript::HeapProfilerInterface::Destroy(const_cast<EcmaVM *>(vm));
129 #else
130     LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
131 #endif
132 }
133 
BuildNativeAndJsStackTrace(const EcmaVM * vm,std::string & stackTraceStr)134 bool DFXJSNApi::BuildNativeAndJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr)
135 {
136     LOG_ECMA(INFO) <<"BuildJsStackInfoList start";
137     std::vector<JsFrameInfo> jf = ecmascript::JsStackInfo::BuildJsStackInfo(vm->GetAssociatedJSThread());
138     LOG_ECMA(INFO) <<"BuildJsStackInfoList JsFrameInfo";
139     for (uint32_t i = 0; i < jf.size(); ++i) {
140         std::string functionname = jf[i].functionName;
141         std::string filename = jf[i].fileName;
142         std::string pos = jf[i].pos;
143         uintptr_t *nativepointer = jf[i].nativePointer;
144         LOG_ECMA(INFO) << "BuildJsStackInfoList functionname: " << functionname;
145         LOG_ECMA(INFO) << "BuildJsStackInfoList filenaem: " << filename;
146         LOG_ECMA(INFO) << "BuildJsStackInfoList pos: " << pos;
147         LOG_ECMA(INFO) << "BuildJsStackInfoList nativepointer: " << nativepointer;
148     }
149     stackTraceStr = ecmascript::JsStackInfo::BuildJsStackTrace(vm->GetAssociatedJSThread(), true);
150     if (stackTraceStr.empty()) {
151         return false;
152     }
153     return true;
154 }
155 
BuildJsStackTrace(const EcmaVM * vm,std::string & stackTraceStr)156 bool DFXJSNApi::BuildJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr)
157 {
158     stackTraceStr = ecmascript::JsStackInfo::BuildJsStackTrace(vm->GetAssociatedJSThread(), false);
159     if (stackTraceStr.empty()) {
160         return false;
161     }
162     return true;
163 }
164 
StartHeapTracking(const EcmaVM * vm,double timeInterval,bool isVmMode,Stream * stream,bool traceAllocation,bool newThread)165 bool DFXJSNApi::StartHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] double timeInterval,
166                                   [[maybe_unused]] bool isVmMode, [[maybe_unused]] Stream *stream,
167                                   [[maybe_unused]] bool traceAllocation, [[maybe_unused]] bool newThread)
168 {
169 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
170     ecmascript::base::BlockHookScope blockScope;
171     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
172         const_cast<EcmaVM *>(vm));
173     return heapProfile->StartHeapTracking(timeInterval, isVmMode, stream, traceAllocation, newThread);
174 #else
175     LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
176     return false;
177 #endif
178 }
179 
UpdateHeapTracking(const EcmaVM * vm,Stream * stream)180 bool DFXJSNApi::UpdateHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream *stream)
181 {
182 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
183     ecmascript::base::BlockHookScope blockScope;
184     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
185         const_cast<EcmaVM *>(vm));
186     return heapProfile->UpdateHeapTracking(stream);
187 #else
188     LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
189     return false;
190 #endif
191 }
192 
StopHeapTracking(const EcmaVM * vm,const std::string & filePath,bool newThread)193 bool DFXJSNApi::StopHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const std::string &filePath,
194                                  [[maybe_unused]] bool newThread)
195 {
196 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
197     FileStream stream(filePath);
198     return StopHeapTracking(vm, &stream, nullptr, newThread);
199 #else
200     LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
201     return false;
202 #endif
203 }
204 
StopHeapTracking(const EcmaVM * vm,Stream * stream,Progress * progress,bool newThread)205 bool DFXJSNApi::StopHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream* stream,
206                                  [[maybe_unused]] Progress *progress, [[maybe_unused]] bool newThread)
207 {
208 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
209     ecmascript::base::BlockHookScope blockScope;
210     bool result = false;
211     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
212         const_cast<EcmaVM *>(vm));
213     result = heapProfile->StopHeapTracking(stream, progress, newThread);
214     ecmascript::HeapProfilerInterface::Destroy(const_cast<EcmaVM *>(vm));
215     return result;
216 #else
217     LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
218     return false;
219 #endif
220 }
221 
PrintStatisticResult(const EcmaVM * vm)222 void DFXJSNApi::PrintStatisticResult(const EcmaVM *vm)
223 {
224     ecmascript::GCStats gcstats(vm->GetHeap());
225     gcstats.PrintStatisticResult();
226 }
227 
StartRuntimeStat(EcmaVM * vm)228 void DFXJSNApi::StartRuntimeStat(EcmaVM *vm)
229 {
230     vm->GetJSThread()->GetCurrentEcmaContext()->SetRuntimeStatEnable(true);
231 }
232 
StopRuntimeStat(EcmaVM * vm)233 void DFXJSNApi::StopRuntimeStat(EcmaVM *vm)
234 {
235     vm->GetJSThread()->GetCurrentEcmaContext()->SetRuntimeStatEnable(false);
236 }
237 
GetArrayBufferSize(const EcmaVM * vm)238 size_t DFXJSNApi::GetArrayBufferSize(const EcmaVM *vm)
239 {
240     return vm->GetHeap()->GetArrayBufferSize();
241 }
242 
GetHeapTotalSize(const EcmaVM * vm)243 size_t DFXJSNApi::GetHeapTotalSize(const EcmaVM *vm)
244 {
245     return vm->GetHeap()->GetCommittedSize();
246 }
247 
GetHeapUsedSize(const EcmaVM * vm)248 size_t DFXJSNApi::GetHeapUsedSize(const EcmaVM *vm)
249 {
250     return vm->GetHeap()->GetHeapObjectSize();
251 }
252 
NotifyApplicationState(EcmaVM * vm,bool inBackground)253 void DFXJSNApi::NotifyApplicationState(EcmaVM *vm, bool inBackground)
254 {
255     const_cast<ecmascript::Heap *>(vm->GetHeap())->ChangeGCParams(inBackground);
256 }
257 
NotifyIdleStatusControl(const EcmaVM * vm,std::function<void (bool)> callback)258 void DFXJSNApi::NotifyIdleStatusControl(const EcmaVM *vm, std::function<void(bool)> callback)
259 {
260     const_cast<ecmascript::Heap *>(vm->GetHeap())->InitializeIdleStatusControl(callback);
261 }
262 
NotifyIdleTime(const EcmaVM * vm,int idleMicroSec)263 void DFXJSNApi::NotifyIdleTime(const EcmaVM *vm, int idleMicroSec)
264 {
265     const_cast<ecmascript::Heap *>(vm->GetHeap())->TriggerIdleCollection(idleMicroSec);
266 }
267 
NotifyMemoryPressure(EcmaVM * vm,bool inHighMemoryPressure)268 void DFXJSNApi::NotifyMemoryPressure(EcmaVM *vm, bool inHighMemoryPressure)
269 {
270     const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyMemoryPressure(inHighMemoryPressure);
271 }
272 
StopCpuProfilerForColdStart(const EcmaVM * vm)273 bool DFXJSNApi::StopCpuProfilerForColdStart([[maybe_unused]] const EcmaVM *vm)
274 {
275 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
276     bool success = false;
277     auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
278     if (options.EnableCpuProfilerColdStartMainThread()) {
279         success = true;
280         DFXJSNApi::StopCpuProfilerForFile(vm);
281     }
282 
283     if (options.EnableCpuProfilerColdStartWorkerThread()) {
284         success = true;
285         const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
286             if (workerVm->GetJSThread()->GetIsProfiling()) {
287                 DFXJSNApi::StopCpuProfilerForFile(workerVm);
288             }
289         });
290     }
291 
292     return success;
293 #else
294     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
295     return false;
296 #endif
297 }
298 
CpuProfilerSamplingAnyTime(const EcmaVM * vm)299 bool DFXJSNApi::CpuProfilerSamplingAnyTime([[maybe_unused]] const EcmaVM *vm)
300 {
301 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
302     (void)killCount;
303     bool success = false;
304     const uint8_t KILL_COUNT_FACTOR = 2;
305     auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
306     if (options.EnableCpuProfilerAnyTimeMainThread()) {
307         success = true;
308         if (killCount % KILL_COUNT_FACTOR == 0) {
309             uint8_t fileCount = killCount / KILL_COUNT_FACTOR + 1;
310             LOG_ECMA(INFO) << "Start CpuProfiler Any Time Main Thread, killCount = " << killCount;
311             std::string fileName = ConvertToStdString(const_cast<EcmaVM *>(vm)->GetBundleName())
312                                     + "_" + std::to_string(fileCount) + ".cpuprofile";
313             if (!BuiltinsArkTools::CreateFile(fileName)) {
314                 LOG_ECMA(ERROR) << "createFile failed " << fileName;
315             } else {
316                 DFXJSNApi::StartCpuProfilerForFile(vm, fileName, CpuProfiler::INTERVAL_OF_INNER_START);
317             }
318         } else {
319             LOG_ECMA(INFO) << "Stop CpuProfiler Any Time Main Thread, killCount = " << killCount;
320             if (vm->GetJSThread()->GetIsProfiling()) {
321                 DFXJSNApi::StopCpuProfilerForFile(vm);
322             }
323         }
324     }
325 
326     if (options.EnableCpuProfilerAnyTimeWorkerThread()) {
327         success = true;
328         if (killCount % KILL_COUNT_FACTOR == 0) {
329             uint8_t fileCount = killCount / KILL_COUNT_FACTOR + 1;
330             LOG_ECMA(INFO) << "Start CpuProfiler Any Time Worker Thread, killCount = " << killCount;
331             const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
332                 auto *thread = workerVm->GetAssociatedJSThread();
333                 std::string fileName = ConvertToStdString(workerVm->GetBundleName()) + "_"
334                                        + std::to_string(thread->GetThreadId()) + "_"
335                                        + std::to_string(fileCount) + ".cpuprofile";
336                 if (!BuiltinsArkTools::CreateFile(fileName)) {
337                     LOG_ECMA(ERROR) << "createFile failed " << fileName;
338                 } else {
339                     thread->SetCpuProfileName(fileName);
340                     thread->SetNeedProfiling(true);
341                 }
342             });
343         } else {
344             LOG_ECMA(INFO) << "Stop CpuProfiler Any Time Worker Thread, killCount = " << killCount;
345             const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
346                 auto *thread = workerVm->GetAssociatedJSThread();
347                 if (thread->GetIsProfiling()) {
348                     DFXJSNApi::StopCpuProfilerForFile(workerVm);
349                 }
350                 thread->SetNeedProfiling(false);
351             });
352         }
353     }
354 
355     return success;
356 #else
357     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
358     return false;
359 #endif
360 }
361 
StartCpuProfilerForFile(const EcmaVM * vm,const std::string & fileName,int interval)362 void DFXJSNApi::StartCpuProfilerForFile([[maybe_unused]] const EcmaVM *vm,
363                                         [[maybe_unused]] const std::string &fileName,
364                                         [[maybe_unused]] int interval)
365 {
366 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
367     if (vm == nullptr) {
368         return;
369     }
370     CpuProfiler *profiler = vm->GetProfiler();
371     if (profiler == nullptr) {
372         profiler = new CpuProfiler(vm, interval);
373         const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
374     }
375     profiler->StartCpuProfilerForFile(fileName);
376 #else
377     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
378 #endif
379 }
380 
StopCpuProfilerForFile(const EcmaVM * vm)381 void DFXJSNApi::StopCpuProfilerForFile([[maybe_unused]] const EcmaVM *vm)
382 {
383 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
384     if (vm == nullptr) {
385         return;
386     }
387     CpuProfiler *profiler = vm->GetProfiler();
388     if (profiler == nullptr) {
389         return;
390     }
391     profiler->StopCpuProfilerForFile();
392     delete profiler;
393     profiler = nullptr;
394     const_cast<EcmaVM *>(vm)->SetProfiler(nullptr);
395 #else
396     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
397 #endif
398 }
399 
StartCpuProfilerForInfo(const EcmaVM * vm,int interval)400 void DFXJSNApi::StartCpuProfilerForInfo([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int interval)
401 {
402 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
403     if (vm == nullptr) {
404         return;
405     }
406     CpuProfiler *profiler = vm->GetProfiler();
407     if (profiler == nullptr) {
408         profiler = new CpuProfiler(vm, interval);
409         const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
410     }
411     profiler->StartCpuProfilerForInfo();
412 #else
413     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
414 #endif
415 }
416 
StopCpuProfilerForInfo(const EcmaVM * vm)417 std::unique_ptr<ProfileInfo> DFXJSNApi::StopCpuProfilerForInfo([[maybe_unused]] const EcmaVM *vm)
418 {
419 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
420     if (vm == nullptr) {
421         return nullptr;
422     }
423     CpuProfiler *profiler = vm->GetProfiler();
424     if (profiler == nullptr) {
425         return nullptr;
426     }
427     auto profile = profiler->StopCpuProfilerForInfo();
428     if (profile == nullptr) {
429         LOG_DEBUGGER(ERROR) << "Transfer CpuProfiler::StopCpuProfilerImpl is failure";
430     }
431     delete profiler;
432     profiler = nullptr;
433     const_cast<EcmaVM *>(vm)->SetProfiler(nullptr);
434     return profile;
435 #else
436     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
437     return nullptr;
438 #endif
439 }
440 
SetCpuSamplingInterval(const EcmaVM * vm,int interval)441 void DFXJSNApi::SetCpuSamplingInterval([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int interval)
442 {
443 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
444     LOG_ECMA(INFO) << "SetCpuProfilerSamplingInterval, Sampling interval is: " << interval;
445     if (vm == nullptr) {
446         return;
447     }
448     CpuProfiler *profiler = vm->GetProfiler();
449     if (profiler == nullptr) {
450         profiler = new CpuProfiler(vm, interval);
451         const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
452         return;
453     }
454     profiler->SetCpuSamplingInterval(interval);
455 #else
456     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
457 #endif
458 }
459 
SuspendVM(const EcmaVM * vm)460 bool DFXJSNApi::SuspendVM([[maybe_unused]] const EcmaVM *vm)
461 {
462 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
463     ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
464     return vmThreadControl->NotifyVMThreadSuspension();
465 #else
466     LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
467     return false;
468 #endif
469 }
470 
ResumeVM(const EcmaVM * vm)471 void DFXJSNApi::ResumeVM([[maybe_unused]] const EcmaVM *vm)
472 {
473 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
474     ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
475     vmThreadControl->ResumeVM();
476 #else
477     LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
478 #endif
479 }
480 
IsSuspended(const EcmaVM * vm)481 bool DFXJSNApi::IsSuspended([[maybe_unused]] const EcmaVM *vm)
482 {
483 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
484     ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
485     return vmThreadControl->IsSuspended();
486 #else
487     LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
488     return false;
489 #endif
490 }
491 
CheckSafepoint(const EcmaVM * vm)492 bool DFXJSNApi::CheckSafepoint([[maybe_unused]] const EcmaVM *vm)
493 {
494 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
495     ecmascript::JSThread* thread = vm->GetJSThread();
496     return thread->CheckSafepoint();
497 #else
498     LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
499     return false;
500 #endif
501 }
502 
BuildJsStackInfoList(const EcmaVM * hostVm,uint32_t tid,std::vector<JsFrameInfo> & jsFrames)503 bool DFXJSNApi::BuildJsStackInfoList(const EcmaVM *hostVm, uint32_t tid, std::vector<JsFrameInfo>& jsFrames)
504 {
505     EcmaVM *vm;
506     if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
507         vm = const_cast<EcmaVM*>(hostVm);
508     } else {
509         vm = const_cast<EcmaVM*>(hostVm)->GetWorkerVm(tid);
510         if (vm == nullptr) {
511             return false;
512         }
513     }
514     jsFrames = ecmascript::JsStackInfo::BuildJsStackInfo(vm->GetAssociatedJSThread());
515     if (jsFrames.size() > 0) {
516         return true;
517     }
518     return false;
519 }
520 
StartSampling(const EcmaVM * vm,uint64_t samplingInterval)521 bool DFXJSNApi::StartSampling([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] uint64_t samplingInterval)
522 {
523 #if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
524     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
525         const_cast<EcmaVM *>(vm));
526     return heapProfile->StartHeapSampling(samplingInterval);
527 #else
528     LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
529     return false;
530 #endif
531 }
532 
GetAllocationProfile(const EcmaVM * vm)533 const SamplingInfo *DFXJSNApi::GetAllocationProfile([[maybe_unused]] const EcmaVM *vm)
534 {
535 #if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
536     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
537         const_cast<EcmaVM *>(vm));
538     return heapProfile->GetAllocationProfile();
539 #else
540     LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
541     return nullptr;
542 #endif
543 }
544 
StopSampling(const EcmaVM * vm)545 void DFXJSNApi::StopSampling([[maybe_unused]] const EcmaVM *vm)
546 {
547 #if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
548     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
549         const_cast<EcmaVM *>(vm));
550     heapProfile->StopHeapSampling();
551 #else
552     LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
553 #endif
554 }
555 
StartProfiler(EcmaVM * vm,const ProfilerOption & option,int32_t instanceId,const DebuggerPostTask & debuggerPostTask)556 bool DFXJSNApi::StartProfiler(EcmaVM *vm, const ProfilerOption &option, int32_t instanceId,
557                               const DebuggerPostTask &debuggerPostTask)
558 {
559     JSNApi::DebugOption debugOption;
560     debugOption.libraryPath = option.libraryPath;
561     if (option.profilerType == ProfilerType::CPU_PROFILER) {
562         debugOption.isDebugMode = false;
563         if (JSNApi::StartDebugger(vm, debugOption, instanceId, debuggerPostTask)) {
564             StartCpuProfilerForInfo(vm, option.interval);
565             return true;
566         } else {
567             LOG_ECMA(ERROR) << "DFXJSNApi:Failed to StartDebugger";
568             return false;
569         }
570     } else {
571         debugOption.isDebugMode = true;
572         return JSNApi::StartDebugger(vm, debugOption, instanceId, debuggerPostTask);
573     }
574 }
575 
ResumeVMById(EcmaVM * hostVm,uint32_t tid)576 void DFXJSNApi::ResumeVMById(EcmaVM *hostVm, uint32_t tid)
577 {
578     if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
579         ResumeVM(hostVm);
580     } else {
581         hostVm->ResumeWorkerVm(tid);
582     }
583 }
584 
SuspendVMById(EcmaVM * hostVm,uint32_t tid)585 bool DFXJSNApi::SuspendVMById(EcmaVM *hostVm, uint32_t tid)
586 {
587     if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
588         return SuspendVM(hostVm);
589     } else {
590         return hostVm->SuspendWorkerVm(tid);
591     }
592 }
593 } // namespace panda
594