add heapProfiler and getBackTrace napi

Signed-off-by: shikai <shikai25@huawei.com>
This commit is contained in:
shikai 2022-01-14 16:35:06 +08:00
parent bb19fcf0ab
commit 7a9e23bcf4
12 changed files with 159 additions and 13 deletions

View File

@ -370,6 +370,7 @@ ecma_source = [
"ecmascript/mem/space.cpp",
"ecmascript/mem/verification.cpp",
"ecmascript/napi/jsnapi.cpp",
"ecmascript/napi/dfx_jsnapi.cpp",
"ecmascript/object_factory.cpp",
"ecmascript/object_operator.cpp",
"ecmascript/platform/platform.cpp",

View File

@ -230,4 +230,13 @@ CString ErrorHelper::BuildNativeEcmaStackTrace(JSThread *thread)
return data;
}
std::string ErrorHelper::BuildNativeAndJsBackStackTrace(JSThread *thread)
{
CString data = BuildNativeEcmaStackTrace(thread);
std::string temp = CstringConvertToString(data);
std::string result = nullptr;
result += temp;
return result;
}
} // namespace panda::ecmascript::base

View File

@ -33,6 +33,7 @@ public:
static CString BuildNativeEcmaStackTrace(JSThread *thread);
static std::string BuildNativeAndJsBackStackTrace(JSThread *thread);
private:
static CString DecodeFunctionName(const CString &name);
static JSHandle<EcmaString> BuildEcmaStackTrace(JSThread *thread);

View File

@ -285,7 +285,7 @@ bool CpuProfiler::CheckFileName(const std::string &fileName, std::string &absolu
CVector<char> resolvedPath(PATH_MAX);
realpath(fileName.c_str(), resolvedPath.data());
std::ifstream file(resolvedPath.data());
std::ofstream file(resolvedPath.data());
if (!file.good()) {
return false;
}

View File

@ -34,7 +34,7 @@ HeapProfiler::~HeapProfiler()
jsonSerializer_ = nullptr;
}
bool HeapProfiler::DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, const CString &filePath, bool isVmMode)
bool HeapProfiler::DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, const std::string &filePath, bool isVmMode)
{
[[maybe_unused]] bool heapClean = ForceFullGC(thread);
ASSERT(heapClean);
@ -68,7 +68,7 @@ bool HeapProfiler::StartHeapTracking(JSThread *thread, double timeInterval, bool
return true;
}
bool HeapProfiler::StopHeapTracking(JSThread *thread, DumpFormat dumpFormat, const CString &path)
bool HeapProfiler::StopHeapTracking(JSThread *thread, DumpFormat dumpFormat, const std::string &path)
{
if (heapTracker_ == nullptr) {
return false;
@ -93,7 +93,7 @@ bool HeapProfiler::StopHeapTracking(JSThread *thread, DumpFormat dumpFormat, con
return jsonSerializer_->Serialize(snapShot, realPath.second);
}
std::pair<bool, CString> HeapProfiler::FilePathValid(const CString &filePath)
std::pair<bool, CString> HeapProfiler::FilePathValid(const std::string &filePath)
{
if (filePath.size() > PATH_MAX) {
return std::make_pair(false, "");
@ -106,7 +106,7 @@ std::pair<bool, CString> HeapProfiler::FilePathValid(const CString &filePath)
return std::make_pair(false, "");
}
CString HeapProfiler::GenDumpFileName(DumpFormat dumpFormat)
std::string HeapProfiler::GenDumpFileName(DumpFormat dumpFormat)
{
CString filename("hprof_");
switch (dumpFormat) {
@ -124,7 +124,7 @@ CString HeapProfiler::GenDumpFileName(DumpFormat dumpFormat)
break;
}
filename.append(".heapsnapshot");
return filename;
return CstringConvertToString(filename);
}
CString HeapProfiler::GetTimeStamp()

View File

@ -44,11 +44,11 @@ public:
/**
* dump the specific snapshot in target format
*/
bool DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, const CString &path, bool isVmMode = true);
bool DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, const std::string &path, bool isVmMode = true);
void AddSnapShot(HeapSnapShot *snapshot);
bool StartHeapTracking(JSThread *thread, double timeInterval, bool isVmMode = true) override;
bool StopHeapTracking(JSThread *thread, DumpFormat dumpFormat, const CString &filePath) override;
bool StopHeapTracking(JSThread *thread, DumpFormat dumpFormat, const std::string &filePath) override;
private:
/**
@ -60,8 +60,8 @@ private:
* make a new heap snapshot and put it into a container eg, vector
*/
HeapSnapShot *MakeHeapSnapShot(JSThread *thread, SampleType sampleType, bool isVmMode = true);
std::pair<bool, CString> FilePathValid(const CString &filePath);
CString GenDumpFileName(DumpFormat dumpFormat);
std::pair<bool, CString> FilePathValid(const std::string &filePath);
std::string GenDumpFileName(DumpFormat dumpFormat);
CString GetTimeStamp();
void ClearSnapShot();

View File

@ -18,8 +18,17 @@
#include "ecmascript/mem/heap.h"
namespace panda::ecmascript {
HeapProfilerInterface *HeapProfilerInterface::heapProfile_ = nullptr;
HeapProfilerInterface *HeapProfilerInterface::GetInstance(JSThread *thread)
{
if (HeapProfilerInterface::heapProfile_ == nullptr) {
heapProfile_ = HeapProfilerInterface::CreateHeapProfiler(thread);
}
return HeapProfilerInterface::heapProfile_;
}
void HeapProfilerInterface::DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat,
const CString &filePath, bool isVmMode)
const std::string &filePath, bool isVmMode)
{
LOG(ERROR, RUNTIME) << "HeapProfilerInterface::DumpHeapSnapshot";
const Heap *heap = thread->GetEcmaVM()->GetHeap();

View File

@ -24,8 +24,9 @@ enum class DumpFormat { JSON, BINARY, OTHER };
class HeapProfilerInterface {
public:
static HeapProfilerInterface *GetInstance(JSThread *thread);
static void DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat,
const CString &filePath, bool isVmMode = true);
const std::string &filePath, bool isVmMode = true);
static HeapProfilerInterface *CreateHeapProfiler(JSThread *thread);
static void Destroy(JSThread *thread, HeapProfilerInterface *heapProfiler);
@ -34,10 +35,12 @@ public:
virtual ~HeapProfilerInterface() = default;
virtual bool StartHeapTracking(JSThread *thread, double timeInterval, bool isVmMode = true) = 0;
virtual bool StopHeapTracking(JSThread *thread, DumpFormat dumpFormat, const CString &filePath) = 0;
virtual bool StopHeapTracking(JSThread *thread, DumpFormat dumpFormat, const std::string &filePath) = 0;
NO_MOVE_SEMANTIC(HeapProfilerInterface);
NO_COPY_SEMANTIC(HeapProfilerInterface);
private:
static HeapProfilerInterface *heapProfile_;
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_HPROF_HEAP_PROFILER_INTERFACE_H

View File

@ -123,4 +123,14 @@ CString ConvertToString(JSTaggedValue key)
return ConvertToString(EcmaString::ConstCast(desc.GetTaggedObject()));
}
std::string CstringConvertToString(const CString &str)
{
std::string res;
res.reserve(str.size());
for (auto c : str) {
res.push_back(c);
}
return res;
}
} // namespace panda::ecmascript

View File

@ -39,6 +39,7 @@ float CStringToF(const CString &str);
double CStringToD(const CString &str);
CString ConvertToString(const std::string &str);
std::string CstringConvertToString(const CString &str);
// '\u0000' is skip according to holdZero
CString ConvertToString(const ecmascript::EcmaString *s, StringConvertedUsage usage = StringConvertedUsage::PRINT);

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2021 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.
*/
#include "ecmascript/napi/include/dfx_jsnapi.h"
#include "ecmascript/ecma_module.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/hprof/heap_profiler.h"
namespace panda {
using ecmascript::CString;
using ecmascript::EcmaString;
using ecmascript::JSTaggedValue;
template<typename T>
using JSHandle = ecmascript::JSHandle<T>;
void DFXJSNApi::DumpHeapSnapShot(EcmaVM *vm, int dumpFormat, const std::string &path, bool isVmMode)
{
if (dumpFormat == 0) {
ecmascript::HeapProfilerInterface::DumpHeapSnapShot(vm->GetJSThread(), ecmascript::DumpFormat::JSON,
path, isVmMode);
} else if (dumpFormat == 1) {
ecmascript::HeapProfilerInterface::DumpHeapSnapShot(vm->GetJSThread(), ecmascript::DumpFormat::BINARY,
path, isVmMode);
} else if (dumpFormat == 2) { // 2: enum is 2
ecmascript::HeapProfilerInterface::DumpHeapSnapShot(vm->GetJSThread(), ecmascript::DumpFormat::OTHER,
path, isVmMode);
}
}
std::string DFXJSNApi::BuildNativeAndJsBackStackTrace(EcmaVM *vm)
{
std::string result = ecmascript::base::ErrorHelper::BuildNativeAndJsBackStackTrace(vm->GetJSThread());
return result;
}
bool DFXJSNApi::StartHeapTracking(EcmaVM *vm, double timeInterval, bool isVmMode)
{
ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(vm->GetJSThread());
return heapProfile->StartHeapTracking(vm->GetJSThread(), timeInterval, isVmMode);
}
bool DFXJSNApi::StopHeapTracking(EcmaVM *vm, int dumpFormat, const std::string &filePath)
{
bool result = false;
ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(vm->GetJSThread());
if (dumpFormat == 0) {
result = heapProfile->StopHeapTracking(vm->GetJSThread(), ecmascript::DumpFormat::JSON, filePath);
}
if (dumpFormat == 1) {
result = heapProfile->StopHeapTracking(vm->GetJSThread(), ecmascript::DumpFormat::BINARY, filePath);
}
if (dumpFormat == 2) { // 2: enum is 2
result = heapProfile->StopHeapTracking(vm->GetJSThread(), ecmascript::DumpFormat::OTHER, filePath);
}
const ecmascript::Heap *heap = vm->GetJSThread()->GetEcmaVM()->GetHeap();
const_cast<ecmascript::RegionFactory *>(heap->GetRegionFactory())->Delete(heapProfile);
return result;
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2021 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 <string>
#include <vector>
#include "ecmascript/common.h"
#include "libpandabase/macros.h"
namespace panda {
namespace ecmascript {
class EcmaVM;
}
class DFXJSNApi;
using EcmaVM = ecmascript::EcmaVM;
class PUBLIC_API DFXJSNApi {
public:
static void DumpHeapSnapShot(EcmaVM *vm, int dumpFormat, const std::string &path, bool isVmMode = true);
static std::string BuildNativeAndJsBackStackTrace(EcmaVM *vm);
static bool StartHeapTracking(EcmaVM *vm, double timeInterval, bool isVmMode = true);
static bool StopHeapTracking(EcmaVM *vm, int dumpFormat, const std::string &filePath);
};
}
#endif