* Copyright (c) 2021-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_NAPI_INCLUDE_DFX_JSNAPI_H
#define ECMASCRIPT_NAPI_INCLUDE_DFX_JSNAPI_H
#include <cassert>
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <atomic>
#include "ecmascript/common.h"
#include "ecmascript/dfx/hprof/file_stream.h"
#include "ecmascript/dfx/hprof/heap_profiler_interface.h"
#include "ecmascript/napi/include/jsnapi_expo.h"
#include "libpandabase/macros.h"
namespace panda {
namespace ecmascript {
class EcmaVM;
class JSTaggedValue;
template<typename T>
class JSHandle;
class Stream;
class Progress;
struct ProfileInfo;
struct JsFrameInfo;
struct SamplingInfo;
struct TraceEvent;
enum class RawHeapDumpCropLevel;
}
class DFXJSNApi;
class JSValueRef;
template<typename T>
class Local;
using EcmaVM = ecmascript::EcmaVM;
using JSTaggedValue = ecmascript::JSTaggedValue;
using Stream = ecmascript::Stream;
using Progress = ecmascript::Progress;
using ProfileInfo = ecmascript::ProfileInfo;
using JsFrameInfo = ecmascript::JsFrameInfo;
using SamplingInfo = ecmascript::SamplingInfo;
using DebuggerPostTask = std::function<void(std::function<void()> &&)>;
using TraceEvent = ecmascript::TraceEvent;
using AppFreezeFilterCallback =
std::function<bool(const int32_t pid, const bool needDecreaseQuota, std::string &eventConfig)>;
using DumpSnapShotOption = ecmascript::DumpSnapShotOption;
using DumpFormat = ecmascript::DumpFormat;
using CropLevel = ecmascript::RawHeapDumpCropLevel;
struct GCStatistic {
size_t count {0};
float maxPause {0.0f};
float minPause {0.0f};
float averagePause {0.0f};
uint64_t lastStartTime {0};
uint64_t lastEndTime {0};
const char *lastType {"UnknownType"};
};
struct DumpForSnapShotStruct {
const EcmaVM *vm;
DumpSnapShotOption dumpOption;
uint32_t tid {0};
};
class PUBLIC_API DFXJSNApi {
public:
static void DumpHeapSnapshot(const EcmaVM *vm, const std::string &path, const DumpSnapShotOption &dumpOption,
const std::function<void(uint8_t)> &callback = nullptr);
static void DumpHeapSnapshot(const EcmaVM *vm, Stream *stream, const DumpSnapShotOption &dumpOption,
Progress *progress = nullptr,
std::function<void(uint8_t)> callback = [] (uint8_t) {});
static void DumpCpuProfile(const EcmaVM *vm);
static void DumpHeapSnapshot(const EcmaVM *vm, const DumpSnapShotOption &dumpOption);
static void DumpHeapSnapshot(const EcmaVM *vm, const DumpSnapShotOption &dumpOption, uint32_t tid);
static void DumpHeapSnapshotWithVm(const EcmaVM *vm, const DumpSnapShotOption &dumpOption, uint32_t tid);
static bool PerformHybridHeapDump(const EcmaVM *vm, const DumpSnapShotOption &dumpOption);
static bool PerformHybridHeapDump(const EcmaVM *vm, Stream *stream, const DumpSnapShotOption &dumpOption);
static void ScheduleHybridHeapDump(const EcmaVM *vm, const DumpSnapShotOption &dumpOption, uint32_t tid);
static void ScheduleHybridDumpOnLoop(const EcmaVM *vm, const DumpSnapShotOption &dumpOption, uint32_t tid);
static void TriggerGC(const EcmaVM *vm, uint32_t tid);
static void TriggerGCWithVm(const EcmaVM *vm);
static void TriggerLocalCCWithVmForTest(const EcmaVM *vm);
static void TriggerSharedGCWithVm(const EcmaVM *vm);
static void DestroyHeapProfiler(const EcmaVM *vm);
static bool BuildNativeAndJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr);
static bool BuildJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr);
static bool StartHeapTracking(const EcmaVM *vm, double timeInterval, bool isVmMode = true,
Stream *stream = nullptr, bool traceAllocation = false, bool newThread = true);
static bool UpdateHeapTracking(const EcmaVM *vm, Stream *stream);
static bool StopHeapTracking(const EcmaVM *vm, const std::string &filePath, bool newThread = true);
static bool StopHeapTracking(const EcmaVM *vm, Stream *stream, Progress *progress = nullptr, bool newThread = true);
static void PrintStatisticResult(const EcmaVM *vm);
static void StartRuntimeStat(EcmaVM *vm);
static void StopRuntimeStat(EcmaVM *vm);
static size_t GetArrayBufferSize(const EcmaVM *vm);
static size_t GetHeapTotalSize(const EcmaVM *vm);
static size_t GetHeapUsedSize(const EcmaVM *vm);
static size_t GetHeapObjectSize(const EcmaVM *vm);
static size_t GetSharedHeapSize();
static size_t GetHeapLimitSize(const EcmaVM *vm);
static size_t GetProcessHeapLimitSize();
static size_t GetGCCount(const EcmaVM *vm);
static size_t GetGCDuration(const EcmaVM *vm);
static size_t GetAccumulatedAllocateSize(const EcmaVM *vm);
static size_t GetAccumulatedFreeSize(const EcmaVM *vm);
static size_t GetFullGCLongTimeCount(const EcmaVM *vm);
static GCStatistic GetGCStatistic(const EcmaVM *vm);
static void GetHeapPrepare(const EcmaVM *vm);
static void NotifyApplicationState(EcmaVM *vm, bool inBackground);
static void NotifyIdleStatusControl(const EcmaVM *vm, std::function<void(bool)> callback);
static void NotifyIdleTime(const EcmaVM *vm, int idleMicroSec);
static void NotifyMemoryPressure(EcmaVM *vm, bool inHighMemoryPressure);
static void NotifyFinishColdStart(EcmaVM *vm, [[maybe_unused]] bool isConvinced);
static void NotifyHighSensitive(EcmaVM *vm, bool isStart);
static void NotifyWarmStart(EcmaVM *vm);
static bool BuildJsStackInfoList(const EcmaVM *hostVm, uint32_t tid, std::vector<JsFrameInfo>& jsFrames);
static int32_t GetObjectHash(const EcmaVM *vm, Local<JSValueRef> nativeObject);
static int32_t GetObjectHashCode(const EcmaVM *vm, Local<JSValueRef> nativeObject);
static std::pair<std::string, std::uint32_t> GetAnonymizeExtraErrorMessage(const EcmaVM *vm, uint32_t width);
static void ClearExtraErrorMessage(const EcmaVM *vm);
static std::string GetExtraJSCrashMessage(const EcmaVM* vm);
static bool StopCpuProfilerForColdStart(const EcmaVM *vm);
static bool CpuProfilerSamplingAnyTime(const EcmaVM *vm);
static void CpuProfilerAnyTimeMainThread(const EcmaVM *vm);
static void SetJsDumpThresholds(EcmaVM *vm, size_t thresholds);
static void SetAppFreezeFilterCallback(const EcmaVM *vm, AppFreezeFilterCallback cb);
static bool StartCpuProfilerForFile(const EcmaVM *vm, const std::string &fileName,
int interval = 500);
static void StopCpuProfilerForFile(const EcmaVM *vm);
static bool StartCpuProfilerForInfo(const EcmaVM *vm,
int interval = 500);
static std::unique_ptr<ProfileInfo> StopCpuProfilerForInfo(const EcmaVM *vm);
static void EnableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM, int32_t threshold);
static void DisableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM);
enum class PUBLIC_API ProfilerType : uint8_t { CPU_PROFILER, HEAP_PROFILER };
struct PUBLIC_API HeapMemoryPressureOptions {
double localHeapThreshold;
double sharedHeapThreshold;
double processHeapThreshold;
};
struct PUBLIC_API MultithreadingDetectionOptions {
std::atomic<bool> abort{true};
std::atomic<int64_t> frequency{100};
std::atomic<int64_t> interval{5};
MultithreadingDetectionOptions() = default;
MultithreadingDetectionOptions(bool abort_, int64_t frequency_, int64_t interval_)
: abort(abort_), frequency(frequency_), interval(interval_) {}
};
struct ProfilerOption {
const char *libraryPath;
int interval = 500;
ProfilerType profilerType = ProfilerType::CPU_PROFILER;
};
static bool StartProfiler(EcmaVM *vm, const ProfilerOption &option, int tid,
int32_t instanceId, const DebuggerPostTask &debuggerPostTask, bool isDebugApp);
static void SetCpuSamplingInterval(const EcmaVM *vm, int interval);
static bool StartSampling(const EcmaVM *vm, uint64_t samplingInterval);
static const SamplingInfo *GetAllocationProfile(const EcmaVM *vm);
static void StopSampling(const EcmaVM *vm);
static void ResumeVM(const EcmaVM *vm);
static bool SuspendVM(const EcmaVM *vm);
static bool IsSuspended(const EcmaVM *vm);
static void TerminateExecution(const EcmaVM *vm);
static bool CheckSafepoint(const EcmaVM *vm);
static void ResumeVMById(EcmaVM *vm, uint32_t tid);
static bool SuspendVMById(EcmaVM *vm, uint32_t tid);
static bool StartTracing(const EcmaVM *vm, std::string &categories);
static std::unique_ptr<std::vector<TraceEvent>> StopTracing(const EcmaVM *vm);
static void GetTracingBufferUseage(const EcmaVM *vm, double &percentFull, uint32_t &eventCount, double &value);
static void TranslateJSStackInfo(const EcmaVM *vm, std::string &url, int32_t &line, int32_t &column,
std::string &packageName);
static uint32_t GetCurrentThreadId();
static void RegisterAsyncDetectCallBack(const EcmaVM *vm);
static void GetMainThreadStackTrace(const EcmaVM *vm, std::string &stackTraceStr);
static void SetMultithreadingDetectionEnabled(const EcmaVM *vm, bool enabled,
const MultithreadingDetectionOptions& options);
static const MultithreadingDetectionOptions &GetDetectionConfig();
static bool OnVMHeapMemoryPressure(const EcmaVM *vm, HeapMemoryPressureOptions options,
Local<FunctionRef> callback);
static void OffVMHeapMemoryPressure(const EcmaVM *vm);
static void GetHybridStackTrace(const EcmaVM *vm, std::string &stackTraceStr);
static void SetJsRawHeapCropLevel(CropLevel level);
static void SetProcDumpInSharedOOM(bool enable);
static ecmascript::JSHandle<JSTaggedValue> FindFunctionForHook(const EcmaVM *vm,
const std::string &recordName, const std::string &namespaceName,
const std::string &className, const std::string &funcName);
static void ReplaceFunctionForHook(const EcmaVM *vm, ecmascript::JSHandle<JSTaggedValue> &target,
ecmascript::JSHandle<JSTaggedValue> &hook, ecmascript::JSHandle<JSTaggedValue> &backup);
static bool LoadHookModule(const EcmaVM *vm);
static void SetEnableRuntimeAsyncStack(EcmaVM *vm, bool state);
static bool GetEnableRuntimeAsyncStack(const EcmaVM *vm);
};
}
#endif