!4898 Save abcId in ProfileType

Merge pull request !4898 from hzzhouzebin/SaveAbcIdInProfileType
This commit is contained in:
openharmony_ci 2023-09-27 02:20:06 +00:00 committed by Gitee
commit 4906107bce
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
24 changed files with 1017 additions and 592 deletions

View File

@ -370,7 +370,8 @@ std::shared_ptr<JSPandaFile> JSPandaFileManager::OpenJSPandaFileFromBuffer(uint8
std::shared_ptr<JSPandaFile> JSPandaFileManager::NewJSPandaFile(const panda_file::File *pf, const CString &desc)
{
std::shared_ptr<JSPandaFile> jsPandaFile = std::make_shared<JSPandaFile>(pf, desc);
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(jsPandaFile->GetChecksum());
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(jsPandaFile->GetChecksum(),
jsPandaFile->GetJSPandaFileDesc());
return jsPandaFile;
}

View File

@ -28,6 +28,8 @@
#include "ecmascript/patch/quick_fix_manager.h"
#include "ecmascript/pgo_profiler/pgo_profiler.h"
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "libpandafile/class_data_accessor-inl.h"
#include "libpandafile/index_accessor.h"
@ -312,7 +314,11 @@ public:
JSObject::DefinePropertyByLiteral(thread, obj, key, valueHandle);
}
if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
thread->GetEcmaVM()->GetPGOProfiler()->ProfileCreateObject(obj.GetTaggedType(), id.GetOffset());
pgo::ApEntityId abcId(0);
pgo::PGOProfilerManager::GetInstance()->GetPandaFileId(jsPandaFile->GetJSPandaFileDesc(),
abcId);
thread->GetEcmaVM()->GetPGOProfiler()->ProfileCreateObject(obj.GetTaggedType(), abcId,
id.GetOffset());
}
val = obj.GetTaggedValue();
break;

View File

@ -3692,6 +3692,7 @@ std::string JSNApi::GetBundleName(EcmaVM *vm)
void JSNApi::SetModuleName(EcmaVM *vm, const std::string &moduleName)
{
ecmascript::CString name = moduleName.c_str();
ecmascript::pgo::PGOProfilerManager::GetInstance()->SetModuleName(moduleName);
vm->SetModuleName(name);
}

View File

@ -102,16 +102,18 @@ public:
static constexpr VersionType ELEMENTS_KIND_MINI_VERSION = {0, 0, 0, 8};
static constexpr VersionType RECORD_POOL_MINI_VERSION = {0, 0, 0, 9};
static constexpr VersionType WIDE_CLASS_TYPE_MINI_VERSION = {0, 0, 0, 10};
static constexpr VersionType PROFILE_TYPE_WITH_ABC_ID_MINI_VERSION = {0, 0, 0, 11};
static constexpr VersionType FILE_SIZE_MINI_VERSION = FILE_CONSISTENCY_MINI_VERSION;
static constexpr VersionType HEADER_SIZE_MINI_VERSION = FILE_CONSISTENCY_MINI_VERSION;
static constexpr VersionType ELASTIC_HEADER_MINI_VERSION = FILE_CONSISTENCY_MINI_VERSION;
static constexpr VersionType LAST_VERSION = {0, 0, 0, 10};
static constexpr size_t SECTION_SIZE = 5;
static constexpr VersionType LAST_VERSION = {0, 0, 0, 11};
static constexpr size_t SECTION_SIZE = 6;
static constexpr size_t PANDA_FILE_SECTION_INDEX = 0;
static constexpr size_t RECORD_INFO_SECTION_INDEX = 1;
static constexpr size_t LAYOUT_DESC_SECTION_INDEX = 2;
static constexpr size_t RECORD_POOL_SECTION_INDEX = 3;
static constexpr size_t CLASS_TYPE_POOL_SECTION_INDEX = 4;
static constexpr size_t ABC_FILE_POOL_SECTION_INDEX = 5;
PGOProfilerHeader() : base::FileHeaderElastic(LAST_VERSION), sectionNumber_(SECTION_SIZE)
{
@ -203,6 +205,11 @@ public:
return GetSectionInfo(CLASS_TYPE_POOL_SECTION_INDEX);
}
SectionInfo *GetAbcFilePoolSection() const
{
return GetSectionInfo(ABC_FILE_POOL_SECTION_INDEX);
}
bool SupportType() const
{
return CompatibleVerify(TYPE_MINI_VERSION);
@ -253,6 +260,11 @@ public:
return CompatibleVerify(WIDE_CLASS_TYPE_MINI_VERSION);
}
bool SupportProfileTypeWithAbcId() const
{
return CompatibleVerify(PROFILE_TYPE_WITH_ABC_ID_MINI_VERSION);
}
NO_COPY_SEMANTIC(PGOProfilerHeader);
NO_MOVE_SEMANTIC(PGOProfilerHeader);
@ -293,7 +305,7 @@ public:
PGOFileDataInterface() = default;
virtual ~PGOFileDataInterface() = default;
virtual uint32_t ProcessToBinary(std::fstream &stream) = 0;
virtual uint32_t ParseFromBinary(void **buffer, PGOProfilerHeader *const header) = 0;
virtual uint32_t ParseFromBinary(void **buffer, PGOProfilerHeader const *header) = 0;
virtual bool ProcessToText(std::ofstream &stream) = 0;
// not support yet
virtual bool ParseFromText([[maybe_unused]] std::ifstream &stream)
@ -305,5 +317,43 @@ private:
NO_COPY_SEMANTIC(PGOFileDataInterface);
NO_MOVE_SEMANTIC(PGOFileDataInterface);
};
class PGOFileSectionInterface : public PGOFileDataInterface {
public:
PGOFileSectionInterface() = default;
~PGOFileSectionInterface() override = default;
virtual bool Support(PGOProfilerHeader const *header) const = 0;
virtual SectionInfo *GetSection(PGOProfilerHeader const *header) const = 0;
static bool ParseSectionFromBinary(void *buffer, PGOProfilerHeader const *header, PGOFileSectionInterface &section)
{
if (section.Support(header)) {
SectionInfo *info = section.GetSection(header);
if (info == nullptr) {
return false;
}
void *addr = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + info->offset_);
section.ParseFromBinary(&addr, header);
}
return true;
}
static bool ProcessSectionToBinary(std::fstream &fileStream, PGOProfilerHeader *const header,
PGOFileSectionInterface &section)
{
auto *info = section.GetSection(header);
if (info == nullptr) {
return false;
}
info->offset_ = static_cast<uint32_t>(fileStream.tellp());
info->number_ = section.ProcessToBinary(fileStream);
info->size_ = static_cast<uint32_t>(fileStream.tellp()) - info->offset_;
return true;
}
private:
NO_COPY_SEMANTIC(PGOFileSectionInterface);
NO_MOVE_SEMANTIC(PGOFileSectionInterface);
};
} // namespace panda::ecmascript::pgo
#endif // ECMASCRIPT_PGO_PROFILER_AP_FILE_BASE_INFO_H

View File

@ -102,7 +102,7 @@ bool PGOMethodTypeSet::ProcessToBinary(PGOContext &context, std::stringstream &s
}
}
for (auto typeInfo : objDefOpTypeInfos_) {
for (const auto &typeInfo : objDefOpTypeInfos_) {
ObjDefOpTypeInfoRef infoRef(typeInfo.GetOffset(),
PGOSampleTypeRef::ConvertFrom(context, typeInfo.GetType()),
PGOSampleTypeRef::ConvertFrom(context, typeInfo.GetSuperType()));

View File

@ -18,180 +18,152 @@
#include <cstdint>
#include <fstream>
#include <memory>
#include <string>
#include <unordered_map>
#include "ecmascript/common.h"
#include "ecmascript/log.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/mem/c_string.h"
#include "ecmascript/mem/mem.h"
#include "ecmascript/pgo_profiler/ap_file/pgo_file_info.h"
#include "ecmascript/pgo_profiler/ap_file/pool_template.h"
#include "ecmascript/pgo_profiler/pgo_context.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "ecmascript/pgo_profiler/types/pgo_profile_type.h"
#include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
#include "macros.h"
namespace panda::ecmascript::pgo {
class PGOProfileTypePool : public PGOFileDataInterface {
class PGOProfileTypePool {
public:
class Entry {
class Entry : public PGOFileDataInterface {
public:
explicit Entry(ProfileType type) : type_(type) {}
Entry() = default;
ApEntityId GetEntryId() const
{
return id_;
return entryId_;
}
void SetId(ApEntityId id)
void SetEntryId(ApEntityId entryId)
{
id_ = id;
entryId_ = entryId;
}
const ProfileType &GetProfileType() const
ProfileType GetProfileType() const
{
return type_;
}
const ProfileType &GetData() const
{
return type_;
}
uint32_t ProcessToBinary(std::fstream &stream) override
{
auto profileType = type_.GetRaw();
stream.write(reinterpret_cast<const char *>(&(profileType)), sizeof(ProfileType));
return 1;
}
uint32_t ParseFromBinary(void **buffer, [[maybe_unused]] PGOProfilerHeader const *header) override
{
type_ = base::ReadBuffer<ProfileType>(buffer, sizeof(ProfileType));
return 1;
}
bool ProcessToText(std::ofstream &stream) override
{
stream << type_.GetTypeString();
return true;
}
private:
ApEntityId id_ {};
ApEntityId entryId_ {0};
ProfileType type_;
};
enum class ReservedType : uint8_t {
NONE_CLASS_TYPE_REF = 0,
END
};
using PoolType = PoolTemplate<Entry, ProfileType>;
enum class ReservedType : uint8_t { NONE_CLASS_TYPE_REF = 0, END };
static constexpr uint32_t RESERVED_COUNT = 64;
static_assert(static_cast<uint32_t>(ReservedType::END) < RESERVED_COUNT);
PGOProfileTypePool() = default;
~PGOProfileTypePool() override
static bool IsReserved(const ProfileType &value)
{
return value.IsNone();
}
static ApEntityId GetReservedId([[maybe_unused]] const ProfileType &value)
{
ASSERT(value.IsNone());
return ApEntityId(static_cast<uint32_t>(ReservedType::NONE_CLASS_TYPE_REF));
}
static bool Support(PGOProfilerHeader const *header)
{
return header->SupportWideProfileType();
}
static SectionInfo *GetSection(PGOProfilerHeader const *header)
{
return header->GetProfileTypeSection();
}
PGOProfileTypePool()
{
pool_ = std::make_shared<PoolType>("ProfileTypePool", RESERVED_COUNT);
pool_->SetIsReservedCb(IsReserved);
pool_->SetGetReservedIdCb(GetReservedId);
pool_->SetGetSectionCb(GetSection);
pool_->SetSupportCb(Support);
}
~PGOProfileTypePool()
{
Clear();
}
bool TryAdd(const ProfileType &profileType, ApEntityId &id)
bool TryAdd(const ProfileType &profileType, ApEntityId &entryId)
{
for (auto &record : pool_) {
if (record.second.GetProfileType() == profileType) {
id = record.second.GetEntryId();
return true;
}
}
id = ApEntityId(IsReserved(profileType) ? GetReservedId(profileType).GetOffset()
: RESERVED_COUNT + pool_.size());
auto result = pool_.emplace(id, profileType);
auto &record = result.first->second;
record.SetId(id);
return true;
return pool_->TryAdd(profileType, entryId);
}
bool GetRecordId(const ProfileType &profileType, ApEntityId &recordId) const
bool GetEntryId(const ProfileType &profileType, ApEntityId &entryId) const
{
for (auto [id, record] : pool_) {
if (record.GetProfileType() == profileType) {
recordId = id;
return true;
}
}
return false;
return pool_->GetEntryId(profileType, entryId);
}
const Entry *GetRecord(ApEntityId id) const
const Entry *GetEntry(ApEntityId entryId) const
{
auto iter = pool_.find(id);
if (iter == pool_.end()) {
return nullptr;
}
return &(iter->second);
return pool_->GetEntry(entryId);
}
void Clear()
{
pool_.clear();
pool_->Clear();
}
void Merge(const PGOProfileTypePool &recordPool, std::map<ApEntityId, ApEntityId> &idMapping)
void Merge(const PGOProfileTypePool &profileTypePool, std::map<ApEntityId, ApEntityId> &idMapping)
{
for (auto [id, record] : recordPool.pool_) {
ApEntityId apId;
TryAdd(record.GetProfileType(), apId);
idMapping.emplace(id, apId);
}
pool_->Merge(*profileTypePool.pool_, [&](ApEntityId oldEntryId, ApEntityId newEntryId) {
idMapping.try_emplace(oldEntryId, newEntryId);
});
}
uint32_t ProcessToBinary(std::fstream &stream) override
std::shared_ptr<PoolType> &GetPool()
{
SectionInfo secInfo;
secInfo.number_ = pool_.size();
secInfo.offset_ = sizeof(SectionInfo);
auto secInfoPos = stream.tellp();
stream.seekp(secInfo.offset_, std::ofstream::cur);
for (const auto &record : pool_) {
stream.write(reinterpret_cast<const char *>(&(record.first)), sizeof(ApEntityId));
auto profileType = record.second.GetProfileType().GetRaw();
stream.write(reinterpret_cast<const char *>(&(profileType)), sizeof(ProfileType));
}
secInfo.size_ = static_cast<uint32_t>(stream.tellp()) - static_cast<uint32_t>(secInfoPos);
auto tail = stream.tellp();
stream.seekp(secInfoPos, std::ofstream::beg);
stream.write(reinterpret_cast<const char *>(&(secInfo)), sizeof(SectionInfo));
stream.seekp(tail, std::ofstream::beg);
return tail - secInfoPos;
}
bool ProcessToText(std::ofstream &stream) override
{
std::string profilerString;
bool isFirst = true;
for (auto [id, record] : pool_) {
if (isFirst) {
profilerString += DumpUtils::NEW_LINE;
profilerString += "ProfileTypePool";
profilerString += DumpUtils::BLOCK_START;
isFirst = false;
}
profilerString += DumpUtils::NEW_LINE;
profilerString += std::to_string(id.GetOffset());
profilerString += DumpUtils::ELEMENT_SEPARATOR;
profilerString += record.GetProfileType().GetTypeString();
}
if (!isFirst) {
profilerString += (DumpUtils::SPACE + DumpUtils::NEW_LINE);
stream << profilerString;
}
return true;
}
uint32_t ParseFromBinary(void **buffer, [[maybe_unused]] PGOProfilerHeader *const header) override
{
auto *startBuffer = *buffer;
auto secInfo = base::ReadBuffer<SectionInfo>(buffer);
for (uint32_t i = 0; i < secInfo.number_; i++) {
auto recordId = base::ReadBuffer<ApEntityId>(buffer, sizeof(ApEntityId));
auto profileType = base::ReadBuffer<ProfileType>(buffer, sizeof(ProfileType));
auto result = pool_.emplace(recordId, profileType);
result.first->second.SetId(recordId);
}
return reinterpret_cast<uintptr_t>(*buffer) - reinterpret_cast<uintptr_t>(startBuffer);
return pool_;
}
private:
NO_COPY_SEMANTIC(PGOProfileTypePool);
NO_MOVE_SEMANTIC(PGOProfileTypePool);
static bool IsReserved(ProfileType type)
{
return type.IsNone();
}
static ApEntityId GetReservedId([[maybe_unused]] ProfileType type)
{
ASSERT(type.IsNone());
return ApEntityId(static_cast<uint32_t>(ReservedType::NONE_CLASS_TYPE_REF));
}
std::unordered_map<ApEntityId, Entry> pool_;
std::shared_ptr<PoolType> pool_;
};
} // namespace panda::ecmascript::pgo
} // namespace panda::ecmascript::pgo
#endif // ECMASCRIPT_PGO_PROFILER_AP_FILE_PGO_PROFILE_TYPE_POOL_H

View File

@ -19,176 +19,181 @@
#include <cstdint>
#include <fstream>
#include <unordered_map>
#include <memory>
#include "ecmascript/common.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/mem/c_string.h"
#include "ecmascript/pgo_profiler/ap_file/pgo_file_info.h"
#include "ecmascript/pgo_profiler/ap_file/pool_template.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "macros.h"
namespace panda::ecmascript::pgo {
class PGOProfilerHeader;
class PGORecordPool : public PGOFileDataInterface {
class PGOStringPool {
public:
class Entry {
class Entry : public PGOFileDataInterface {
public:
explicit Entry(CString name) : name_(std::move(name)) {}
Entry() = default;
ApEntityId GetEntryId() const
{
return id_;
return entryId_;
}
void SetId(ApEntityId id)
void SetEntryId(ApEntityId entryId)
{
id_ = id;
entryId_ = entryId;
}
const CString &GetRecordName() const
const CString &GetData() const
{
return name_;
}
uint32_t ProcessToBinary(std::fstream &stream) override
{
stream << name_ << '\0';
return 1;
}
uint32_t ParseFromBinary(void **buffer, [[maybe_unused]] PGOProfilerHeader const *header) override
{
name_ = base::ReadBuffer(buffer);
return 1;
}
bool ProcessToText(std::ofstream &stream) override
{
stream << name_;
return true;
}
private:
ApEntityId id_ {};
ApEntityId entryId_ {};
CString name_;
};
enum class ReservedType : uint8_t {
EMPTY_RECORD_ID = 0,
END
using PoolType = PoolTemplate<Entry, CString>;
PGOStringPool(const std::string &poolName, uint32_t reservedCount)
{
pool_ = std::make_shared<PoolType>(poolName, reservedCount);
};
static constexpr uint32_t RESERVED_COUNT = 64;
static_assert(static_cast<uint32_t>(ReservedType::END) < RESERVED_COUNT);
PGORecordPool() = default;
~PGORecordPool() override
~PGOStringPool()
{
Clear();
}
bool TryAdd(const CString &recordName, ApEntityId &id)
bool TryAdd(const CString &value, ApEntityId &entryId)
{
for (auto &record : pool_) {
if (record.second.GetRecordName() == recordName) {
id = record.second.GetEntryId();
return true;
}
}
id = ApEntityId(IsReserved(recordName) ? GetReservedId(recordName).GetOffset()
: RESERVED_COUNT + pool_.size());
auto result = pool_.emplace(id, recordName);
auto &record = result.first->second;
record.SetId(id);
return true;
return pool_->TryAdd(value, entryId);
}
bool GetRecordId(const CString &recordName, ApEntityId &recordId) const
bool GetEntryId(const CString &value, ApEntityId &entryId) const
{
for (auto [id, record] : pool_) {
if (record.GetRecordName() == recordName) {
recordId = id;
return true;
}
}
return false;
return pool_->GetEntryId(value, entryId);
}
const Entry *GetRecord(ApEntityId id) const
const Entry *GetEntry(ApEntityId entryId) const
{
auto iter = pool_.find(id);
if (iter == pool_.end()) {
return nullptr;
}
return &(iter->second);
return pool_->GetEntry(entryId);
}
void Clear()
{
pool_.clear();
pool_->Clear();
}
std::shared_ptr<PoolType> &GetPool()
{
return pool_;
}
protected:
NO_COPY_SEMANTIC(PGOStringPool);
NO_MOVE_SEMANTIC(PGOStringPool);
std::shared_ptr<PoolType> pool_;
};
class PGORecordPool : public PGOStringPool {
public:
enum class ReservedType : uint8_t { EMPTY_RECORD_ID = 0, END };
static constexpr uint32_t RESERVED_COUNT = 64;
static_assert(static_cast<uint32_t>(ReservedType::END) < RESERVED_COUNT);
static bool IsReserved(const CString &value)
{
return value.empty();
}
static ApEntityId GetReservedId([[maybe_unused]] const CString &value)
{
ASSERT(value.empty());
return ApEntityId(static_cast<uint32_t>(ReservedType::EMPTY_RECORD_ID));
}
static bool Support(PGOProfilerHeader const *header)
{
return header->SupportRecordPool();
}
static SectionInfo *GetSection(PGOProfilerHeader const *header)
{
return header->GetRecordPoolSection();
}
PGORecordPool() : PGOStringPool("RecordPool", RESERVED_COUNT)
{
pool_->SetIsReservedCb(IsReserved);
pool_->SetGetReservedIdCb(GetReservedId);
pool_->SetGetSectionCb(GetSection);
pool_->SetSupportCb(Support);
}
void Merge(const PGORecordPool &recordPool, std::map<ApEntityId, ApEntityId> &idMapping)
{
for (auto [oldId, record] : recordPool.pool_) {
ApEntityId newId;
TryAdd(record.GetRecordName(), newId);
idMapping.emplace(oldId, newId);
}
pool_->Merge(*recordPool.pool_,
[&](ApEntityId oldId, ApEntityId newId) { idMapping.try_emplace(oldId, newId); });
}
uint32_t ProcessToBinary(std::fstream &stream) override
{
SectionInfo secInfo;
secInfo.number_ = pool_.size();
secInfo.offset_ = sizeof(SectionInfo);
auto secInfoPos = stream.tellp();
stream.seekp(secInfo.offset_, std::ofstream::cur);
for (const auto &record : pool_) {
stream.write(reinterpret_cast<const char *>(&(record.first)), sizeof(ApEntityId));
stream << record.second.GetRecordName() << '\0';
}
secInfo.size_ = static_cast<uint32_t>(stream.tellp()) - static_cast<uint32_t>(secInfoPos);
auto tail = stream.tellp();
stream.seekp(secInfoPos, std::ofstream::beg);
stream.write(reinterpret_cast<const char *>(&(secInfo)), sizeof(SectionInfo));
stream.seekp(tail, std::ofstream::beg);
return tail - secInfoPos;
}
bool ProcessToText(std::ofstream &stream) override
{
std::string profilerString;
bool isFirst = true;
for (auto [id, record] : pool_) {
if (isFirst) {
profilerString += DumpUtils::NEW_LINE;
profilerString += "RecordPool";
profilerString += DumpUtils::BLOCK_START;
isFirst = false;
}
profilerString += DumpUtils::NEW_LINE;
profilerString += std::to_string(id.GetOffset());
profilerString += DumpUtils::ELEMENT_SEPARATOR;
profilerString += record.GetRecordName();
}
if (!isFirst) {
profilerString += (DumpUtils::SPACE + DumpUtils::NEW_LINE);
stream << profilerString;
}
return true;
}
uint32_t ParseFromBinary(void **buffer, [[maybe_unused]] PGOProfilerHeader *const header) override
{
auto *startBuffer = *buffer;
auto secInfo = base::ReadBuffer<SectionInfo>(buffer);
for (uint32_t i = 0; i < secInfo.number_; i++) {
auto recordId = base::ReadBuffer<ApEntityId>(buffer, sizeof(ApEntityId));
auto *recordName = base::ReadBuffer(buffer);
auto result = pool_.emplace(recordId, recordName);
result.first->second.SetId(recordId);
}
return reinterpret_cast<uintptr_t>(*buffer) - reinterpret_cast<uintptr_t>(startBuffer);
}
private:
NO_COPY_SEMANTIC(PGORecordPool);
NO_MOVE_SEMANTIC(PGORecordPool);
static bool IsReserved(const CString &recordName)
{
return recordName.empty();
}
static ApEntityId GetReservedId([[maybe_unused]]const CString &recordName)
{
ASSERT(recordName.empty());
return ApEntityId(static_cast<uint32_t>(ReservedType::EMPTY_RECORD_ID));
}
std::unordered_map<ApEntityId, Entry> pool_;
};
} // namespace panda::ecmascript::pgo
class PGOAbcFilePool : public PGOStringPool {
public:
enum class ReservedType : uint8_t { EMPTY_ABC_FILE_ID = 0, END };
static constexpr uint32_t RESERVED_COUNT = 64;
static_assert(static_cast<uint32_t>(ReservedType::END) < RESERVED_COUNT);
static bool IsReserved(const CString &value)
{
return value.empty();
}
static ApEntityId GetReservedId([[maybe_unused]] const CString &value)
{
ASSERT(value.empty());
return ApEntityId(static_cast<uint32_t>(ReservedType::EMPTY_ABC_FILE_ID));
}
static bool Support(PGOProfilerHeader const *header)
{
return header->SupportProfileTypeWithAbcId();
}
static SectionInfo *GetSection(PGOProfilerHeader const *header)
{
return header->GetAbcFilePoolSection();
}
PGOAbcFilePool() : PGOStringPool("AbcFilePool", RESERVED_COUNT)
{
pool_->SetIsReservedCb(IsReserved);
pool_->SetGetReservedIdCb(GetReservedId);
pool_->SetGetSectionCb(GetSection);
pool_->SetSupportCb(Support);
}
};
} // namespace panda::ecmascript::pgo
#endif // ECMASCRIPT_PGO_PROFILER_AP_FILE_PGO_RECORD_POOL_H

View File

@ -0,0 +1,225 @@
/*
* Copyright (c) 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_PGO_PROFILER_AP_FILE_POOL_TEMPLATE_H
#define ECMASCRIPT_PGO_PROFILER_AP_FILE_POOL_TEMPLATE_H
#include <cstdint>
#include <fstream>
#include <unordered_map>
#include <utility>
#include "ecmascript/common.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/mem/c_string.h"
#include "ecmascript/pgo_profiler/ap_file/pgo_file_info.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "macros.h"
namespace panda::ecmascript::pgo {
template <typename Entry, typename V>
class PoolTemplate : public PGOFileSectionInterface {
public:
using IsReservedCb = std::function<bool(const V &value)>;
using GetReservedIdCb = std::function<ApEntityId(const V &value)>;
using SupportCb = std::function<bool(PGOProfilerHeader const *header)>;
using GetSectionCb = std::function<SectionInfo *(PGOProfilerHeader const *header)>;
PoolTemplate(std::string poolName, uint32_t reservedCount)
: poolName_(std::move(poolName)), RESERVED_COUNT(reservedCount) {};
~PoolTemplate() override
{
Clear();
}
bool TryAdd(const V &value, ApEntityId &entryId)
{
for (auto &entry : pool_) {
if (entry.second.GetData() == value) {
entryId = entry.second.GetEntryId();
return true;
}
}
entryId = ApEntityId(IsReserved(value) ? (++reservedUsed_, GetReservedId(value))
: RESERVED_COUNT + pool_.size() - reservedUsed_);
auto result = pool_.emplace(entryId, value);
auto &entry = result.first->second;
entry.SetEntryId(entryId);
return true;
}
bool GetEntryId(const V &value, ApEntityId &entryId) const
{
for (const auto &entry : pool_) {
if (entry.second.GetData() == value) {
entryId = entry.first;
return true;
}
}
return false;
}
const Entry *GetEntry(ApEntityId id) const
{
auto iter = pool_.find(id);
if (iter == pool_.end()) {
return nullptr;
}
return &(iter->second);
}
void Clear()
{
pool_.clear();
reservedUsed_ = 0;
}
bool Empty() const
{
return pool_.empty();
}
void Merge(const PoolTemplate &pool, const std::function<void(ApEntityId, ApEntityId)> &callback)
{
for (const auto &entry : pool.pool_) {
ApEntityId newId(0);
TryAdd(entry.second.GetData(), newId);
if (callback != nullptr) {
callback(entry.first, newId);
}
}
}
uint32_t ProcessToBinary(std::fstream &stream) override
{
LOG_ECMA(DEBUG) << "ProcessToBinary. name: " << poolName_ << ", count: " << pool_.size();
SectionInfo secInfo;
secInfo.number_ = pool_.size();
secInfo.offset_ = sizeof(SectionInfo);
auto secInfoPos = stream.tellp();
stream.seekp(secInfo.offset_, std::ofstream::cur);
for (auto &entry : pool_) {
stream.write(reinterpret_cast<const char *>(&(entry.first)), sizeof(ApEntityId));
entry.second.ProcessToBinary(stream);
}
secInfo.size_ = static_cast<uint32_t>(stream.tellp()) - static_cast<uint32_t>(secInfoPos);
auto tail = stream.tellp();
stream.seekp(secInfoPos, std::ofstream::beg);
stream.write(reinterpret_cast<const char *>(&(secInfo)), sizeof(SectionInfo));
stream.seekp(tail, std::ofstream::beg);
return 1;
}
bool ProcessToText(std::ofstream &stream) override
{
bool isFirst = true;
for (auto &entry : pool_) {
if (isFirst) {
stream << DumpUtils::NEW_LINE;
stream << poolName_;
stream << DumpUtils::BLOCK_START;
isFirst = false;
}
stream << DumpUtils::NEW_LINE;
stream << std::to_string(entry.first);
stream << DumpUtils::SPACE;
stream << DumpUtils::ARRAY_START;
entry.second.ProcessToText(stream);
stream << DumpUtils::ARRAY_END;
}
if (!isFirst) {
stream << (DumpUtils::SPACE + DumpUtils::NEW_LINE);
}
return true;
}
uint32_t ParseFromBinary(void **buffer, PGOProfilerHeader const *header) override
{
auto secInfo = base::ReadBuffer<SectionInfo>(buffer);
for (uint32_t i = 0; i < secInfo.number_; i++) {
auto entryId = base::ReadBuffer<ApEntityId>(buffer, sizeof(ApEntityId));
auto result = pool_.try_emplace(entryId);
result.first->second.SetEntryId(entryId);
result.first->second.ParseFromBinary(buffer, header);
}
LOG_ECMA(DEBUG) << "ParseFromBinary. name: " << poolName_ << ", count: " << secInfo.number_;
return 1;
}
void SetIsReservedCb(const IsReservedCb &isReservedCb)
{
isReservedCb_ = isReservedCb;
}
void SetGetReservedIdCb(const GetReservedIdCb &getReservedIdCb)
{
getReservedIdCb_ = getReservedIdCb;
}
void SetSupportCb(const SupportCb &supportCb)
{
supportCb_ = supportCb;
}
void SetGetSectionCb(const GetSectionCb &getSectionCb)
{
getSectionCb_ = getSectionCb;
}
std::unordered_map<ApEntityId, Entry> &GetPool()
{
return pool_;
}
private:
NO_COPY_SEMANTIC(PoolTemplate);
NO_MOVE_SEMANTIC(PoolTemplate);
bool Support(PGOProfilerHeader const *header) const override
{
return supportCb_(header);
}
SectionInfo *GetSection(PGOProfilerHeader const *header) const override
{
return getSectionCb_(header);
}
bool IsReserved(const V &value)
{
return isReservedCb_(value);
}
ApEntityId GetReservedId(const V &value)
{
return getReservedIdCb_(value);
}
const std::string poolName_;
const uint32_t RESERVED_COUNT {};
uint32_t reservedUsed_ {0};
IsReservedCb isReservedCb_;
GetReservedIdCb getReservedIdCb_;
SupportCb supportCb_;
GetSectionCb getSectionCb_;
std::unordered_map<ApEntityId, Entry> pool_;
};
} // namespace panda::ecmascript::pgo
#endif // ECMASCRIPT_PGO_PROFILER_AP_FILE_POOL_TEMPLATE_H

View File

@ -25,7 +25,7 @@
#include "macros.h"
namespace panda::ecmascript::pgo {
class PGORecordPool;
class PGOAbcFilePool;
class PGOProfileTypePool;
class PGOProfilerHeader;
@ -33,7 +33,6 @@ class PGOContext {
public:
PGOContext() = default;
virtual ~PGOContext() = default;
virtual std::shared_ptr<PGORecordPool> GetRecordPool() const = 0;
virtual std::shared_ptr<PGOProfileTypePool> GetProfileTypePool() const = 0;
virtual uint32_t GetHotnessThreshold() const = 0;
virtual PGOProfilerHeader *GetHeader() const = 0;

View File

@ -21,9 +21,15 @@
#include "ecmascript/ic/profile_type_info.h"
#include "ecmascript/interpreter/interpreter-inl.h"
#include "ecmascript/js_function.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/pgo_profiler/pgo_context.h"
#include "ecmascript/pgo_profiler/pgo_profiler_info.h"
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
#include "ecmascript/pgo_profiler/types/pgo_profile_type.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "ecmascript/module/js_module_source_text.h"
#include "ecmascript/jspandafile/js_pandafile.h"
#include "macros.h"
namespace panda::ecmascript::pgo {
void PGOProfiler::ProfileCall(JSTaggedType callTarget, SampleMode mode, int32_t incCount)
@ -45,10 +51,11 @@ void PGOProfiler::ProfileCall(JSTaggedType callTarget, SampleMode mode, int32_t
return;
}
CString calleeRecordName = ConvertToString(calleeRecordNameValue);
recordInfos_->AddMethod(calleeRecordName, calleeMethod, mode, incCount);
ProfileType calleeRecordType = GetRecordProfileType(JSFunction::Cast(calleeFunc), calleeRecordName);
recordInfos_->AddMethod(calleeRecordType, calleeMethod, mode, incCount);
}
void PGOProfiler::ProfileCreateObject(JSTaggedType object, int32_t traceId)
void PGOProfiler::ProfileCreateObject(JSTaggedType object, ApEntityId abcId, int32_t traceId)
{
if (!isEnable_) {
return;
@ -58,7 +65,7 @@ void PGOProfiler::ProfileCreateObject(JSTaggedType object, int32_t traceId)
if (objectValue.IsJSObject()) {
auto hclass = objectValue.GetTaggedObject()->GetClass();
hclass->SetParent(vm_->GetJSThread(), JSTaggedValue::Undefined());
InsertLiteralId(JSTaggedType(hclass), traceId);
InsertLiteralTraceId(JSTaggedType(hclass), abcId, traceId);
}
}
@ -80,13 +87,13 @@ void PGOProfiler::ProfileDefineClass(JSTaggedType ctor)
auto traceId = ctorMethod->GetMethodId().GetOffset();
auto ctorMethodHClass = ctorFunc->GetClass();
ctorMethodHClass->SetParent(vm_->GetJSThread(), JSTaggedValue::Undefined());
InsertLiteralId(JSTaggedType(ctorFunc->GetClass()), traceId);
InsertLiteralTraceId(JSTaggedType(ctorFunc->GetClass()), GetMethodAbcId(ctorFunc), traceId);
auto prototype = ctorFunc->GetProtoOrHClass();
if (prototype.IsJSObject()) {
auto prototypeHClass = prototype.GetTaggedObject()->GetClass();
prototypeHClass->SetParent(vm_->GetJSThread(), JSTaggedValue::Undefined());
InsertLiteralId(JSTaggedType(prototypeHClass), traceId);
InsertLiteralTraceId(JSTaggedType(prototypeHClass), GetMethodAbcId(ctorFunc), traceId);
}
}
@ -203,7 +210,8 @@ void PGOProfiler::HandlePGOPreDump()
continue;
}
CString recordName = ConvertToString(recordNameValue);
ProfileByteCode(recordName, methodValue);
auto abcId = GetMethodAbcId(func);
ProfileByteCode(abcId, recordName, methodValue);
}
}
@ -227,7 +235,8 @@ void PGOProfiler::HandlePGODump()
continue;
}
CString recordName = ConvertToString(recordNameValue);
ProfileByteCode(recordName, methodValue);
auto abcId = GetMethodAbcId(func);
ProfileByteCode(abcId, recordName, methodValue);
methodCount_++;
current = PopFromProfileQueue();
}
@ -270,7 +279,7 @@ JSTaggedValue PGOProfiler::PopFromProfileQueue()
return result;
}
void PGOProfiler::ProfileByteCode(CString recordName, JSTaggedValue value)
void PGOProfiler::ProfileByteCode(ApEntityId abcId, const CString &recordName, JSTaggedValue value)
{
Method *method = Method::Cast(value.GetTaggedObject());
JSTaggedValue profileTypeInfoVal = method->GetProfileTypeInfo();
@ -290,49 +299,49 @@ void PGOProfiler::ProfileByteCode(CString recordName, JSTaggedValue value)
case EcmaOpcode::LDTHISBYNAME_IMM8_ID16:
case EcmaOpcode::LDOBJBYNAME_IMM8_ID16: {
uint8_t slotId = READ_INST_8_0();
DumpICByName(recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::LOAD);
DumpICByName(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::LOAD);
break;
}
case EcmaOpcode::LDTHISBYNAME_IMM16_ID16:
case EcmaOpcode::LDOBJBYNAME_IMM16_ID16: {
uint16_t slotId = READ_INST_16_0();
DumpICByName(recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::LOAD);
DumpICByName(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::LOAD);
break;
}
case EcmaOpcode::LDOBJBYVALUE_IMM8_V8:
case EcmaOpcode::LDTHISBYVALUE_IMM8: {
uint8_t slotId = READ_INST_8_0();
DumpICByValue(recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::LOAD);
DumpICByValue(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::LOAD);
break;
}
case EcmaOpcode::LDOBJBYVALUE_IMM16_V8:
case EcmaOpcode::LDTHISBYVALUE_IMM16: {
uint16_t slotId = READ_INST_16_0();
DumpICByValue(recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::LOAD);
DumpICByValue(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::LOAD);
break;
}
case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
case EcmaOpcode::STTHISBYNAME_IMM8_ID16: {
uint8_t slotId = READ_INST_8_0();
DumpICByName(recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::STORE);
DumpICByName(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::STORE);
break;
}
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
case EcmaOpcode::STTHISBYNAME_IMM16_ID16: {
uint16_t slotId = READ_INST_16_0();
DumpICByName(recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::STORE);
DumpICByName(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::STORE);
break;
}
case EcmaOpcode::STOBJBYVALUE_IMM8_V8_V8:
case EcmaOpcode::STTHISBYVALUE_IMM8_V8: {
uint8_t slotId = READ_INST_8_0();
DumpICByValue(recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::STORE);
DumpICByValue(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::STORE);
break;
}
case EcmaOpcode::STOBJBYVALUE_IMM16_V8_V8:
case EcmaOpcode::STTHISBYVALUE_IMM16_V8: {
uint16_t slotId = READ_INST_16_0();
DumpICByValue(recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::STORE);
DumpICByValue(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::STORE);
break;
}
// Op
@ -361,7 +370,7 @@ void PGOProfiler::ProfileByteCode(CString recordName, JSTaggedValue value)
case EcmaOpcode::STRICTNOTEQ_IMM8_V8:
case EcmaOpcode::STRICTEQ_IMM8_V8: {
uint8_t slotId = READ_INST_8_0();
DumpOpType(recordName, methodId, bcOffset, slotId, profileTypeInfo);
DumpOpType(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo);
break;
}
// Call
@ -376,13 +385,13 @@ void PGOProfiler::ProfileByteCode(CString recordName, JSTaggedValue value)
case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: {
uint8_t slotId = READ_INST_8_0();
DumpCall(recordName, methodId, bcOffset, slotId, profileTypeInfo);
DumpCall(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo);
break;
}
case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8:
case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: {
uint16_t slotId = READ_INST_16_0();
DumpCall(recordName, methodId, bcOffset, slotId, profileTypeInfo);
DumpCall(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo);
break;
}
case EcmaOpcode::NEWOBJRANGE_IMM8_IMM8_V8:
@ -393,12 +402,12 @@ void PGOProfiler::ProfileByteCode(CString recordName, JSTaggedValue value)
// Create object
case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: {
uint8_t slotId = READ_INST_8_0();
DumpDefineClass(recordName, methodId, bcOffset, slotId, profileTypeInfo);
DumpDefineClass(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo);
break;
}
case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
uint16_t slotId = READ_INST_16_0();
DumpDefineClass(recordName, methodId, bcOffset, slotId, profileTypeInfo);
DumpDefineClass(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo);
break;
}
case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
@ -408,7 +417,7 @@ void PGOProfiler::ProfileByteCode(CString recordName, JSTaggedValue value)
auto traceId =
static_cast<int32_t>(reinterpret_cast<uintptr_t>(pc) - reinterpret_cast<uintptr_t>(header));
uint8_t slotId = READ_INST_8_0();
DumpCreateObject(recordName, methodId, bcOffset, slotId, profileTypeInfo, traceId);
DumpCreateObject(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, traceId);
break;
}
case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16:
@ -418,7 +427,7 @@ void PGOProfiler::ProfileByteCode(CString recordName, JSTaggedValue value)
auto traceId =
static_cast<int32_t>(reinterpret_cast<uintptr_t>(pc) - reinterpret_cast<uintptr_t>(header));
uint16_t slotId = READ_INST_16_0();
DumpCreateObject(recordName, methodId, bcOffset, slotId, profileTypeInfo, traceId);
DumpCreateObject(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, traceId);
break;
}
case EcmaOpcode::DEFINEGETTERSETTERBYVALUE_V8_V8_V8_V8:
@ -429,8 +438,8 @@ void PGOProfiler::ProfileByteCode(CString recordName, JSTaggedValue value)
}
}
void PGOProfiler::DumpICByName(const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId,
ProfileTypeInfo *profileTypeInfo, BCType type)
void PGOProfiler::DumpICByName(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
uint32_t slotId, ProfileTypeInfo *profileTypeInfo, BCType type)
{
JSTaggedValue firstValue = profileTypeInfo->Get(slotId);
if (!firstValue.IsHeapObject()) {
@ -441,15 +450,15 @@ void PGOProfiler::DumpICByName(const CString &recordName, EntityId methodId, int
if (object->GetClass()->IsHClass()) {
JSTaggedValue secondValue = profileTypeInfo->Get(slotId + 1);
JSHClass *hclass = JSHClass::Cast(object);
DumpICByNameWithHandler(recordName, methodId, bcOffset, hclass, secondValue, type);
DumpICByNameWithHandler(abcId, recordName, methodId, bcOffset, hclass, secondValue, type);
}
return;
}
DumpICByNameWithPoly(recordName, methodId, bcOffset, firstValue, type);
DumpICByNameWithPoly(abcId, recordName, methodId, bcOffset, firstValue, type);
}
void PGOProfiler::DumpICByValue(const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId,
ProfileTypeInfo *profileTypeInfo, BCType type)
void PGOProfiler::DumpICByValue(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
uint32_t slotId, ProfileTypeInfo *profileTypeInfo, BCType type)
{
JSTaggedValue firstValue = profileTypeInfo->Get(slotId);
if (!firstValue.IsHeapObject()) {
@ -460,21 +469,21 @@ void PGOProfiler::DumpICByValue(const CString &recordName, EntityId methodId, in
if (object->GetClass()->IsHClass()) {
JSTaggedValue secondValue = profileTypeInfo->Get(slotId + 1);
JSHClass *hclass = JSHClass::Cast(object);
DumpICByValueWithHandler(recordName, methodId, bcOffset, hclass, secondValue, type);
DumpICByValueWithHandler(abcId, recordName, methodId, bcOffset, hclass, secondValue, type);
}
return;
}
// Check key
if ((firstValue.IsString() || firstValue.IsSymbol())) {
JSTaggedValue secondValue = profileTypeInfo->Get(slotId + 1);
DumpICByNameWithPoly(recordName, methodId, bcOffset, secondValue, type);
DumpICByNameWithPoly(abcId, recordName, methodId, bcOffset, secondValue, type);
return;
}
// Check without key
DumpICByValueWithPoly(recordName, methodId, bcOffset, firstValue, type);
DumpICByValueWithPoly(abcId, recordName, methodId, bcOffset, firstValue, type);
}
void PGOProfiler::DumpICByNameWithPoly(
void PGOProfiler::DumpICByNameWithPoly(ApEntityId abcId,
const CString &recordName, EntityId methodId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type)
{
if (cacheValue.IsWeak()) {
@ -494,11 +503,11 @@ void PGOProfiler::DumpICByNameWithPoly(
continue;
}
JSHClass *hclass = JSHClass::Cast(object);
DumpICByNameWithHandler(recordName, methodId, bcOffset, hclass, handler, type);
DumpICByNameWithHandler(abcId, recordName, methodId, bcOffset, hclass, handler, type);
}
}
void PGOProfiler::DumpICByValueWithPoly(
void PGOProfiler::DumpICByValueWithPoly(ApEntityId abcId,
const CString &recordName, EntityId methodId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type)
{
if (cacheValue.IsWeak()) {
@ -518,12 +527,12 @@ void PGOProfiler::DumpICByValueWithPoly(
continue;
}
JSHClass *hclass = JSHClass::Cast(object);
DumpICByValueWithHandler(recordName, methodId, bcOffset, hclass, handler, type);
DumpICByValueWithHandler(abcId, recordName, methodId, bcOffset, hclass, handler, type);
}
}
void PGOProfiler::DumpICByNameWithHandler(const CString &recordName, EntityId methodId, int32_t bcOffset,
JSHClass *hclass, JSTaggedValue secondValue, BCType type)
void PGOProfiler::DumpICByNameWithHandler(ApEntityId abcId, const CString &recordName, EntityId methodId,
int32_t bcOffset, JSHClass *hclass, JSTaggedValue secondValue, BCType type)
{
if (type == BCType::LOAD) {
if (secondValue.IsInt()) {
@ -532,18 +541,18 @@ void PGOProfiler::DumpICByNameWithHandler(const CString &recordName, EntityId me
return;
}
auto kind = PGOObjKind::LOCAL;
AddObjectInfo(recordName, methodId, bcOffset, hclass, kind);
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, kind);
}
if (secondValue.IsPrototypeHandler()) {
auto kind = PGOObjKind::PROTOTYPE;
AddObjectInfo(recordName, methodId, bcOffset, hclass, kind);
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, kind);
}
// LoadGlobal
return;
}
if (secondValue.IsInt()) {
auto kind = PGOObjKind::LOCAL;
AddObjectInfo(recordName, methodId, bcOffset, hclass, kind);
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, kind);
}
if (secondValue.IsTransitionHandler()) {
auto kind = PGOObjKind::LOCAL;
@ -551,7 +560,7 @@ void PGOProfiler::DumpICByNameWithHandler(const CString &recordName, EntityId me
auto transitionHClassVal = transitionHandler->GetTransitionHClass();
if (transitionHClassVal.IsJSHClass()) {
auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
AddObjectInfo(recordName, methodId, bcOffset, transitionHClass, kind);
AddObjectInfo(abcId, recordName, methodId, bcOffset, transitionHClass, kind);
}
}
if (secondValue.IsTransWithProtoHandler()) {
@ -560,7 +569,7 @@ void PGOProfiler::DumpICByNameWithHandler(const CString &recordName, EntityId me
auto transitionHClassVal = transWithProtoHandler->GetTransitionHClass();
if (transitionHClassVal.IsJSHClass()) {
auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
AddObjectInfo(recordName, methodId, bcOffset, transitionHClass, kind);
AddObjectInfo(abcId, recordName, methodId, bcOffset, transitionHClass, kind);
}
}
if (secondValue.IsTransitionHandler()) {
@ -569,12 +578,12 @@ void PGOProfiler::DumpICByNameWithHandler(const CString &recordName, EntityId me
auto transitionHClassVal = transitionHandler->GetTransitionHClass();
if (transitionHClassVal.IsJSHClass()) {
auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
AddObjectInfo(recordName, methodId, bcOffset, transitionHClass, kind);
AddObjectInfo(abcId, recordName, methodId, bcOffset, transitionHClass, kind);
}
}
if (secondValue.IsPrototypeHandler()) {
auto kind = PGOObjKind::PROTOTYPE;
AddObjectInfo(recordName, methodId, bcOffset, hclass, kind);
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, kind);
}
if (secondValue.IsPropertyBox()) {
// StoreGlobal
@ -588,12 +597,12 @@ void PGOProfiler::DumpICByNameWithHandler(const CString &recordName, EntityId me
return;
}
auto kind = PGOObjKind::LOCAL;
AddObjectInfo(recordName, methodId, bcOffset, hclass, kind);
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, kind);
}
}
void PGOProfiler::DumpICByValueWithHandler(const CString &recordName, EntityId methodId, int32_t bcOffset,
JSHClass *hclass, JSTaggedValue secondValue, BCType type)
void PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &recordName, EntityId methodId,
int32_t bcOffset, JSHClass *hclass, JSTaggedValue secondValue, BCType type)
{
if (type == BCType::LOAD) {
if (secondValue.IsInt()) {
@ -602,7 +611,7 @@ void PGOProfiler::DumpICByValueWithHandler(const CString &recordName, EntityId m
if (HandlerBase::IsJSArray(handlerInfo)) {
kind = PGOObjKind::ELEMENT;
}
AddObjectInfo(recordName, methodId, bcOffset, hclass, kind);
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, kind);
}
return;
}
@ -612,7 +621,7 @@ void PGOProfiler::DumpICByValueWithHandler(const CString &recordName, EntityId m
if (HandlerBase::IsJSArray(handlerInfo)) {
kind = PGOObjKind::ELEMENT;
}
AddObjectInfo(recordName, methodId, bcOffset, hclass, kind);
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, kind);
} else if (secondValue.IsTransitionHandler()) {
auto transitionHandler = TransitionHandler::Cast(secondValue.GetTaggedObject());
auto transitionHClassVal = transitionHandler->GetTransitionHClass();
@ -626,7 +635,7 @@ void PGOProfiler::DumpICByValueWithHandler(const CString &recordName, EntityId m
}
if (transitionHClassVal.IsJSHClass()) {
auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
AddObjectInfo(recordName, methodId, bcOffset, transitionHClass, kind);
AddObjectInfo(abcId, recordName, methodId, bcOffset, transitionHClass, kind);
}
} else if (secondValue.IsTransWithProtoHandler()) {
auto transWithProtoHandler = TransWithProtoHandler::Cast(secondValue.GetTaggedObject());
@ -641,7 +650,7 @@ void PGOProfiler::DumpICByValueWithHandler(const CString &recordName, EntityId m
}
if (transitionHClassVal.IsJSHClass()) {
auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
AddObjectInfo(recordName, methodId, bcOffset, transitionHClass, kind);
AddObjectInfo(abcId, recordName, methodId, bcOffset, transitionHClass, kind);
}
} else {
ASSERT(secondValue.IsPrototypeHandler());
@ -659,22 +668,23 @@ void PGOProfiler::DumpICByValueWithHandler(const CString &recordName, EntityId m
if (HandlerBase::IsJSArray(handlerInfo)) {
kind = PGOObjKind::ELEMENT;
}
AddObjectInfo(recordName, methodId, bcOffset, hclass, kind);
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, kind);
}
}
void PGOProfiler::DumpOpType(
const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId, ProfileTypeInfo *profileTypeInfo)
void PGOProfiler::DumpOpType(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
uint32_t slotId, ProfileTypeInfo *profileTypeInfo)
{
JSTaggedValue slotValue = profileTypeInfo->Get(slotId);
if (slotValue.IsInt()) {
auto type = slotValue.GetInt();
recordInfos_->AddType(recordName, methodId, bcOffset, PGOSampleType(type));
ProfileType recordType = GetRecordProfileType(abcId, recordName);
recordInfos_->AddType(recordType, methodId, bcOffset, PGOSampleType(type));
}
}
void PGOProfiler::DumpDefineClass(
const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId, ProfileTypeInfo *profileTypeInfo)
void PGOProfiler::DumpDefineClass(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
uint32_t slotId, ProfileTypeInfo *profileTypeInfo)
{
JSTaggedValue slotValue = profileTypeInfo->Get(slotId);
if (!slotValue.IsHeapObject() || !slotValue.IsWeak()) {
@ -687,21 +697,24 @@ void PGOProfiler::DumpDefineClass(
if (!ctorMethod.IsMethod()) {
return;
}
ApEntityId ctorAbcId = GetMethodAbcId(ctorFunction);
auto ctorJSMethod = Method::Cast(ctorMethod);
int32_t ctorMethodId = static_cast<int32_t>(ctorJSMethod->GetMethodId().GetOffset());
auto currentType = PGOSampleType::CreateProfileType(ctorMethodId);
auto currentType = PGOSampleType::CreateProfileType(ctorAbcId, ctorMethodId);
auto superFuncValue = ctorFunction->GetJSHClass()->GetPrototype();
PGOSampleType superType = PGOSampleType::CreateProfileType(0);
PGOSampleType superType(ProfileType::PROFILE_TYPE_NONE);
if (superFuncValue.IsJSFunction()) {
auto superFuncFunction = JSFunction::Cast(superFuncValue);
if (superFuncFunction->GetMethod().IsMethod()) {
ApEntityId superAbcId = GetMethodAbcId(superFuncFunction);
auto superMethod = Method::Cast(superFuncFunction->GetMethod());
auto superMethodId = superMethod->GetMethodId().GetOffset();
superType = PGOSampleType::CreateProfileType(superMethodId);
superType = PGOSampleType::CreateProfileType(superAbcId, superMethodId);
}
}
recordInfos_->AddDefine(recordName, methodId, bcOffset, currentType, superType);
ProfileType recordType = GetRecordProfileType(abcId, recordName);
recordInfos_->AddDefine(recordType, methodId, bcOffset, currentType, superType);
auto hclassValue = ctorFunction->GetProtoOrHClass();
if (!hclassValue.IsJSHClass()) {
@ -723,32 +736,34 @@ void PGOProfiler::DumpDefineClass(
}
}
void PGOProfiler::DumpCreateObject(const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId,
ProfileTypeInfo *profileTypeInfo, int32_t traceId)
void PGOProfiler::DumpCreateObject(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
uint32_t slotId, ProfileTypeInfo *profileTypeInfo, int32_t traceId)
{
JSTaggedValue slotValue = profileTypeInfo->Get(slotId);
if (!slotValue.IsHeapObject()) {
return;
}
ProfileType recordType = GetRecordProfileType(abcId, recordName);
if (slotValue.IsWeak()) {
auto object = slotValue.GetWeakReferentUnChecked();
if (object->GetClass()->IsHClass()) {
auto newHClass = JSHClass::Cast(object);
ASSERT(newHClass->IsJSObject());
auto iter = traceIds_.find(JSTaggedType(newHClass));
if (iter == traceIds_.end()) {
auto iter = tracedProfiles_.find(JSTaggedType(newHClass));
if (iter == tracedProfiles_.end()) {
return;
}
auto currentType = PGOSampleType::CreateProfileType(iter->second, ProfileType::Kind::LiteralId);
auto superType = PGOSampleType::CreateProfileType(0);
recordInfos_->AddDefine(recordName, methodId, bcOffset, currentType, superType);
ASSERT(iter->second.GetKind() == ProfileType::Kind::LiteralId);
PGOSampleType currentType(iter->second);
PGOSampleType superType(ProfileType::PROFILE_TYPE_NONE);
recordInfos_->AddDefine(recordType, methodId, bcOffset, currentType, superType);
PGOObjKind kind = PGOObjKind::LOCAL;
recordInfos_->AddLayout(currentType, JSTaggedType(newHClass), kind);
}
} else if (slotValue.IsTrackInfoObject()) {
auto currentType = PGOSampleType::CreateProfileType(traceId);
auto superType = PGOSampleType::CreateProfileType(0);
recordInfos_->AddDefine(recordName, methodId, bcOffset, currentType, superType);
auto currentType = PGOSampleType::CreateProfileType(abcId, traceId);
PGOSampleType superType(ProfileType::PROFILE_TYPE_NONE);
recordInfos_->AddDefine(recordType, methodId, bcOffset, currentType, superType);
TrackInfo *trackInfo = TrackInfo::Cast(slotValue.GetTaggedObject());
auto cachedHClass = trackInfo->GetCachedHClass();
if (cachedHClass.IsJSHClass()) {
@ -761,8 +776,8 @@ void PGOProfiler::DumpCreateObject(const CString &recordName, EntityId methodId,
}
}
void PGOProfiler::DumpCall(
const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId, ProfileTypeInfo *profileTypeInfo)
void PGOProfiler::DumpCall(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
uint32_t slotId, ProfileTypeInfo *profileTypeInfo)
{
JSTaggedValue slotValue = profileTypeInfo->Get(slotId);
if (!slotValue.IsInt()) {
@ -770,35 +785,37 @@ void PGOProfiler::DumpCall(
}
auto calleeMethodId = slotValue.GetInt();
PGOSampleType type = PGOSampleType::CreateProfileType(calleeMethodId);
recordInfos_->AddCallTargetType(recordName, methodId, bcOffset, type);
PGOSampleType type = PGOSampleType::CreateProfileType(abcId, calleeMethodId);
ProfileType recordType = GetRecordProfileType(abcId, recordName);
recordInfos_->AddCallTargetType(recordType, methodId, bcOffset, type);
}
void PGOProfiler::AddObjectInfo(
const CString &recordName, EntityId methodId, int32_t bcOffset, JSHClass *hclass, PGOObjKind kind)
void PGOProfiler::AddObjectInfo(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
JSHClass *hclass, PGOObjKind kind)
{
ProfileType recordType = GetRecordProfileType(abcId, recordName);
if (hclass->IsClassConstructor()) {
kind = PGOObjKind::CONSTRUCTOR;
auto rootHClass = JSHClass::FindRootHClass(hclass);
AddObjectInfoByTraceId(recordName, methodId, bcOffset, rootHClass, ProfileType::Kind::ClassId, kind);
AddObjectInfoByTraceId(abcId, recordName, methodId, bcOffset, rootHClass, ProfileType::Kind::ClassId, kind);
} else if (hclass->IsJSArray()) {
if (kind == PGOObjKind::ELEMENT) {
auto elementsKind = hclass->GetElementsKind();
auto profileType = ProfileType(static_cast<uint32_t>(elementsKind), ProfileType::Kind::ElementId);
auto profileType = ProfileType(abcId, static_cast<uint32_t>(elementsKind), ProfileType::Kind::ElementId);
PGOObjectInfo info(profileType, kind);
recordInfos_->AddObjectInfo(recordName, methodId, bcOffset, info);
recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info);
}
} else if (hclass->IsTypedArray()) {
// Depend to TypedArray IC
auto id = static_cast<uint32_t>(hclass->GetObjectType());
PGOObjectInfo info(ProfileType(id, ProfileType::Kind::BuiltinsId), kind);
recordInfos_->AddObjectInfo(recordName, methodId, bcOffset, info);
PGOObjectInfo info(ProfileType(abcId, id, ProfileType::Kind::BuiltinsId), kind);
recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info);
} else {
if (hclass->IsJSObject()) {
// maybe object literal
auto rootHClass = JSHClass::FindRootHClass(hclass);
auto profileKind = ProfileType::Kind::LiteralId;
if (AddObjectInfoByTraceId(recordName, methodId, bcOffset, rootHClass, profileKind, kind)) {
if (AddObjectInfoByTraceId(abcId, recordName, methodId, bcOffset, rootHClass, profileKind, kind)) {
return;
}
}
@ -807,39 +824,46 @@ void PGOProfiler::AddObjectInfo(
// maybe class object
auto prototypeHClass = prototype.GetTaggedObject()->GetClass();
auto rootHClass = JSHClass::FindRootHClass(prototypeHClass);
if (AddObjectInfoByTraceId(recordName, methodId, bcOffset, rootHClass, ProfileType::Kind::ClassId, kind)) {
if (AddObjectInfoByTraceId(abcId, recordName, methodId, bcOffset, rootHClass, ProfileType::Kind::ClassId,
kind)) {
return;
}
}
auto profileType = ProfileType(static_cast<uint32_t>(0), ProfileType::Kind::UnknowId);
auto profileType = ProfileType(abcId, static_cast<uint32_t>(0), ProfileType::Kind::UnknowId);
PGOObjectInfo info(profileType, kind);
recordInfos_->AddObjectInfo(recordName, methodId, bcOffset, info);
recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info);
}
}
bool PGOProfiler::AddObjectInfoByTraceId(const CString &recordName, EntityId methodId, int32_t bcOffset,
JSHClass *hclass, ProfileType::Kind classKind, PGOObjKind kind)
bool PGOProfiler::AddObjectInfoByTraceId(ApEntityId abcId, const CString &recordName, EntityId methodId,
int32_t bcOffset, JSHClass *hclass, ProfileType::Kind classKind,
PGOObjKind kind)
{
auto iter = traceIds_.find(JSTaggedType(hclass));
if (iter != traceIds_.end()) {
PGOObjectInfo info(ProfileType(iter->second, classKind), kind);
recordInfos_->AddObjectInfo(recordName, methodId, bcOffset, info);
ProfileType recordType = GetRecordProfileType(abcId, recordName);
auto iter = tracedProfiles_.find(JSTaggedType(hclass));
if (iter != tracedProfiles_.end()) {
ProfileType traceType = iter->second;
traceType.UpdateKind(classKind);
PGOObjectInfo info(traceType, kind);
recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info);
return true;
}
return false;
}
int32_t PGOProfiler::InsertLiteralId(JSTaggedType hclass, int32_t traceId)
ProfileType PGOProfiler::InsertLiteralTraceId(JSTaggedType hclass, ApEntityId abcId, int32_t traceId)
{
ProfileType literalType(abcId, traceId, ProfileType::Kind::LiteralId);
return InsertTraceId(hclass, literalType);
}
ProfileType PGOProfiler::InsertTraceId(JSTaggedType hclass, ProfileType traceType)
{
if (!isEnable_) {
return traceId;
return traceType;
}
auto iter = traceIds_.find(hclass);
if (iter != traceIds_.end()) {
return iter->second;
}
traceIds_.emplace(hclass, traceId);
return traceId;
auto result = tracedProfiles_.try_emplace(hclass, traceType);
return result.first->second;
}
void PGOProfiler::ProcessReferences(const WeakRootVisitor &visitor)
@ -847,11 +871,11 @@ void PGOProfiler::ProcessReferences(const WeakRootVisitor &visitor)
if (!isEnable_) {
return;
}
for (auto iter = traceIds_.begin(); iter != traceIds_.end();) {
for (auto iter = tracedProfiles_.begin(); iter != tracedProfiles_.end();) {
JSTaggedType object = iter->first;
auto fwd = visitor(reinterpret_cast<TaggedObject *>(object));
if (fwd == nullptr) {
iter = traceIds_.erase(iter);
iter = tracedProfiles_.erase(iter);
continue;
}
if (fwd != reinterpret_cast<TaggedObject *>(object)) {
@ -916,4 +940,43 @@ void PGOProfiler::Reset(bool isEnable)
}
}
}
ApEntityId PGOProfiler::GetMethodAbcId(JSFunction *jsFunction)
{
CString pfName;
auto jsMethod = jsFunction->GetMethod();
if (jsMethod.IsMethod()) {
const auto *pf = Method::Cast(jsMethod)->GetJSPandaFile();
if (pf != nullptr) {
pfName = pf->GetJSPandaFileDesc();
}
}
ApEntityId abcId(0);
if (!PGOProfilerManager::GetInstance()->GetPandaFileId(pfName, abcId) && !pfName.empty()) {
LOG_ECMA(ERROR) << "Get method abc id failed. abcName: " << pfName;
}
return abcId;
}
ApEntityId PGOProfiler::GetRecordId(const CString &recordName)
{
ApEntityId recordId(0);
recordInfos_->GetRecordPool()->TryAdd(recordName, recordId);
return recordId;
}
ProfileType PGOProfiler::GetRecordProfileType(JSFunction *jsFunction, const CString &recordName)
{
return GetRecordProfileType(GetMethodAbcId(jsFunction), GetRecordId(recordName));
}
ProfileType PGOProfiler::GetRecordProfileType(ApEntityId abcId, const CString &recordName)
{
return GetRecordProfileType(abcId, GetRecordId(recordName));
}
ProfileType PGOProfiler::GetRecordProfileType(ApEntityId abcId, ApEntityId recordId)
{
return {abcId, recordId, ProfileType::Kind::LocalRecordId};
}
} // namespace panda::ecmascript::pgo

View File

@ -26,9 +26,13 @@
#include "ecmascript/mem/c_containers.h"
#include "ecmascript/mem/visitor.h"
#include "ecmascript/taskpool/task.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "ecmascript/pgo_profiler/types/pgo_profile_type.h"
namespace panda::ecmascript {
class ProfileTypeInfo;
class JSFunction;
namespace pgo {
class PGORecordDetailInfos;
@ -42,8 +46,9 @@ public:
NO_COPY_SEMANTIC(PGOProfiler);
NO_MOVE_SEMANTIC(PGOProfiler);
static ProfileType GetRecordProfileType(ApEntityId abcId, ApEntityId recordId);
void ProfileCall(JSTaggedType callTarget, SampleMode mode = SampleMode::CALL_MODE, int32_t incCount = 1);
void ProfileCreateObject(JSTaggedType object, int32_t traceId);
void ProfileCreateObject(JSTaggedType object, ApEntityId abcId, int32_t traceId);
void ProfileDefineClass(JSTaggedType ctor);
void SetSaveTimestamp(std::chrono::system_clock::time_point timestamp)
@ -65,7 +70,8 @@ public:
void Iterate(const RootVisitor &visitor);
void UpdateTrackInfo(JSTaggedValue trackInfoVal, ElementsKind newKind);
int32_t InsertLiteralId(JSTaggedType hclass, int32_t traceId);
ProfileType InsertLiteralTraceId(JSTaggedType hclass, ApEntityId abcId, int32_t traceId);
ProfileType InsertTraceId(JSTaggedType hclass, ProfileType traceType);
private:
static constexpr uint32_t MERGED_EVERY_COUNT = 50;
@ -81,36 +87,36 @@ private:
START,
};
void ProfileByteCode(CString recordName, JSTaggedValue value);
void ProfileByteCode(ApEntityId abcId, const CString &recordName, JSTaggedValue value);
void DumpICByName(const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId,
ProfileTypeInfo *profileTypeInfo, BCType type);
void DumpICByValue(const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId,
ProfileTypeInfo *profileTypeInfo, BCType type);
void DumpICByName(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId,
ProfileTypeInfo *profileTypeInfo, BCType type);
void DumpICByValue(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
uint32_t slotId, ProfileTypeInfo *profileTypeInfo, BCType type);
void DumpICByNameWithPoly(
const CString &recordName, EntityId methodId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type);
void DumpICByValueWithPoly(
const CString &recordName, EntityId methodId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type);
void DumpICByNameWithPoly(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
JSTaggedValue cacheValue, BCType type);
void DumpICByValueWithPoly(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
JSTaggedValue cacheValue, BCType type);
void DumpICByNameWithHandler(const CString &recordName, EntityId methodId, int32_t bcOffset, JSHClass *hclass,
JSTaggedValue secondValue, BCType type);
void DumpICByValueWithHandler(const CString &recordName, EntityId methodId, int32_t bcOffset, JSHClass *hclass,
JSTaggedValue secondValue, BCType type);
void DumpICByNameWithHandler(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
JSHClass *hclass, JSTaggedValue secondValue, BCType type);
void DumpICByValueWithHandler(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
JSHClass *hclass, JSTaggedValue secondValue, BCType type);
void DumpOpType(const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId,
ProfileTypeInfo *profileTypeInfo);
void DumpDefineClass(const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId,
ProfileTypeInfo *profileTypeInfo);
void DumpCreateObject(const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId,
ProfileTypeInfo *profileTypeInfo, int32_t traceId);
void DumpCall(const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId,
ProfileTypeInfo *profileTypeInfo);
void DumpOpType(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId,
ProfileTypeInfo *profileTypeInfo);
void DumpDefineClass(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
uint32_t slotId, ProfileTypeInfo *profileTypeInfo);
void DumpCreateObject(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
uint32_t slotId, ProfileTypeInfo *profileTypeInfo, int32_t traceId);
void DumpCall(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId,
ProfileTypeInfo *profileTypeInfo);
void AddObjectInfo(
const CString &recordName, EntityId methodId, int32_t bcOffset, JSHClass *hclass, PGOObjKind kind);
bool AddObjectInfoByTraceId(const CString &recordName, EntityId methodId, int32_t bcOffset, JSHClass *hclass,
ProfileType::Kind classKind, PGOObjKind kind);
void AddObjectInfo(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
JSHClass *hclass, PGOObjKind kind);
bool AddObjectInfoByTraceId(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
JSHClass *hclass, ProfileType::Kind classKind, PGOObjKind kind);
JSTaggedValue PopFromProfileQueue();
@ -135,6 +141,11 @@ private:
virtual ~PGOProfiler();
static ApEntityId GetMethodAbcId(JSFunction *jsFunction);
ApEntityId GetRecordId(const CString &recordName);
ProfileType GetRecordProfileType(JSFunction *jsFunction, const CString &recordName);
ProfileType GetRecordProfileType(ApEntityId abcId, const CString &recordName);
void Reset(bool isEnable);
EcmaVM *vm_ { nullptr };
@ -146,10 +157,10 @@ private:
os::memory::ConditionVariable condition_;
CList<JSTaggedType> dumpWorkList_;
CSet<JSTaggedType> preDumpWorkList_;
CMap<JSTaggedType, int32_t> traceIds_;
CMap<JSTaggedType, ProfileType> tracedProfiles_;
std::unique_ptr<PGORecordDetailInfos> recordInfos_;
friend class PGOProfilerManager;
};
} // namespace panda::ecmascript
} // namespace pgo
} // namespace panda::ecmascript
#endif // ECMASCRIPT_PGO_PROFILER_H

View File

@ -39,9 +39,16 @@ bool PGOProfilerDecoder::Load()
return false;
}
pandaFileInfos_.ParseFromBinary(addr, header_->GetPandaInfoSection());
if (!recordSimpleInfos_) {
recordSimpleInfos_ = std::make_unique<PGORecordSimpleInfos>(hotnessThreshold_);
}
if (!abcFilePool_) {
abcFilePool_ = std::make_unique<PGOAbcFilePool>();
}
if (header_->SupportProfileTypeWithAbcId()) {
PGOFileSectionInterface::ParseSectionFromBinary(addr, header_, *abcFilePool_->GetPool());
}
recordSimpleInfos_->ParseFromBinary(addr, header_);
UnLoadAPBinaryFile();
@ -97,6 +104,14 @@ bool PGOProfilerDecoder::LoadFull()
if (!recordDetailInfos_) {
recordDetailInfos_ = std::make_shared<PGORecordDetailInfos>(hotnessThreshold_);
}
if (!abcFilePool_) {
abcFilePool_ = std::make_unique<PGOAbcFilePool>();
}
if (header_->SupportProfileTypeWithAbcId()) {
PGOFileSectionInterface::ParseSectionFromBinary(addr, header_, *abcFilePool_->GetPool());
}
recordDetailInfos_->ParseFromBinary(addr, header_);
isLoaded_ = true;
@ -123,6 +138,7 @@ bool PGOProfilerDecoder::SaveAPTextFile(const std::string &outPath)
}
pandaFileInfos_.ProcessToText(fileStream);
recordDetailInfos_->ProcessToText(fileStream);
abcFilePool_->GetPool()->ProcessToText(fileStream);
return true;
}
@ -163,6 +179,9 @@ void PGOProfilerDecoder::Clear()
hotnessThreshold_ = 0;
PGOProfilerHeader::Destroy(&header_);
pandaFileInfos_.Clear();
if (abcFilePool_) {
abcFilePool_->Clear();
}
if (recordDetailInfos_) {
recordDetailInfos_->Clear();
}
@ -181,7 +200,7 @@ bool PGOProfilerDecoder::Match(const CString &recordName, PGOMethodId methodId)
if (!isVerifySuccess_) {
return false;
}
return recordSimpleInfos_->Match(recordName, methodId);
return recordSimpleInfos_->Match(recordName, EntityId(methodId));
}
bool PGOProfilerDecoder::GetHClassLayoutDesc(PGOSampleType profileType, PGOHClassLayoutDesc **desc) const

View File

@ -152,6 +152,7 @@ private:
uint32_t hotnessThreshold_ {0};
PGOProfilerHeader *header_ {nullptr};
PGOPandaFileInfos pandaFileInfos_;
std::shared_ptr<PGOAbcFilePool> abcFilePool_;
std::shared_ptr<PGORecordDetailInfos> recordDetailInfos_;
std::unique_ptr<PGORecordSimpleInfos> recordSimpleInfos_;
MemMap fileMapAddr_;

View File

@ -20,13 +20,18 @@
#include <string>
#include "ecmascript/log_wrapper.h"
#include "ecmascript/pgo_profiler/ap_file/pgo_file_info.h"
#include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
#include "ecmascript/pgo_profiler/pgo_profiler_encoder.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "ecmascript/platform/file.h"
#include "os/mutex.h"
namespace panda::ecmascript::pgo {
static const std::string PROFILE_FILE_NAME = "/modules.ap";
static const std::string AP_SUFFIX = ".ap";
static const std::string PROFILE_FILE_NAME = "/modules" + AP_SUFFIX;
static const std::string RUNTIME_AP_PREFIX = "/rt_";
void PGOProfilerEncoder::Destroy()
{
if (!isInitialized_) {
@ -39,32 +44,63 @@ void PGOProfilerEncoder::Destroy()
isInitialized_ = false;
}
bool PGOProfilerEncoder::ResetOutPathByModuleName(const std::string &moduleName)
{
os::memory::LockHolder lock(mutex_);
// only first assign takes effect
if (!moduleName_.empty() || moduleName.empty()) {
return false;
}
moduleName_ = moduleName;
return ResetOutPath(RUNTIME_AP_PREFIX + moduleName_ + AP_SUFFIX);
}
bool PGOProfilerEncoder::ResetOutPath(const std::string &profileFileName)
{
if (!RealPath(outDir_, realOutPath_, false)) {
return false;
}
if (realOutPath_.compare(realOutPath_.length() - AP_SUFFIX.length(), AP_SUFFIX.length(), AP_SUFFIX)) {
realOutPath_ += profileFileName;
}
LOG_ECMA(INFO) << "Save profiler to file:" << realOutPath_;
return true;
}
bool PGOProfilerEncoder::InitializeData()
{
if (!isInitialized_) {
if (!RealPath(outDir_, realOutPath_, false)) {
if (!ResetOutPath(PROFILE_FILE_NAME)) {
return false;
}
static const std::string endString = ".ap";
if (realOutPath_.compare(realOutPath_.length() - endString.length(), endString.length(), endString)) {
realOutPath_ += PROFILE_FILE_NAME;
}
LOG_ECMA(INFO) << "Save profiler to file:" << realOutPath_;
PGOProfilerHeader::Build(&header_, PGOProfilerHeader::LastSize());
pandaFileInfos_ = std::make_unique<PGOPandaFileInfos>();
abcFilePool_ = std::make_unique<PGOAbcFilePool>();
globalRecordInfos_ = std::make_shared<PGORecordDetailInfos>(hotnessThreshold_);
isInitialized_ = true;
}
return true;
}
void PGOProfilerEncoder::SamplePandaFileInfo(uint32_t checksum)
void PGOProfilerEncoder::SamplePandaFileInfo(uint32_t checksum, const CString &abcName)
{
if (!isInitialized_) {
return;
}
os::memory::WriteLockHolder lock(rwLock_);
pandaFileInfos_->Sample(checksum);
ApEntityId entryId(0);
abcFilePool_->TryAdd(abcName, entryId);
}
bool PGOProfilerEncoder::GetPandaFileId(const CString &abcName, ApEntityId &entryId)
{
if (!isInitialized_) {
return false;
}
os::memory::ReadLockHolder lock(rwLock_);
return abcFilePool_->GetEntryId(abcName, entryId);
}
void PGOProfilerEncoder::Merge(const PGORecordDetailInfos &recordInfos)
@ -102,31 +138,10 @@ bool PGOProfilerEncoder::Save()
return InternalSave();
}
void PGOProfilerEncoder::MergeWithExistProfile(PGOProfilerEncoder &encoder, PGOProfilerDecoder &decoder,
const SaveTask *task)
{
if (!decoder.LoadFull()) {
LOG_ECMA(ERROR) << "Fail to load ap: " << realOutPath_;
} else {
Merge(decoder.GetPandaFileInfos());
globalRecordInfos_ = decoder.GetRecordDetailInfosPtr();
}
if (task && task->IsTerminate()) {
LOG_ECMA(DEBUG) << "ProcessProfile: task is already terminate";
return;
}
Merge(*encoder.pandaFileInfos_);
if (task && task->IsTerminate()) {
LOG_ECMA(DEBUG) << "ProcessProfile: task is already terminate";
return;
}
Merge(*encoder.globalRecordInfos_);
}
bool PGOProfilerEncoder::SaveAndRename(const SaveTask *task)
{
static const char *tempSuffix = ".tmp";
auto tmpOutPath = realOutPath_ + "." + std::to_string(getpid()) + "." + tempSuffix;
auto tmpOutPath = realOutPath_ + "." + std::to_string(getpid()) + tempSuffix;
std::fstream fileStream(tmpOutPath.c_str(),
std::fstream::binary | std::fstream::out | std::fstream::in | std::fstream::trunc);
if (!fileStream.is_open()) {
@ -135,6 +150,11 @@ bool PGOProfilerEncoder::SaveAndRename(const SaveTask *task)
}
pandaFileInfos_->ProcessToBinary(fileStream, header_->GetPandaInfoSection());
globalRecordInfos_->ProcessToBinary(task, fileStream, header_);
{
os::memory::ReadLockHolder lock(rwLock_);
PGOFileSectionInterface::ProcessSectionToBinary(fileStream, header_, *abcFilePool_->GetPool());
}
header_->SetFileSize(static_cast<uint32_t>(fileStream.tellp()));
header_->ProcessToBinary(fileStream);
if (header_->SupportFileConsistency()) {
AddChecksum(fileStream);
@ -161,13 +181,6 @@ bool PGOProfilerEncoder::InternalSave(const SaveTask *task)
if (!isInitialized_) {
return false;
}
if ((mode_ == MERGE) && FileExist(realOutPath_.c_str())) {
PGOProfilerEncoder encoder(realOutPath_, hotnessThreshold_, mode_);
encoder.InitializeData();
PGOProfilerDecoder decoder(realOutPath_, hotnessThreshold_);
encoder.MergeWithExistProfile(*this, decoder, task);
return encoder.SaveAndRename(task);
}
return SaveAndRename(task);
}

View File

@ -16,6 +16,8 @@
#ifndef ECMASCRIPT_PGO_PROFILER_ENCODER_H
#define ECMASCRIPT_PGO_PROFILER_ENCODER_H
#include <utility>
#include "ecmascript/pgo_profiler/pgo_profiler_info.h"
#include "macros.h"
@ -23,7 +25,7 @@ namespace panda::ecmascript::pgo {
class PGOProfilerDecoder;
class PGOProfilerEncoder {
public:
enum ApGenMode { OVERWRITE, MERGE };
enum ApGenMode { OVERWRITE };
PGOProfilerEncoder(const std::string &outDir, uint32_t hotnessThreshold, ApGenMode mode)
: outDir_(outDir), hotnessThreshold_(hotnessThreshold), mode_(mode) {}
@ -42,7 +44,8 @@ public:
return isInitialized_;
}
void SamplePandaFileInfo(uint32_t checksum);
void SamplePandaFileInfo(uint32_t checksum, const CString &abcName);
bool GetPandaFileId(const CString &abcName, ApEntityId &entryId);
void Merge(const PGORecordDetailInfos &recordInfos);
void Merge(const PGOPandaFileInfos &pandaFileInfos);
void Merge(const PGOProfilerEncoder &encoder);
@ -59,12 +62,13 @@ public:
bool PUBLIC_API LoadAPTextFile(const std::string &inPath);
bool ResetOutPathByModuleName(const std::string &moduleName);
private:
void StartSaveTask(const SaveTask *task);
bool InternalSave(const SaveTask *task = nullptr);
bool SaveAndRename(const SaveTask *task = nullptr);
void MergeWithExistProfile(PGOProfilerEncoder &encoder, PGOProfilerDecoder &decoder,
const SaveTask *task = nullptr);
bool ResetOutPath(const std::string& profileFileName);
bool isInitialized_ {false};
std::string outDir_;
@ -72,8 +76,11 @@ private:
std::string realOutPath_;
PGOProfilerHeader *header_ {nullptr};
std::unique_ptr<PGOPandaFileInfos> pandaFileInfos_;
std::shared_ptr<PGOAbcFilePool> abcFilePool_;
std::shared_ptr<PGORecordDetailInfos> globalRecordInfos_;
os::memory::Mutex mutex_;
os::memory::RWLock rwLock_;
std::string moduleName_;
ApGenMode mode_ {OVERWRITE};
friend SaveTask;
};

View File

@ -17,6 +17,7 @@
#include <cstdint>
#include <fstream>
#include <iomanip>
#include <memory>
#include "ecmascript/base/bit_helper.h"
#include "ecmascript/base/file_header.h"
@ -24,11 +25,13 @@
#include "ecmascript/jspandafile/method_literal.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/mem/c_string.h"
#include "ecmascript/pgo_profiler/ap_file/pgo_file_info.h"
#include "ecmascript/pgo_profiler/ap_file/pgo_method_type_set.h"
#include "ecmascript/pgo_profiler/ap_file/pgo_profile_type_pool.h"
#include "ecmascript/pgo_profiler/ap_file/pgo_record_pool.h"
#include "ecmascript/pgo_profiler/pgo_context.h"
#include "ecmascript/pgo_profiler/pgo_profiler_encoder.h"
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "ecmascript/pgo_profiler/types/pgo_profile_type.h"
#include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
@ -36,6 +39,20 @@
#include "securec.h"
namespace panda::ecmascript::pgo {
namespace {
bool ParseSectionsFromBinary(const std::list<std::weak_ptr<PGOFileSectionInterface>> &sectionList, void *buffer,
PGOProfilerHeader const *header)
{
return std::all_of(sectionList.begin(), sectionList.end(), [&](const auto &sectionWeak) {
auto section = sectionWeak.lock();
if (section == nullptr) {
return true;
}
return PGOFileSectionInterface::ParseSectionFromBinary(buffer, header, *section);
});
}
} // namespace
using StringHelper = base::StringHelper;
void PGOPandaFileInfos::ParseFromBinary(void *buffer, SectionInfo *const info)
{
@ -320,8 +337,8 @@ bool PGOMethodInfoMap::ParseFromBinary(Chunk *chunk, PGOContext &context, void *
return !methodInfos_.empty();
}
bool PGOMethodInfoMap::ProcessToBinary(PGOContext &context, ApEntityId recordId, const SaveTask *task,
std::fstream &stream, PGOProfilerHeader *const header) const
bool PGOMethodInfoMap::ProcessToBinary(PGOContext &context, ProfileTypeRef recordProfileRef, const SaveTask *task,
std::fstream &stream, PGOProfilerHeader *const header) const
{
SectionInfo secInfo;
std::stringstream methodStream;
@ -361,7 +378,7 @@ bool PGOMethodInfoMap::ProcessToBinary(PGOContext &context, ApEntityId recordId,
if (secInfo.number_ > 0) {
secInfo.offset_ = sizeof(SectionInfo);
secInfo.size_ = static_cast<uint32_t>(methodStream.tellp());
stream.write(reinterpret_cast<char *>(&recordId), sizeof(uint32_t));
stream.write(reinterpret_cast<char *>(&recordProfileRef), sizeof(uint32_t));
stream.write(reinterpret_cast<char *>(&secInfo), sizeof(SectionInfo));
stream << methodStream.rdbuf();
return true;
@ -540,8 +557,7 @@ void PGODecodeMethodInfo::Merge(const PGODecodeMethodInfo &from)
PGORecordDetailInfos::PGORecordDetailInfos(uint32_t hotnessThreshold) : hotnessThreshold_(hotnessThreshold)
{
chunk_ = std::make_unique<Chunk>(&nativeAreaAllocator_);
recordPool_ = std::make_shared<PGORecordPool>();
profileTypePool_ = std::make_shared<PGOProfileTypePool>();
InitSections();
};
PGORecordDetailInfos::~PGORecordDetailInfos()
@ -549,55 +565,54 @@ PGORecordDetailInfos::~PGORecordDetailInfos()
Clear();
}
PGOMethodInfoMap *PGORecordDetailInfos::GetMethodInfoMap(const CString &recordName)
PGOMethodInfoMap *PGORecordDetailInfos::GetMethodInfoMap(ProfileType recordProfileType)
{
ApEntityId recordId;
recordPool_->TryAdd(recordName, recordId);
auto iter = recordInfos_.find(recordId);
auto iter = recordInfos_.find(recordProfileType);
if (iter != recordInfos_.end()) {
return iter->second;
} else {
auto curMethodInfos = nativeAreaAllocator_.New<PGOMethodInfoMap>();
recordInfos_.emplace(recordId, curMethodInfos);
recordInfos_.emplace(recordProfileType, curMethodInfos);
return curMethodInfos;
}
}
bool PGORecordDetailInfos::AddMethod(const CString &recordName, Method *jsMethod, SampleMode mode, int32_t incCount)
bool PGORecordDetailInfos::AddMethod(ProfileType recordProfileType, Method *jsMethod, SampleMode mode, int32_t incCount)
{
auto curMethodInfos = GetMethodInfoMap(recordName);
auto curMethodInfos = GetMethodInfoMap(recordProfileType);
ASSERT(curMethodInfos != nullptr);
ASSERT(jsMethod != nullptr);
return curMethodInfos->AddMethod(&nativeAreaAllocator_, jsMethod, mode, incCount);
}
bool PGORecordDetailInfos::AddType(const CString &recordName, PGOMethodId methodId, int32_t offset, PGOSampleType type)
bool PGORecordDetailInfos::AddType(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset,
PGOSampleType type)
{
auto curMethodInfos = GetMethodInfoMap(recordName);
auto curMethodInfos = GetMethodInfoMap(recordProfileType);
ASSERT(curMethodInfos != nullptr);
return curMethodInfos->AddType(chunk_.get(), methodId, offset, type);
}
bool PGORecordDetailInfos::AddCallTargetType(const CString &recordName, PGOMethodId methodId, int32_t offset,
bool PGORecordDetailInfos::AddCallTargetType(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset,
PGOSampleType type)
{
auto curMethodInfos = GetMethodInfoMap(recordName);
auto curMethodInfos = GetMethodInfoMap(recordProfileType);
ASSERT(curMethodInfos != nullptr);
return curMethodInfos->AddCallTargetType(chunk_.get(), methodId, offset, type);
}
bool PGORecordDetailInfos::AddObjectInfo(
const CString &recordName, EntityId methodId, int32_t offset, const PGOObjectInfo &info)
ProfileType recordProfileType, EntityId methodId, int32_t offset, const PGOObjectInfo &info)
{
auto curMethodInfos = GetMethodInfoMap(recordName);
auto curMethodInfos = GetMethodInfoMap(recordProfileType);
ASSERT(curMethodInfos != nullptr);
return curMethodInfos->AddObjectInfo(chunk_.get(), methodId, offset, info);
}
bool PGORecordDetailInfos::AddDefine(
const CString &recordName, PGOMethodId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType)
ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType)
{
auto curMethodInfos = GetMethodInfoMap(recordName);
auto curMethodInfos = GetMethodInfoMap(recordProfileType);
ASSERT(curMethodInfos != nullptr);
curMethodInfos->AddDefine(chunk_.get(), methodId, offset, type, superType);
@ -646,18 +661,20 @@ void PGORecordDetailInfos::Merge(const PGORecordDetailInfos &recordInfos)
{
std::map<ApEntityId, ApEntityId> idMapping;
recordPool_->Merge(*recordInfos.recordPool_, idMapping);
for (auto iter = recordInfos.recordInfos_.begin(); iter != recordInfos.recordInfos_.end(); iter++) {
auto oldRecordId = iter->first;
auto newRecordId = idMapping.at(oldRecordId);
auto oldRecordType = iter->first;
auto newIter = idMapping.find(oldRecordType.GetId());
if (newIter == idMapping.end()) {
continue;
}
auto newRecordType = PGOProfiler::GetRecordProfileType(oldRecordType.GetAbcId(), newIter->second);
auto fromMethodInfos = iter->second;
auto recordInfosIter = recordInfos_.find(newRecordId);
auto recordInfosIter = recordInfos_.find(newRecordType);
PGOMethodInfoMap *toMethodInfos = nullptr;
if (recordInfosIter == recordInfos_.end()) {
toMethodInfos = nativeAreaAllocator_.New<PGOMethodInfoMap>();
recordInfos_.emplace(newRecordId, toMethodInfos);
recordInfos_.emplace(newRecordType, toMethodInfos);
} else {
toMethodInfos = recordInfosIter->second;
}
@ -667,11 +684,12 @@ void PGORecordDetailInfos::Merge(const PGORecordDetailInfos &recordInfos)
// Merge global layout desc infos to global method info map
for (auto info = recordInfos.moduleLayoutDescInfos_.begin(); info != recordInfos.moduleLayoutDescInfos_.end();
info++) {
auto result = moduleLayoutDescInfos_.find(*info);
auto fromInfo = *info;
auto result = moduleLayoutDescInfos_.find(fromInfo);
if (result == moduleLayoutDescInfos_.end()) {
moduleLayoutDescInfos_.emplace(*info);
moduleLayoutDescInfos_.emplace(fromInfo);
} else {
const_cast<PGOHClassLayoutDesc &>(*result).Merge(*info);
const_cast<PGOHClassLayoutDesc &>(*result).Merge(fromInfo);
}
}
}
@ -679,37 +697,29 @@ void PGORecordDetailInfos::Merge(const PGORecordDetailInfos &recordInfos)
void PGORecordDetailInfos::ParseFromBinary(void *buffer, PGOProfilerHeader *const header)
{
header_ = header;
// parse pools first
if (header->SupportRecordPool()) {
SectionInfo *info = header->GetRecordPoolSection();
if (info == nullptr) {
return;
}
void *addr = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + info->offset_);
recordPool_->ParseFromBinary(&addr, header);
if (!ParseSectionsFromBinary(apSectionList_, buffer, header)) {
return;
}
if (header->SupportWideProfileType()) {
SectionInfo *info = header->GetProfileTypeSection();
if (info == nullptr) {
return;
}
void *addr = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + info->offset_);
profileTypePool_->ParseFromBinary(&addr, header);
}
SectionInfo *info = header->GetRecordInfoSection();
void *addr = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + info->offset_);
for (uint32_t i = 0; i < info->number_; i++) {
ApEntityId recordId(0);
if (header->SupportRecordPool()) {
ProfileType recordType;
if (header->SupportProfileTypeWithAbcId()) {
auto recordTypeRef = ProfileTypeRef(base::ReadBuffer<ApEntityId>(&addr, sizeof(ApEntityId)));
recordType = ProfileType(*this, recordTypeRef);
recordId = recordType.GetId();
} else if (header->SupportRecordPool()) {
recordId = base::ReadBuffer<ApEntityId>(&addr, sizeof(ApEntityId));
} else {
auto *recordName = base::ReadBuffer(&addr);
recordPool_->TryAdd(recordName, recordId);
}
recordType.UpdateId(recordId);
recordType.UpdateKind(ProfileType::Kind::LocalRecordId);
PGOMethodInfoMap *methodInfos = nativeAreaAllocator_.New<PGOMethodInfoMap>();
if (methodInfos->ParseFromBinary(chunk_.get(), *this, &addr)) {
recordInfos_.emplace(recordId, methodInfos);
recordInfos_.emplace(recordType, methodInfos);
}
}
@ -750,7 +760,7 @@ void PGORecordDetailInfos::ProcessToBinary(
}
auto recordId = iter->first;
auto curMethodInfos = iter->second;
if (curMethodInfos->ProcessToBinary(*this, recordId, task, fileStream, header)) {
if (curMethodInfos->ProcessToBinary(*this, ProfileTypeRef(*this, recordId), task, fileStream, header)) {
info->number_++;
}
}
@ -770,24 +780,13 @@ void PGORecordDetailInfos::ProcessToBinary(
}
info->size_ = static_cast<uint32_t>(fileStream.tellp()) - info->offset_;
info = header->GetRecordPoolSection();
if (info == nullptr) {
return;
for (const auto &sectionWeak : apSectionList_) {
auto section = sectionWeak.lock();
if (section == nullptr) {
continue;
}
PGOFileSectionInterface::ProcessSectionToBinary(fileStream, header, *section);
}
info->number_ = 0;
info->offset_ = static_cast<uint32_t>(fileStream.tellp());
info->number_ = recordPool_->ProcessToBinary(fileStream);
info->size_ = static_cast<uint32_t>(fileStream.tellp()) - info->offset_;
info = header->GetProfileTypeSection();
if (info == nullptr) {
return;
}
info->number_ = 0;
info->offset_ = static_cast<uint32_t>(fileStream.tellp());
info->number_ = profileTypePool_->ProcessToBinary(fileStream);
info->size_ = static_cast<uint32_t>(fileStream.tellp()) - info->offset_;
header->SetFileSize(static_cast<uint32_t>(fileStream.tellp()));
}
bool PGORecordDetailInfos::ProcessToBinaryForLayout(
@ -852,13 +851,14 @@ bool PGORecordDetailInfos::ParseFromText(std::ifstream &stream)
continue;
}
ApEntityId recordId;
ApEntityId recordId(0);
recordPool_->TryAdd(recordName, recordId);
auto methodInfosIter = recordInfos_.find(recordId);
ProfileType profileType(0, recordId, ProfileType::Kind::LocalRecordId);
auto methodInfosIter = recordInfos_.find(profileType);
PGOMethodInfoMap *methodInfos = nullptr;
if (methodInfosIter == recordInfos_.end()) {
methodInfos = nativeAreaAllocator_.New<PGOMethodInfoMap>();
recordInfos_.emplace(recordId, methodInfos);
recordInfos_.emplace(profileType, methodInfos);
} else {
methodInfos = methodInfosIter->second;
}
@ -888,13 +888,21 @@ void PGORecordDetailInfos::ProcessToText(std::ofstream &stream) const
stream << profilerString;
}
for (auto iter = recordInfos_.begin(); iter != recordInfos_.end(); iter++) {
auto recordId = iter->first;
auto recordName = recordPool_->GetRecord(recordId)->GetRecordName();
auto recordId = ApEntityId(iter->first.GetId());
auto recordName = recordPool_->GetEntry(recordId)->GetData();
auto methodInfos = iter->second;
methodInfos->ProcessToText(hotnessThreshold_, recordName, stream);
}
recordPool_->ProcessToText(stream);
profileTypePool_->ProcessToText(stream);
recordPool_->GetPool()->ProcessToText(stream);
profileTypePool_->GetPool()->ProcessToText(stream);
}
void PGORecordDetailInfos::InitSections()
{
recordPool_ = std::make_unique<PGORecordPool>();
apSectionList_.emplace_back(recordPool_->GetPool());
profileTypePool_ = std::make_unique<PGOProfileTypePool>();
apSectionList_.emplace_back(profileTypePool_->GetPool());
}
void PGORecordDetailInfos::Clear()
@ -906,9 +914,9 @@ void PGORecordDetailInfos::Clear()
recordInfos_.clear();
recordPool_->Clear();
profileTypePool_->Clear();
apSectionList_.clear();
chunk_ = std::make_unique<Chunk>(&nativeAreaAllocator_);
recordPool_ = std::make_unique<PGORecordPool>();
profileTypePool_ = std::make_unique<PGOProfileTypePool>();
InitSections();
}
bool PGORecordSimpleInfos::Match(const CString &recordName, EntityId methodId)
@ -923,29 +931,20 @@ bool PGORecordSimpleInfos::Match(const CString &recordName, EntityId methodId)
void PGORecordSimpleInfos::ParseFromBinary(void *buffer, PGOProfilerHeader *const header)
{
header_ = header;
if (header->SupportRecordPool()) {
SectionInfo *info = header->GetRecordPoolSection();
if (info == nullptr) {
return;
}
void *addr = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + info->offset_);
recordPool_->ParseFromBinary(&addr, header);
}
if (header->SupportWideProfileType()) {
SectionInfo *info = header->GetProfileTypeSection();
if (info == nullptr) {
return;
}
void *addr = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + info->offset_);
profileTypePool_->ParseFromBinary(&addr, header);
}
ParseSectionsFromBinary(apSectionList_, buffer, header);
SectionInfo *info = header->GetRecordInfoSection();
void *addr = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + info->offset_);
for (uint32_t i = 0; i < info->number_; i++) {
CString recordName;
if (header->SupportRecordPool()) {
ProfileType recordType;
if (header->SupportProfileTypeWithAbcId()) {
auto recordTypeRef = ProfileTypeRef(base::ReadBuffer<ApEntityId>(&addr, sizeof(ApEntityId)));
recordType = ProfileType(*this, recordTypeRef);
auto recordId = recordType.GetId();
recordName = recordPool_->GetEntry(recordId)->GetData();
} else if (header->SupportRecordPool()) {
auto recordId = base::ReadBuffer<ApEntityId>(&addr, sizeof(ApEntityId));
recordName = recordPool_->GetRecord(recordId)->GetRecordName();
recordName = recordPool_->GetEntry(recordId)->GetData();
} else {
recordName = base::ReadBuffer(&addr);
}
@ -1003,6 +1002,14 @@ bool PGORecordSimpleInfos::ParseFromBinaryForLayout(void **buffer)
return true;
}
void PGORecordSimpleInfos::InitSections()
{
recordPool_ = std::make_unique<PGORecordPool>();
apSectionList_.emplace_back(recordPool_->GetPool());
profileTypePool_ = std::make_unique<PGOProfileTypePool>();
apSectionList_.emplace_back(profileTypePool_->GetPool());
}
void PGORecordSimpleInfos::Clear()
{
for (const auto &iter : methodIds_) {
@ -1012,16 +1019,15 @@ void PGORecordSimpleInfos::Clear()
methodIds_.clear();
recordPool_->Clear();
profileTypePool_->Clear();
apSectionList_.clear();
chunk_ = std::make_unique<Chunk>(&nativeAreaAllocator_);
recordPool_ = std::make_shared<PGORecordPool>();
profileTypePool_ = std::make_shared<PGOProfileTypePool>();
InitSections();
}
PGORecordSimpleInfos::PGORecordSimpleInfos(uint32_t threshold) : hotnessThreshold_(threshold)
{
chunk_ = std::make_unique<Chunk>(&nativeAreaAllocator_);
recordPool_ = std::make_shared<PGORecordPool>();
profileTypePool_ = std::make_shared<PGOProfileTypePool>();
InitSections();
}
PGORecordSimpleInfos::~PGORecordSimpleInfos()

View File

@ -37,6 +37,7 @@
#include "ecmascript/pgo_profiler/ap_file/pgo_record_pool.h"
#include "ecmascript/pgo_profiler/pgo_context.h"
#include "ecmascript/pgo_profiler/pgo_profiler_layout.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
#include "ecmascript/property_attributes.h"
#include "macros.h"
@ -282,8 +283,8 @@ public:
void Merge(Chunk *chunk, PGOMethodInfoMap *methodInfos);
bool ParseFromBinary(Chunk *chunk, PGOContext &context, void **buffer);
bool ProcessToBinary(PGOContext &context, ApEntityId recordId, const SaveTask *task, std::fstream &fileStream,
PGOProfilerHeader *const header) const;
bool ProcessToBinary(PGOContext &context, ProfileTypeRef recordProfileRef, const SaveTask *task,
std::fstream &fileStream, PGOProfilerHeader *const header) const;
bool ParseFromText(Chunk *chunk, uint32_t threshold, const std::vector<std::string> &content);
void ProcessToText(uint32_t threshold, const CString &recordName, std::ofstream &stream) const;
@ -454,14 +455,15 @@ public:
~PGORecordDetailInfos() override;
void Clear();
void InitSections();
// If it is a new method, return true.
bool AddMethod(const CString &recordName, Method *jsMethod, SampleMode mode, int32_t incCount);
bool AddType(const CString &recordName, PGOMethodId methodId, int32_t offset, PGOSampleType type);
bool AddCallTargetType(const CString &recordName, PGOMethodId methodId, int32_t offset, PGOSampleType type);
bool AddObjectInfo(const CString &recordName, PGOMethodId methodId, int32_t offset, const PGOObjectInfo &info);
bool AddMethod(ProfileType recordProfileType, Method *jsMethod, SampleMode mode, int32_t incCount);
bool AddType(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, PGOSampleType type);
bool AddCallTargetType(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, PGOSampleType type);
bool AddObjectInfo(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, const PGOObjectInfo &info);
bool AddDefine(
const CString &recordName, PGOMethodId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType);
ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType);
bool AddLayout(PGOSampleType type, JSTaggedType hclass, PGOObjKind kind);
bool UpdateElementsKind(PGOSampleType type, ElementsKind kind);
void Merge(const PGORecordDetailInfos &recordInfos);
@ -474,15 +476,16 @@ public:
bool ParseFromText(std::ifstream &stream);
void ProcessToText(std::ofstream &stream) const;
const CMap<ApEntityId, PGOMethodInfoMap *> &GetRecordInfos() const
const CMap<ProfileType, PGOMethodInfoMap *> &GetRecordInfos() const
{
return recordInfos_;
}
std::shared_ptr<PGORecordPool> GetRecordPool() const override
std::shared_ptr<PGORecordPool> GetRecordPool() const
{
return recordPool_;
}
std::shared_ptr<PGOProfileTypePool> GetProfileTypePool() const override
{
return profileTypePool_;
@ -508,16 +511,17 @@ public:
NO_MOVE_SEMANTIC(PGORecordDetailInfos);
private:
PGOMethodInfoMap *GetMethodInfoMap(const CString &recordName);
PGOMethodInfoMap *GetMethodInfoMap(ProfileType recordProfileType);
bool ParseFromBinaryForLayout(void **buffer);
bool ProcessToBinaryForLayout(NativeAreaAllocator *allocator, const SaveTask *task, std::fstream &stream);
uint32_t hotnessThreshold_ {2};
NativeAreaAllocator nativeAreaAllocator_;
std::unique_ptr<Chunk> chunk_;
CMap<ApEntityId, PGOMethodInfoMap *> recordInfos_;
CMap<ProfileType, PGOMethodInfoMap *> recordInfos_;
std::set<PGOHClassLayoutDesc> moduleLayoutDescInfos_;
PGOProfilerHeader *header_;
PGOProfilerHeader *header_ {nullptr};
std::list<std::weak_ptr<PGOFileSectionInterface>> apSectionList_;
std::shared_ptr<PGORecordPool> recordPool_;
std::shared_ptr<PGOProfileTypePool> profileTypePool_;
};
@ -530,6 +534,8 @@ public:
void Clear();
void InitSections();
bool Match(const CString &recordName, EntityId methodId);
template <typename Callback>
@ -607,10 +613,6 @@ public:
void Merge(const PGORecordSimpleInfos &simpleInfos);
std::shared_ptr<PGORecordPool> GetRecordPool() const override
{
return recordPool_;
}
std::shared_ptr<PGOProfileTypePool> GetProfileTypePool() const override
{
return profileTypePool_;
@ -642,7 +644,8 @@ private:
NativeAreaAllocator nativeAreaAllocator_;
std::unique_ptr<Chunk> chunk_;
CUnorderedMap<CString, PGOMethodIdSet *> methodIds_;
PGOProfilerHeader *header_;
PGOProfilerHeader *header_ {nullptr};
std::list<std::weak_ptr<PGOFileSectionInterface>> apSectionList_;
std::shared_ptr<PGORecordPool> recordPool_;
std::shared_ptr<PGOProfileTypePool> profileTypePool_;
std::set<PGOHClassLayoutDesc> moduleLayoutDescInfos_;

View File

@ -45,7 +45,7 @@ public:
void Initialize(const std::string &outDir, uint32_t hotnessThreshold)
{
// For FA jsvm, merge with existed output file
encoder_ = std::make_unique<PGOProfilerEncoder>(outDir, hotnessThreshold, ApGenMode::MERGE);
encoder_ = std::make_unique<PGOProfilerEncoder>(outDir, hotnessThreshold, ApGenMode::OVERWRITE);
}
void Destroy()
@ -91,13 +91,28 @@ public:
}
}
void SamplePandaFileInfo(uint32_t checksum)
void SamplePandaFileInfo(uint32_t checksum, const CString &abcName)
{
if (encoder_) {
encoder_->SamplePandaFileInfo(checksum);
encoder_->SamplePandaFileInfo(checksum, abcName);
}
}
void SetModuleName(const std::string &moduleName)
{
if (encoder_) {
encoder_->ResetOutPathByModuleName(moduleName);
}
}
bool GetPandaFileId(const CString &abcName, ApEntityId &entryId) const
{
if (encoder_) {
return encoder_->GetPandaFileId(abcName, entryId);
}
return false;
}
void SetApGenMode(ApGenMode mode)
{
if (encoder_) {

View File

@ -24,7 +24,8 @@
namespace panda::ecmascript::pgo {
static constexpr Alignment ALIGN_SIZE = Alignment::LOG_ALIGN_4;
using PGOMethodId = panda_file::File::EntityId;
using ApEntityId = panda_file::File::EntityId;
using ApEntityId = uint32_t;
class DumpUtils {
public:
static const std::string ELEMENT_SEPARATOR;

View File

@ -22,13 +22,13 @@
#include "ecmascript/pgo_profiler/pgo_context.h"
#include "ecmascript/base/file_header.h"
#include "ecmascript/pgo_profiler/pgo_profiler_info.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
namespace panda::ecmascript::pgo {
class PGOContextMock : public PGOContext {
public:
explicit PGOContextMock(base::FileHeaderBase::VersionType version)
{
recordPool_ = std::make_shared<PGORecordPool>();
profileTypePool_ = std::make_shared<PGOProfileTypePool>();
PGOProfilerHeader::Build(&header_, sizeof(PGOProfilerHeader));
header_->SetVersion(version);
@ -38,10 +38,7 @@ public:
delete header_;
header_ = nullptr;
};
std::shared_ptr<PGORecordPool> GetRecordPool() const override
{
return recordPool_;
}
std::shared_ptr<PGOProfileTypePool> GetProfileTypePool() const override
{
return profileTypePool_;
@ -63,7 +60,6 @@ public:
private:
NO_COPY_SEMANTIC(PGOContextMock);
NO_MOVE_SEMANTIC(PGOContextMock);
std::shared_ptr<PGORecordPool> recordPool_;
std::shared_ptr<PGOProfileTypePool> profileTypePool_;
PGOProfilerHeader *header_ {};
uint32_t threshold_ {};

View File

@ -21,8 +21,11 @@
#include "ecmascript/elements.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/pgo_profiler/ap_file/pgo_file_info.h"
#include "ecmascript/pgo_profiler/pgo_context.h"
#include "ecmascript/pgo_profiler/types/pgo_profile_type.h"
#include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "gtest/gtest.h"
#include "assembler/assembly-emitter.h"
@ -134,7 +137,7 @@ HWTEST_F_L0(PGOProfilerTest, Sample)
JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
constPool->SetJSPandaFile(pf.get());
uint32_t checksum = 304293;
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler.abc");
ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
@ -182,7 +185,7 @@ HWTEST_F_L0(PGOProfilerTest, Sample1)
JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
constPool->SetJSPandaFile(pf.get());
uint32_t checksum = 304293;
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler1.abc");
ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
@ -249,7 +252,7 @@ HWTEST_F_L0(PGOProfilerTest, Sample2)
constPool->SetJSPandaFile(pf.get());
ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
uint32_t checksum = 304293;
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler2.abc");
JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
JSHandle<Method> method1 = vm_->GetFactory()->NewMethod(methodLiterals[1]);
@ -309,7 +312,7 @@ HWTEST_F_L0(PGOProfilerTest, DisEnableSample)
JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
constPool->SetJSPandaFile(pf.get());
uint32_t checksum = 304293;
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler3.abc");
ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
@ -364,7 +367,7 @@ HWTEST_F_L0(PGOProfilerTest, PGOProfilerManagerSample)
option.SetProfileDir(currentPath);
vm_ = JSNApi::CreateJSVM(option);
uint32_t checksum = 304293;
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "");
ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
JSHandle<JSArray> array = vm_->GetFactory()->NewJSArray();
@ -406,14 +409,14 @@ HWTEST_F_L0(PGOProfilerTest, PGOProfilerDoubleVM)
JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
constPool->SetJSPandaFile(pf.get());
uint32_t checksum = 304293;
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler5.abc");
ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
// worker vm read profile enable from PGOProfilerManager singleton
option.SetEnableProfile(false);
auto vm2 = JSNApi::CreateJSVM(option);
JSHandle<ConstantPool> constPool2 = vm2->GetFactory()->NewConstantPool(4);
constPool2->SetJSPandaFile(pf.get());
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler5.abc");
ASSERT_TRUE(vm2 != nullptr) << "Cannot create Runtime";
JSHandle<Method> method = vm2->GetFactory()->NewMethod(methodLiterals[0]);
@ -475,7 +478,7 @@ HWTEST_F_L0(PGOProfilerTest, PGOProfilerDecoderNoHotMethod)
JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
constPool->SetJSPandaFile(pf.get());
uint32_t checksum = 304293;
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler8.abc");
JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
@ -520,7 +523,7 @@ HWTEST_F_L0(PGOProfilerTest, PGOProfilerPostTask)
constPool->SetJSPandaFile(pf.get());
uint32_t checksum = 304293;
PGOProfilerManager::GetInstance()->SetApGenMode(ApGenMode::OVERWRITE);
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler9.abc");
JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
for (int i = 61; i < 91; i++) {
@ -572,6 +575,7 @@ HWTEST_F_L0(PGOProfilerTest, BinaryToText)
PGOProfilerHeader *header = nullptr;
PGOProfilerHeader::Build(&header, PGOProfilerHeader::LastSize());
std::unique_ptr<PGOAbcFilePool> abcFilePool = std::make_unique<PGOAbcFilePool>();
std::unique_ptr<PGOPandaFileInfos> pandaFileInfos = std::make_unique<PGOPandaFileInfos>();
std::unique_ptr<PGORecordDetailInfos> recordInfos = std::make_unique<PGORecordDetailInfos>(2);
@ -583,12 +587,17 @@ HWTEST_F_L0(PGOProfilerTest, BinaryToText)
auto *jsMethod =
Method::Cast(vm_->GetFactory()->NewMethod(methodLiteral.get(), MemSpaceType::NON_MOVABLE).GetTaggedValue());
ASSERT_TRUE(recordInfos->AddMethod("test", jsMethod, SampleMode::CALL_MODE, 1));
ASSERT_FALSE(recordInfos->AddMethod("test", jsMethod, SampleMode::CALL_MODE, 1));
ASSERT_FALSE(recordInfos->AddMethod("test", jsMethod, SampleMode::CALL_MODE, 1));
ApEntityId recordId(0);
recordInfos->GetRecordPool()->TryAdd("test", recordId);
ProfileType recordType(0, recordId, ProfileType::Kind::LocalRecordId);
ASSERT_TRUE(recordInfos->AddMethod(recordType, jsMethod, SampleMode::CALL_MODE, 1));
ASSERT_FALSE(recordInfos->AddMethod(recordType, jsMethod, SampleMode::CALL_MODE, 1));
ASSERT_FALSE(recordInfos->AddMethod(recordType, jsMethod, SampleMode::CALL_MODE, 1));
pandaFileInfos->ProcessToBinary(file, header->GetPandaInfoSection());
recordInfos->ProcessToBinary(nullptr, file, header);
PGOFileSectionInterface::ProcessSectionToBinary(file, header, *abcFilePool->GetPool());
header->SetFileSize(static_cast<uint32_t>(file.tellp()));
header->ProcessToBinary(file);
PGOProfilerEncoder::AddChecksum(file);
file.close();
@ -615,7 +624,7 @@ HWTEST_F_L0(PGOProfilerTest, TextToBinary)
file.close();
ASSERT_TRUE(PGOProfilerManager::GetInstance()->TextToBinary("ark-profiler10/modules.text", "ark-profiler10/", 2,
ApGenMode::MERGE));
ApGenMode::OVERWRITE));
PGOProfilerDecoder loader("ark-profiler10/modules.ap", 2);
ASSERT_TRUE(loader.LoadAndVerify(413775942));
@ -643,7 +652,7 @@ HWTEST_F_L0(PGOProfilerTest, FailResetProfilerInWorker)
// PgoProfiler is disabled as default.
vm_ = JSNApi::CreateJSVM(option);
uint32_t checksum = 304293;
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler12.abc");
ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
@ -728,7 +737,8 @@ HWTEST_F_L0(PGOProfilerTest, UseClassTypeTest)
auto pgoRWOpType = *reinterpret_cast<PGORWOpType *>(type);
if (std::string(methodName) == "Foot" || std::string(methodName) == "Arm") {
ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
ASSERT_EQ(pgoRWOpType.GetObjectInfo(0).GetProfileType(), ProfileType(methodId.GetOffset()));
ASSERT_EQ(pgoRWOpType.GetObjectInfo(0).GetProfileType(),
ProfileType(ApEntityId(PGORecordPool::RESERVED_COUNT), methodId.GetOffset()));
} else if (std::string(methodName) == "foo" || std::string(methodName) == "Body") {
ASSERT_TRUE(pgoRWOpType.GetCount() == 3);
}
@ -772,15 +782,15 @@ HWTEST_F_L0(PGOProfilerTest, DefineClassTypeTest)
}
ASSERT_EQ(desc->GetCtorLayoutDesc().size(), 3);
ASSERT_EQ(desc->GetPtLayoutDesc().size(), 1);
auto classId = EntityId(sampleType.GetProfileType().GetRaw());
auto classId = EntityId(sampleType.GetProfileType().GetId());
auto className = MethodLiteral::GetMethodName(jsPandaFile.get(), classId);
if (std::string(className) == "Arm") {
auto superClassId = EntityId(desc->GetSuperProfileType().GetRaw());
auto superClassId = EntityId(desc->GetSuperProfileType().GetId());
auto superClassName = MethodLiteral::GetMethodName(jsPandaFile.get(), superClassId);
ASSERT_EQ(std::string(superClassName), "Body");
ASSERT_EQ(desc->GetLayoutDesc().size(), 0);
} else if (std::string(className) == "Foot") {
auto superClassId = EntityId(desc->GetSuperProfileType().GetRaw());
auto superClassId = EntityId(desc->GetSuperProfileType().GetId());
auto superClassName = MethodLiteral::GetMethodName(jsPandaFile.get(), superClassId);
ASSERT_EQ(std::string(superClassName), "Body");
ASSERT_EQ(desc->GetLayoutDesc().size(), 0);
@ -985,7 +995,7 @@ HWTEST_F_L0(PGOProfilerTest, FileConsistencyCheck)
JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
constPool->SetJSPandaFile(pf.get());
uint32_t checksum = 304293;
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler.abc");
ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);

View File

@ -14,13 +14,18 @@
*/
#include "ecmascript/pgo_profiler/types/pgo_profile_type.h"
#include "ecmascript/log.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/pgo_profiler/pgo_profiler_info.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "macros.h"
namespace panda::ecmascript::pgo {
const ProfileType ProfileType::PROFILE_TYPE_NONE = ProfileType(0, 0);
ProfileTypeRef::ProfileTypeRef(PGOContext &context, const ProfileType &type)
{
ApEntityId apId;
ApEntityId apId(0);
context.GetProfileTypePool()->TryAdd(type, apId);
UpdateId(apId);
}
@ -32,7 +37,7 @@ ProfileType::ProfileType(PGOContext &context, ProfileTypeRef typeRef)
UpdateId(legacy.GetId());
UpdateKind(legacy.GetKind());
} else {
const auto *typeEntry = context.GetProfileTypePool()->GetRecord(typeRef.GetId());
const auto *typeEntry = context.GetProfileTypePool()->GetEntry(typeRef.GetId());
if (typeEntry == nullptr) {
LOG_ECMA(ERROR) << "Profile type ref: " << typeRef.GetTypeString() << " not found in ap file.";
} else {

View File

@ -20,6 +20,8 @@
#include <string>
#include <variant>
#include "ecmascript/log.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/pgo_profiler/pgo_context.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "libpandabase/utils/bit_field.h"
@ -38,27 +40,31 @@ public:
LiteralId,
ElementId,
BuiltinsId,
LegacyKind = BuiltinsId,
LocalRecordId,
TotalKinds,
UnknowId,
LegacyKind = UnknowId
UnknowId
};
static const ProfileType PROFILE_TYPE_NONE;
static constexpr uint32_t ID_BITFIELD_NUM = 29;
static constexpr uint32_t RECORD_ID_BITFIELD_NUM = 20;
static constexpr uint32_t ABC_ID_BITFIELD_NUM = 20;
static constexpr uint32_t KIND_BITFIELD_NUM = 15;
using IdBits = BitField<uint32_t, 0, ID_BITFIELD_NUM>;
using IdRecordBits = IdBits::NextField<uint32_t, RECORD_ID_BITFIELD_NUM>;
using KindBits = IdRecordBits::NextField<Kind, KIND_BITFIELD_NUM>;
using AbcIdBits = IdBits::NextField<uint32_t, ABC_ID_BITFIELD_NUM>;
using KindBits = AbcIdBits::NextField<Kind, KIND_BITFIELD_NUM>;
static_assert(KindBits::IsValid(Kind::TotalKinds));
ProfileType() = default;
ProfileType(PGOContext &context, ProfileTypeRef typeRef);
explicit ProfileType(uint32_t type, Kind kind = Kind::ClassId)
ProfileType(ApEntityId abcId, uint32_t type, Kind kind = Kind::ClassId)
{
if (UNLIKELY(!IdBits::IsValid(type))) {
type_ = 0;
} else {
UpdateAbcId(abcId);
UpdateId(type);
UpdateKind(kind);
}
@ -66,7 +72,7 @@ public:
bool IsNone() const
{
return type_ == 0;
return type_ == PROFILE_TYPE_NONE.type_;
}
uint64_t GetRaw() const
@ -99,9 +105,14 @@ public:
return KindBits::Decode(type_);
}
uint32_t GetRecordId() const
ApEntityId GetAbcId() const
{
return IdRecordBits::Decode(type_);
return AbcIdBits::Decode(type_);
}
void UpdateAbcId(ApEntityId abcId)
{
type_ = AbcIdBits::Update(type_, abcId);
}
bool operator<(const ProfileType &right) const
@ -121,12 +132,22 @@ public:
std::string GetTypeString() const
{
return std::to_string(type_);
std::stringstream stream;
stream << "type: " << std::showbase << std::hex << type_ <<
"(kind: " << std::showbase << std::dec << static_cast<uint32_t>(GetKind()) <<
", abcId: " << GetAbcId() <<
", id: " << GetId() << ")";
return stream.str();
}
void UpdateRecordId(uint32_t recordId)
void UpdateId(uint32_t id)
{
type_ = IdRecordBits::Update(type_, recordId);
type_ = IdBits::Update(type_, id);
}
void UpdateKind(Kind kind)
{
type_ = KindBits::Update(type_, kind);
}
private:
@ -135,10 +156,6 @@ private:
type_ = IdBits::Update(type_, type);
}
void UpdateKind(Kind kind)
{
type_ = KindBits::Update(type_, kind);
}
uint64_t type_ {0};
};
@ -153,7 +170,7 @@ public:
bool IsNone() const
{
return typeId_.GetOffset() == 0;
return typeId_ == 0;
}
ApEntityId GetId() const
@ -173,7 +190,7 @@ public:
std::string GetTypeString() const
{
return std::to_string(typeId_.GetOffset());
return std::to_string(typeId_);
}
void UpdateId(ApEntityId typeId)
@ -184,6 +201,7 @@ public:
private:
ApEntityId typeId_ {0};
};
static_assert(sizeof(ProfileTypeRef) == sizeof(uint32_t));
class ProfileTypeLegacy {
public:
@ -206,10 +224,7 @@ public:
}
}
explicit ProfileTypeLegacy(ProfileTypeRef profileTypeRef)
{
type_ = profileTypeRef.GetId().GetOffset();
}
explicit ProfileTypeLegacy(ProfileTypeRef profileTypeRef) : type_(profileTypeRef.GetId()) {}
bool IsNone() const
{

View File

@ -21,6 +21,7 @@
#include <variant>
#include "ecmascript/log_wrapper.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "ecmascript/pgo_profiler/types/pgo_profile_type.h"
#include "libpandabase/utils/bit_field.h"
#include "macros.h"
@ -96,10 +97,10 @@ public:
return PGOSampleTemplate(static_cast<PGOSampleTemplate::Type>(from.GetType()));
}
static PGOSampleTemplate CreateProfileType(int32_t profileType,
static PGOSampleTemplate CreateProfileType(ApEntityId recordId, int32_t profileType,
typename ProfileType::Kind kind = ProfileType::Kind::ClassId)
{
return PGOSampleTemplate(PGOProfileType(profileType, kind));
return PGOSampleTemplate(PGOProfileType(recordId, profileType, kind));
}
static PGOSampleTemplate NoneType()
@ -197,7 +198,7 @@ public:
uint32_t newMethodId = type.GetProfileType().GetId();
// If we have recorded a valid method if before, invalidate it.
if ((oldMethodId != newMethodId) && (oldMethodId != 0)) {
type_ = PGOProfileType(0);
type_ = ProfileType::PROFILE_TYPE_NONE;
}
return *this;
}