• 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/builtins/builtins_ark_tools.h"
19 #include "ecmascript/dfx/hprof/heap_profiler.h"
20 #include "ecmascript/dfx/stackinfo/js_stackinfo.h"
21 #include "ecmascript/dfx/tracing/tracing.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 #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 
DumpHeapSnapshot(const EcmaVM * vm,int dumpFormat,const std::string & path,bool isVmMode,bool isPrivate,bool captureNumericValue)55 void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int dumpFormat,
56                                  [[maybe_unused]] const std::string &path, [[maybe_unused]] bool isVmMode,
57                                  [[maybe_unused]] bool isPrivate, [[maybe_unused]] bool captureNumericValue)
58 {
59 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
60     FileStream stream(path);
61     DumpHeapSnapshot(vm, dumpFormat, &stream, nullptr, isVmMode, isPrivate, captureNumericValue);
62 #else
63     LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
64 #endif
65 }
66 
DumpHeapSnapshot(const EcmaVM * vm,int dumpFormat,Stream * stream,Progress * progress,bool isVmMode,bool isPrivate,bool captureNumericValue,bool isFullGC)67 void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int dumpFormat,
68                                  [[maybe_unused]] Stream *stream, [[maybe_unused]] Progress *progress,
69                                  [[maybe_unused]] bool isVmMode, [[maybe_unused]] bool isPrivate,
70                                  [[maybe_unused]] bool captureNumericValue, [[maybe_unused]] bool isFullGC)
71 {
72 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
73     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
74         const_cast<EcmaVM *>(vm));
75     heapProfile->DumpHeapSnapshot(ecmascript::DumpFormat(dumpFormat), stream, progress,
76                                   isVmMode, isPrivate, captureNumericValue, isFullGC);
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(const EcmaVM * vm,int dumpFormat,bool isVmMode,bool isPrivate,bool captureNumericValue,bool isFullGC)84 void DFXJSNApi::DumpCpuProfile([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int dumpFormat,
85                                [[maybe_unused]] bool isVmMode, [[maybe_unused]] bool isPrivate,
86                                [[maybe_unused]] bool captureNumericValue, [[maybe_unused]] bool isFullGC)
87 {
88 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
89 #if defined(ENABLE_DUMP_IN_FAULTLOG)
90 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
91     // for CpuProfiler kill contral
92     if (DFXJSNApi::StopCpuProfilerForColdStart(vm)) {
93         return;
94     }
95 
96     (void)killCount;
97     if (DFXJSNApi::CpuProfilerSamplingAnyTime(vm)) {
98         killCount++;
99         return;
100     }
101 #endif // ECMASCRIPT_SUPPORT_CPUPROFILER
102 #endif // ENABLE_DUMP_IN_FAULTLOG
103 #endif // ECMASCRIPT_SUPPORT_SNAPSHOT
104 }
105 
DumpHeapSnapshot(const EcmaVM * vm,int dumpFormat,bool isVmMode,bool isPrivate,bool captureNumericValue,bool isFullGC)106 void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int dumpFormat,
107                                  [[maybe_unused]] bool isVmMode, [[maybe_unused]] bool isPrivate,
108                                  [[maybe_unused]] bool captureNumericValue, [[maybe_unused]] bool isFullGC)
109 {
110 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
111 #if defined(ENABLE_DUMP_IN_FAULTLOG)
112     auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
113     options.SwitchStartGlobalLeakCheck();
114     if (options.EnableGlobalLeakCheck() && options.IsStartGlobalLeakCheck()) {
115         int32_t stackTraceFd = RequestFileDescriptor(static_cast<int32_t>(FaultLoggerType::JS_STACKTRACE));
116         if (stackTraceFd < 0) {
117             options.SwitchStartGlobalLeakCheck();
118         } else {
119             vm->GetJSThread()->SetStackTraceFd(stackTraceFd);
120         }
121     }
122     // Write in faultlog for heap leak.
123     int32_t fd = RequestFileDescriptor(static_cast<int32_t>(FaultLoggerType::JS_HEAP_SNAPSHOT));
124     if (fd < 0) {
125         LOG_ECMA(ERROR) << "Write FD failed, fd" << fd;
126         return;
127     }
128     FileDescriptorStream stream(fd);
129     DumpHeapSnapshot(vm, dumpFormat, &stream, nullptr, isVmMode, isPrivate, captureNumericValue, isFullGC);
130 #endif // ENABLE_DUMP_IN_FAULTLOG
131 #else
132     LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
133 #endif // ECMASCRIPT_SUPPORT_SNAPSHOT
134 }
135 
DumpHeapSnapshotAllVMs(const EcmaVM * vm,int dumpFormat,bool isVmMode,bool isPrivate,bool captureNumericValue,bool isFullGC)136 void DFXJSNApi::DumpHeapSnapshotAllVMs([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int dumpFormat,
137                                        [[maybe_unused]] bool isVmMode, [[maybe_unused]] bool isPrivate,
138                                        [[maybe_unused]] bool captureNumericValue, [[maybe_unused]] bool isFullGC)
139 {
140 #if defined(ENABLE_DUMP_IN_FAULTLOG)
141     if (vm->IsWorkerThread()) {
142         LOG_ECMA(ERROR) << "this is a workthread!";
143         return;
144     }
145     // dump host vm.
146     DumpHeapSnapshot(vm, dumpFormat, isVmMode, isPrivate, captureNumericValue, isFullGC);
147     const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
148         uv_loop_t *loop = reinterpret_cast<uv_loop_t *>(workerVm->GetLoop());
149         if (loop == nullptr) {
150             LOG_ECMA(ERROR) << "loop is nullptr";
151             return;
152         }
153         struct DumpForSnapShotStruct *dumpStruct = new DumpForSnapShotStruct();
154         dumpStruct->vm = workerVm;
155         dumpStruct->dumpFormat = dumpFormat;
156         dumpStruct->isVmMode = isVmMode;
157         dumpStruct->isPrivate = isPrivate;
158         dumpStruct->captureNumericValue = captureNumericValue;
159         dumpStruct->isFullGC = isFullGC;
160         uv_work_t *work = new uv_work_t;
161         work->data = (void *)dumpStruct;
162         if (uv_loop_alive(loop) == 0) {
163             LOG_ECMA(ERROR) << "uv_loop_alive is dead";
164             return;
165         }
166         uv_queue_work(
167             loop,
168             work,
169             [](uv_work_t *) {},
170             [](uv_work_t *work, int32_t) {
171                 struct DumpForSnapShotStruct *dump = (struct DumpForSnapShotStruct *)(work->data);
172                 DumpHeapSnapshot(dump->vm, dump->dumpFormat, dump->isVmMode,
173                                  dump->isPrivate, dump->captureNumericValue, dump->isFullGC);
174                 delete dump;
175                 delete work;
176         });
177     });
178 #endif
179 }
180 
DestroyHeapProfiler(const EcmaVM * vm)181 void DFXJSNApi::DestroyHeapProfiler([[maybe_unused]] const EcmaVM *vm)
182 {
183 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
184     ecmascript::HeapProfilerInterface::Destroy(const_cast<EcmaVM *>(vm));
185 #else
186     LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
187 #endif
188 }
189 
BuildNativeAndJsStackTrace(const EcmaVM * vm,std::string & stackTraceStr)190 bool DFXJSNApi::BuildNativeAndJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr)
191 {
192     LOG_ECMA(INFO) <<"BuildJsStackInfoList start";
193     std::vector<JsFrameInfo> jf = ecmascript::JsStackInfo::BuildJsStackInfo(vm->GetAssociatedJSThread());
194     LOG_ECMA(INFO) <<"BuildJsStackInfoList JsFrameInfo";
195     for (uint32_t i = 0; i < jf.size(); ++i) {
196         std::string functionname = jf[i].functionName;
197         std::string filename = jf[i].fileName;
198         std::string pos = jf[i].pos;
199         uintptr_t *nativepointer = jf[i].nativePointer;
200         LOG_ECMA(INFO) << "BuildJsStackInfoList functionname: " << functionname;
201         LOG_ECMA(INFO) << "BuildJsStackInfoList filenaem: " << filename;
202         LOG_ECMA(INFO) << "BuildJsStackInfoList pos: " << pos;
203         LOG_ECMA(INFO) << "BuildJsStackInfoList nativepointer: " << nativepointer;
204     }
205     stackTraceStr = ecmascript::JsStackInfo::BuildJsStackTrace(vm->GetAssociatedJSThread(), true);
206     if (stackTraceStr.empty()) {
207         return false;
208     }
209     return true;
210 }
211 
BuildJsStackTrace(const EcmaVM * vm,std::string & stackTraceStr)212 bool DFXJSNApi::BuildJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr)
213 {
214     stackTraceStr = ecmascript::JsStackInfo::BuildJsStackTrace(vm->GetAssociatedJSThread(), false);
215     if (stackTraceStr.empty()) {
216         return false;
217     }
218     return true;
219 }
220 
StartHeapTracking(const EcmaVM * vm,double timeInterval,bool isVmMode,Stream * stream,bool traceAllocation,bool newThread)221 bool DFXJSNApi::StartHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] double timeInterval,
222                                   [[maybe_unused]] bool isVmMode, [[maybe_unused]] Stream *stream,
223                                   [[maybe_unused]] bool traceAllocation, [[maybe_unused]] bool newThread)
224 {
225 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
226     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
227         const_cast<EcmaVM *>(vm));
228     return heapProfile->StartHeapTracking(timeInterval, isVmMode, stream, traceAllocation, newThread);
229 #else
230     LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
231     return false;
232 #endif
233 }
234 
UpdateHeapTracking(const EcmaVM * vm,Stream * stream)235 bool DFXJSNApi::UpdateHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream *stream)
236 {
237 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
238     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
239         const_cast<EcmaVM *>(vm));
240     return heapProfile->UpdateHeapTracking(stream);
241 #else
242     LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
243     return false;
244 #endif
245 }
246 
StopHeapTracking(const EcmaVM * vm,const std::string & filePath,bool newThread)247 bool DFXJSNApi::StopHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const std::string &filePath,
248                                  [[maybe_unused]] bool newThread)
249 {
250 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
251     FileStream stream(filePath);
252     return StopHeapTracking(vm, &stream, nullptr, newThread);
253 #else
254     LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
255     return false;
256 #endif
257 }
258 
StopHeapTracking(const EcmaVM * vm,Stream * stream,Progress * progress,bool newThread)259 bool DFXJSNApi::StopHeapTracking([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Stream* stream,
260                                  [[maybe_unused]] Progress *progress, [[maybe_unused]] bool newThread)
261 {
262 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
263     bool result = false;
264     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
265         const_cast<EcmaVM *>(vm));
266     result = heapProfile->StopHeapTracking(stream, progress, newThread);
267     ecmascript::HeapProfilerInterface::Destroy(const_cast<EcmaVM *>(vm));
268     return result;
269 #else
270     LOG_ECMA(ERROR) << "Not support arkcompiler heap tracking";
271     return false;
272 #endif
273 }
274 
PrintStatisticResult(const EcmaVM * vm)275 void DFXJSNApi::PrintStatisticResult(const EcmaVM *vm)
276 {
277     ecmascript::GCStats gcstats(vm->GetHeap());
278     gcstats.PrintStatisticResult();
279 }
280 
StartRuntimeStat(EcmaVM * vm)281 void DFXJSNApi::StartRuntimeStat(EcmaVM *vm)
282 {
283     vm->GetJSThread()->GetCurrentEcmaContext()->SetRuntimeStatEnable(true);
284 }
285 
StopRuntimeStat(EcmaVM * vm)286 void DFXJSNApi::StopRuntimeStat(EcmaVM *vm)
287 {
288     vm->GetJSThread()->GetCurrentEcmaContext()->SetRuntimeStatEnable(false);
289 }
290 
GetArrayBufferSize(const EcmaVM * vm)291 size_t DFXJSNApi::GetArrayBufferSize(const EcmaVM *vm)
292 {
293     return vm->GetHeap()->GetArrayBufferSize();
294 }
295 
GetHeapTotalSize(const EcmaVM * vm)296 size_t DFXJSNApi::GetHeapTotalSize(const EcmaVM *vm)
297 {
298     return vm->GetHeap()->GetCommittedSize();
299 }
300 
GetHeapUsedSize(const EcmaVM * vm)301 size_t DFXJSNApi::GetHeapUsedSize(const EcmaVM *vm)
302 {
303     return vm->GetHeap()->GetLiveObjectSize();
304 }
305 
GetHeapObjectSize(const EcmaVM * vm)306 size_t DFXJSNApi::GetHeapObjectSize(const EcmaVM *vm)
307 {
308     return vm->GetHeap()->GetHeapObjectSize();
309 }
310 
GetHeapLimitSize(const EcmaVM * vm)311 size_t DFXJSNApi::GetHeapLimitSize(const EcmaVM *vm)
312 {
313     return vm->GetHeap()->GetHeapLimitSize();
314 }
315 
isOverLimit(const EcmaVM * vm)316 bool DFXJSNApi::isOverLimit(const EcmaVM *vm)
317 {
318     return vm->isOverLimit();
319 }
320 
SetOverLimit(EcmaVM * vm,bool state)321 void DFXJSNApi::SetOverLimit(EcmaVM *vm, bool state)
322 {
323     vm->SetOverLimit(state);
324 }
325 
GetHeapPrepare(const EcmaVM * vm)326 void DFXJSNApi::GetHeapPrepare(const EcmaVM *vm)
327 {
328     const_cast<ecmascript::Heap *>(vm->GetHeap())->Prepare();
329 }
330 
NotifyApplicationState(EcmaVM * vm,bool inBackground)331 void DFXJSNApi::NotifyApplicationState(EcmaVM *vm, bool inBackground)
332 {
333     const_cast<ecmascript::Heap *>(vm->GetHeap())->ChangeGCParams(inBackground);
334 }
335 
NotifyIdleStatusControl(const EcmaVM * vm,std::function<void (bool)> callback)336 void DFXJSNApi::NotifyIdleStatusControl(const EcmaVM *vm, std::function<void(bool)> callback)
337 {
338     const_cast<ecmascript::Heap *>(vm->GetHeap())->InitializeIdleStatusControl(callback);
339 }
340 
NotifyIdleTime(const EcmaVM * vm,int idleMicroSec)341 void DFXJSNApi::NotifyIdleTime(const EcmaVM *vm, int idleMicroSec)
342 {
343     const_cast<ecmascript::Heap *>(vm->GetHeap())->TriggerIdleCollection(idleMicroSec);
344 }
345 
NotifyMemoryPressure(EcmaVM * vm,bool inHighMemoryPressure)346 void DFXJSNApi::NotifyMemoryPressure(EcmaVM *vm, bool inHighMemoryPressure)
347 {
348     const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyMemoryPressure(inHighMemoryPressure);
349 }
350 
NotifyFinishColdStart(EcmaVM * vm,bool isConvinced)351 void DFXJSNApi::NotifyFinishColdStart(EcmaVM *vm, bool isConvinced)
352 {
353     if (isConvinced) {
354         const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyFinishColdStart();
355     } else {
356         const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyFinishColdStartSoon();
357     }
358 }
359 
NotifyHighSensitive(EcmaVM * vm,bool isStart)360 void DFXJSNApi::NotifyHighSensitive(EcmaVM *vm, bool isStart)
361 {
362     const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyHighSensitive(isStart);
363 }
364 
StopCpuProfilerForColdStart(const EcmaVM * vm)365 bool DFXJSNApi::StopCpuProfilerForColdStart([[maybe_unused]] const EcmaVM *vm)
366 {
367 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
368     bool success = false;
369     auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
370     if (options.EnableCpuProfilerColdStartMainThread()) {
371         success = true;
372         DFXJSNApi::StopCpuProfilerForFile(vm);
373     }
374 
375     if (options.EnableCpuProfilerColdStartWorkerThread()) {
376         success = true;
377         const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
378             if (workerVm->GetJSThread()->GetIsProfiling()) {
379                 DFXJSNApi::StopCpuProfilerForFile(workerVm);
380             }
381         });
382     }
383 
384     return success;
385 #else
386     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
387     return false;
388 #endif
389 }
390 
CpuProfilerSamplingAnyTime(const EcmaVM * vm)391 bool DFXJSNApi::CpuProfilerSamplingAnyTime([[maybe_unused]] const EcmaVM *vm)
392 {
393 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
394     (void)killCount;
395     bool success = false;
396     const uint8_t KILL_COUNT_FACTOR = 2;
397     auto &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
398     if (options.EnableCpuProfilerAnyTimeMainThread()) {
399         success = true;
400         if (killCount % KILL_COUNT_FACTOR == 0) {
401             uint8_t fileCount = killCount / KILL_COUNT_FACTOR + 1;
402             LOG_ECMA(INFO) << "Start CpuProfiler Any Time Main Thread, killCount = " << killCount;
403             std::string fileName = ConvertToStdString(const_cast<EcmaVM *>(vm)->GetBundleName())
404                                     + "_" + std::to_string(fileCount) + ".cpuprofile";
405             if (!BuiltinsArkTools::CreateFile(fileName)) {
406                 LOG_ECMA(ERROR) << "createFile failed " << fileName;
407             } else {
408                 DFXJSNApi::StartCpuProfilerForFile(vm, fileName, CpuProfiler::INTERVAL_OF_INNER_START);
409             }
410         } else {
411             LOG_ECMA(INFO) << "Stop CpuProfiler Any Time Main Thread, killCount = " << killCount;
412             if (vm->GetJSThread()->GetIsProfiling()) {
413                 DFXJSNApi::StopCpuProfilerForFile(vm);
414             }
415         }
416     }
417 
418     if (options.EnableCpuProfilerAnyTimeWorkerThread()) {
419         success = true;
420         if (killCount % KILL_COUNT_FACTOR == 0) {
421             uint8_t fileCount = killCount / KILL_COUNT_FACTOR + 1;
422             LOG_ECMA(INFO) << "Start CpuProfiler Any Time Worker Thread, killCount = " << killCount;
423             const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
424                 auto *thread = workerVm->GetAssociatedJSThread();
425                 std::string fileName = ConvertToStdString(workerVm->GetBundleName()) + "_"
426                                        + std::to_string(thread->GetThreadId()) + "_"
427                                        + std::to_string(fileCount) + ".cpuprofile";
428                 if (!BuiltinsArkTools::CreateFile(fileName)) {
429                     LOG_ECMA(ERROR) << "createFile failed " << fileName;
430                 } else {
431                     thread->SetCpuProfileName(fileName);
432                     thread->SetNeedProfiling(true);
433                 }
434             });
435         } else {
436             LOG_ECMA(INFO) << "Stop CpuProfiler Any Time Worker Thread, killCount = " << killCount;
437             const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
438                 auto *thread = workerVm->GetAssociatedJSThread();
439                 if (thread->GetIsProfiling()) {
440                     DFXJSNApi::StopCpuProfilerForFile(workerVm);
441                 }
442                 thread->SetNeedProfiling(false);
443             });
444         }
445     }
446 
447     return success;
448 #else
449     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
450     return false;
451 #endif
452 }
453 
StartCpuProfilerForFile(const EcmaVM * vm,const std::string & fileName,int interval)454 void DFXJSNApi::StartCpuProfilerForFile([[maybe_unused]] const EcmaVM *vm,
455                                         [[maybe_unused]] const std::string &fileName,
456                                         [[maybe_unused]] int interval)
457 {
458 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
459     if (interval < 0) {
460         LOG_ECMA(ERROR) << "Sampling interval is illegal";
461         return;
462     }
463     if (vm == nullptr) {
464         return;
465     }
466     CpuProfiler *profiler = vm->GetProfiler();
467     if (profiler == nullptr) {
468         profiler = new CpuProfiler(vm, interval);
469         const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
470     }
471     profiler->StartCpuProfilerForFile(fileName);
472 #else
473     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
474 #endif
475 }
476 
StopCpuProfilerForFile(const EcmaVM * vm)477 void DFXJSNApi::StopCpuProfilerForFile([[maybe_unused]] const EcmaVM *vm)
478 {
479 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
480     if (vm == nullptr) {
481         return;
482     }
483     CpuProfiler *profiler = vm->GetProfiler();
484     if (profiler == nullptr) {
485         return;
486     }
487     profiler->StopCpuProfilerForFile();
488     delete profiler;
489     profiler = nullptr;
490     const_cast<EcmaVM *>(vm)->SetProfiler(nullptr);
491 #else
492     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
493 #endif
494 }
495 
StartCpuProfilerForInfo(const EcmaVM * vm,int interval)496 void DFXJSNApi::StartCpuProfilerForInfo([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int interval)
497 {
498 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
499     if (interval < 0) {
500         LOG_ECMA(ERROR) << "Sampling interval is illegal";
501         return;
502     }
503     if (vm == nullptr) {
504         return;
505     }
506     CpuProfiler *profiler = vm->GetProfiler();
507     if (profiler == nullptr) {
508         profiler = new CpuProfiler(vm, interval);
509         const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
510     }
511     profiler->StartCpuProfilerForInfo();
512 #else
513     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
514 #endif
515 }
516 
StopCpuProfilerForInfo(const EcmaVM * vm)517 std::unique_ptr<ProfileInfo> DFXJSNApi::StopCpuProfilerForInfo([[maybe_unused]] const EcmaVM *vm)
518 {
519 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
520     if (vm == nullptr) {
521         return nullptr;
522     }
523     CpuProfiler *profiler = vm->GetProfiler();
524     if (profiler == nullptr) {
525         return nullptr;
526     }
527     auto profile = profiler->StopCpuProfilerForInfo();
528     if (profile == nullptr) {
529         LOG_DEBUGGER(ERROR) << "Transfer CpuProfiler::StopCpuProfilerImpl is failure";
530     }
531     delete profiler;
532     profiler = nullptr;
533     const_cast<EcmaVM *>(vm)->SetProfiler(nullptr);
534     return profile;
535 #else
536     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
537     return nullptr;
538 #endif
539 }
540 
SetCpuSamplingInterval(const EcmaVM * vm,int interval)541 void DFXJSNApi::SetCpuSamplingInterval([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int interval)
542 {
543 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
544     if (interval < 0) {
545         LOG_ECMA(ERROR) << "Sampling interval is illegal";
546         return;
547     }
548     LOG_ECMA(INFO) << "SetCpuProfilerSamplingInterval, Sampling interval is: " << interval;
549     if (vm == nullptr) {
550         return;
551     }
552     CpuProfiler *profiler = vm->GetProfiler();
553     if (profiler == nullptr) {
554         profiler = new CpuProfiler(vm, interval);
555         const_cast<EcmaVM *>(vm)->SetProfiler(profiler);
556         return;
557     }
558     profiler->SetCpuSamplingInterval(interval);
559 #else
560     LOG_ECMA(ERROR) << "Not support arkcompiler cpu profiler";
561 #endif
562 }
563 
SuspendVM(const EcmaVM * vm)564 bool DFXJSNApi::SuspendVM([[maybe_unused]] const EcmaVM *vm)
565 {
566 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
567     ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
568     return vmThreadControl->NotifyVMThreadSuspension();
569 #else
570     LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
571     return false;
572 #endif
573 }
574 
ResumeVM(const EcmaVM * vm)575 void DFXJSNApi::ResumeVM([[maybe_unused]] const EcmaVM *vm)
576 {
577 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
578     ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
579     vmThreadControl->ResumeVM();
580 #else
581     LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
582 #endif
583 }
584 
IsSuspended(const EcmaVM * vm)585 bool DFXJSNApi::IsSuspended([[maybe_unused]] const EcmaVM *vm)
586 {
587 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
588     ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
589     return vmThreadControl->IsSuspended();
590 #else
591     LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
592     return false;
593 #endif
594 }
595 
TerminateExecution(const EcmaVM * vm)596 void DFXJSNApi::TerminateExecution(const EcmaVM *vm)
597 {
598     ecmascript::VmThreadControl* vmThreadControl = vm->GetAssociatedJSThread()->GetVmThreadControl();
599     vmThreadControl->RequestTerminateExecution();
600 }
601 
CheckSafepoint(const EcmaVM * vm)602 bool DFXJSNApi::CheckSafepoint([[maybe_unused]] const EcmaVM *vm)
603 {
604 #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
605     ecmascript::JSThread* thread = vm->GetJSThread();
606     return thread->CheckSafepoint();
607 #else
608     LOG_ECMA(ERROR) << "Not support arkcompiler snapshot";
609     return false;
610 #endif
611 }
612 
BuildJsStackInfoList(const EcmaVM * hostVm,uint32_t tid,std::vector<JsFrameInfo> & jsFrames)613 bool DFXJSNApi::BuildJsStackInfoList(const EcmaVM *hostVm, uint32_t tid, std::vector<JsFrameInfo>& jsFrames)
614 {
615     EcmaVM *vm;
616     if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
617         vm = const_cast<EcmaVM*>(hostVm);
618     } else {
619         vm = const_cast<EcmaVM*>(hostVm)->GetWorkerVm(tid);
620         if (vm == nullptr) {
621             return false;
622         }
623     }
624     jsFrames = ecmascript::JsStackInfo::BuildJsStackInfo(vm->GetAssociatedJSThread());
625     if (jsFrames.size() > 0) {
626         return true;
627     }
628     return false;
629 }
630 
StartSampling(const EcmaVM * vm,uint64_t samplingInterval)631 bool DFXJSNApi::StartSampling([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] uint64_t samplingInterval)
632 {
633 #if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
634     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
635         const_cast<EcmaVM *>(vm));
636     return heapProfile->StartHeapSampling(samplingInterval);
637 #else
638     LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
639     return false;
640 #endif
641 }
642 
GetAllocationProfile(const EcmaVM * vm)643 const SamplingInfo *DFXJSNApi::GetAllocationProfile([[maybe_unused]] const EcmaVM *vm)
644 {
645 #if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
646     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
647         const_cast<EcmaVM *>(vm));
648     return heapProfile->GetAllocationProfile();
649 #else
650     LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
651     return nullptr;
652 #endif
653 }
654 
StopSampling(const EcmaVM * vm)655 void DFXJSNApi::StopSampling([[maybe_unused]] const EcmaVM *vm)
656 {
657 #if defined(ECMASCRIPT_SUPPORT_HEAPSAMPLING)
658     ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
659         const_cast<EcmaVM *>(vm));
660     heapProfile->StopHeapSampling();
661 #else
662     LOG_ECMA(ERROR) << "Not support arkcompiler heap sampling";
663 #endif
664 }
665 
666 // release or debug hap : aa start -p 'dumpheap'
667 //                        aa start -p 'profile'
StartProfiler(EcmaVM * vm,const ProfilerOption & option,int tid,int32_t instanceId,const DebuggerPostTask & debuggerPostTask,bool isDebugApp)668 bool DFXJSNApi::StartProfiler(EcmaVM *vm, const ProfilerOption &option, int tid,
669                               int32_t instanceId, const DebuggerPostTask &debuggerPostTask, bool isDebugApp)
670 {
671     LOG_ECMA(INFO) << "DFXJSNApi::StartProfiler, type = " << (int)option.profilerType
672         << ", tid = " << tid << ", isDebugApp = " << isDebugApp;
673     JSNApi::DebugOption debugOption;
674     debugOption.libraryPath = option.libraryPath;
675     if (option.profilerType == ProfilerType::CPU_PROFILER) {
676         debugOption.isDebugMode = false;
677         if (JSNApi::NotifyDebugMode(tid, vm, debugOption, instanceId, debuggerPostTask, isDebugApp)) {
678             StartCpuProfilerForInfo(vm, option.interval);
679             return true;
680         } else {
681             LOG_ECMA(ERROR) << "DFXJSNApi:Failed to StartDebugger";
682             return false;
683         }
684     } else {
685         debugOption.isDebugMode = true;
686         return JSNApi::NotifyDebugMode(tid, vm, debugOption, instanceId, debuggerPostTask, isDebugApp);
687     }
688 }
689 
ResumeVMById(EcmaVM * hostVm,uint32_t tid)690 void DFXJSNApi::ResumeVMById(EcmaVM *hostVm, uint32_t tid)
691 {
692     if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
693         ResumeVM(hostVm);
694     } else {
695         hostVm->ResumeWorkerVm(tid);
696     }
697 }
698 
SuspendVMById(EcmaVM * hostVm,uint32_t tid)699 bool DFXJSNApi::SuspendVMById(EcmaVM *hostVm, uint32_t tid)
700 {
701     bool success = false;
702     if (hostVm->GetAssociatedJSThread()->GetThreadId() == tid) {
703         success = SuspendVM(hostVm);
704         LOG_ECMA(INFO) << "The main thread, SuspendVMById succeeded: " << success;
705         return success;
706     } else {
707         success = hostVm->SuspendWorkerVm(tid);
708         LOG_ECMA(INFO) << "The worker thread, SuspendVMById succeeded: " << success;
709         return success;
710     }
711 }
712 
StartTracing(const EcmaVM * vm,std::string & categories)713 bool DFXJSNApi::StartTracing([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] std::string &categories)
714 {
715 #if defined(ECMASCRIPT_SUPPORT_TRACING)
716     if (vm == nullptr) {
717         return false;
718     }
719     Tracing *tracing = vm->GetTracing();
720     if (tracing == nullptr) {
721         tracing = new Tracing(vm);
722         const_cast<EcmaVM *>(vm)->SetTracing(tracing);
723     }
724     tracing->StartTracing(categories);
725     return true;
726 #else
727     LOG_ECMA(ERROR) << "Not support arkcompiler tracing";
728     return false;
729 #endif
730 }
731 
StopTracing(const EcmaVM * vm)732 std::unique_ptr<std::vector<TraceEvent>> DFXJSNApi::StopTracing([[maybe_unused]] const EcmaVM *vm)
733 {
734 #if defined(ECMASCRIPT_SUPPORT_TRACING)
735     if (vm == nullptr) {
736         return nullptr;
737     }
738     Tracing *tracing = vm->GetTracing();
739     if (tracing == nullptr) {
740         LOG_ECMA(ERROR) << "StopTracing tracing is nullptr";
741         return nullptr;
742     }
743     auto traceEvents = tracing->StopTracing();
744     if (traceEvents == nullptr) {
745         LOG_ECMA(ERROR) << "trace events is nullptr";
746     }
747     delete tracing;
748     tracing = nullptr;
749     const_cast<EcmaVM *>(vm)->SetTracing(nullptr);
750     return traceEvents;
751 #else
752     LOG_ECMA(ERROR) << "Not support arkcompiler tracing";
753     return nullptr;
754 #endif
755 }
756 
GetTracingBufferUseage(const EcmaVM * vm,double & percentFull,uint32_t & eventCount,double & value)757 void DFXJSNApi::GetTracingBufferUseage([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] double &percentFull,
758                                        [[maybe_unused]] uint32_t &eventCount, [[maybe_unused]] double &value)
759 {
760 #if defined(ECMASCRIPT_SUPPORT_TRACING)
761     if (vm == nullptr) {
762         return;
763     }
764     ecmascript::Tracing *tracing = vm->GetTracing();
765     if (tracing == nullptr) {
766         LOG_ECMA(ERROR) << "GetTracingBufferUseage tracing is nullptr";
767     } else {
768         tracing->GetBufferUseage(percentFull, eventCount, value);
769     }
770 #else
771     LOG_ECMA(ERROR) << "Not support arkcompiler tracing";
772 #endif
773 }
774 } // namespace panda
775