!4311 支持增加未在pgo文件中的函数

Merge pull request !4311 from hzzhouzebin/SupportExternalMethod
This commit is contained in:
openharmony_ci 2023-06-29 08:48:44 +00:00 committed by Gitee
commit a54b399699
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
12 changed files with 289 additions and 152 deletions

View File

@ -19,6 +19,7 @@
#include "ecmascript/compiler/type_recorder.h"
#include "ecmascript/interpreter/interpreter-inl.h"
#include "ecmascript/jspandafile/type_literal_extractor.h"
#include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
#include "ecmascript/ts_types/ts_type_parser.h"
#include "libpandafile/code_data_accessor.h"
@ -29,11 +30,12 @@ static T *InitializeMemory(T *mem, Args... args)
return new (mem) T(std::forward<Args>(args)...);
}
BytecodeInfoCollector::BytecodeInfoCollector(EcmaVM *vm, JSPandaFile *jsPandaFile,
BytecodeInfoCollector::BytecodeInfoCollector(EcmaVM *vm, JSPandaFile *jsPandaFile, PGOProfilerDecoder &pfDecoder,
size_t maxAotMethodSize, bool enableCollectLiteralInfo)
: vm_(vm),
jsPandaFile_(jsPandaFile),
bytecodeInfo_(maxAotMethodSize),
pfDecoder_(pfDecoder),
enableCollectLiteralInfo_(enableCollectLiteralInfo)
{
vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->SetBytecodeInfoCollector(this);
@ -126,6 +128,7 @@ void BytecodeInfoCollector::ProcessClasses()
SetMethodPcInfoIndex(methodOffset, processedInsns[insns]);
jsPandaFile_->SetMethodLiteralToMap(methodLiteral);
pfDecoder_.MatchAndMarkMethod(recordName, name.c_str(), methodId);
});
}
// class Construct need to use new target, can not fastcall

View File

@ -673,7 +673,7 @@ private:
class BytecodeInfoCollector {
public:
BytecodeInfoCollector(EcmaVM *vm, JSPandaFile *jsPandaFile,
BytecodeInfoCollector(EcmaVM *vm, JSPandaFile *jsPandaFile, PGOProfilerDecoder &pfDecoder,
size_t maxAotMethodSize, bool enableCollectLiteralInfo);
~BytecodeInfoCollector();
NO_COPY_SEMANTIC(BytecodeInfoCollector);
@ -778,6 +778,7 @@ private:
EcmaVM *vm_;
JSPandaFile *jsPandaFile_ {nullptr};
BCInfo bytecodeInfo_;
PGOProfilerDecoder &pfDecoder_;
size_t methodInfoIndex_ {0};
bool enableCollectLiteralInfo_ {false};
std::set<int32_t> classDefBCIndexes_ {};

View File

@ -15,6 +15,7 @@
#include "ecmascript/compiler/compilation_driver.h"
#include "ecmascript/compiler/file_generators.h"
#include "ecmascript/jspandafile/method_literal.h"
#include "ecmascript/ts_types/ts_manager.h"
namespace panda::ecmascript::kungfu {
@ -26,6 +27,7 @@ CompilationDriver::CompilationDriver(PGOProfilerDecoder &profilerDecoder,
const std::string &fileName,
const std::string &triple,
LOptions *lOptions,
CompilerLog *log,
bool outputAsm,
size_t maxMethodsInModule)
: vm_(collector->GetVM()),
@ -36,6 +38,7 @@ CompilationDriver::CompilationDriver(PGOProfilerDecoder &profilerDecoder,
fileName_(fileName),
triple_(triple),
lOptions_(lOptions),
log_(log),
outputAsm_(outputAsm),
maxMethodsInModule_(maxMethodsInModule)
{
@ -151,6 +154,16 @@ void CompilationDriver::TopologicalSortForRecords()
ASSERT(tpOrder.size() == mainMethods.size());
}
void CompilationDriver::FetchPGOMismatchResult()
{
ASSERT(log_ != nullptr);
uint32_t totalMethodCount = 0;
uint32_t mismatchMethodCount = 0;
std::set<std::pair<std::string, CString>> mismatchMethodSet {};
pfDecoder_.GetMismatchResult(totalMethodCount, mismatchMethodCount, mismatchMethodSet);
log_->SetPGOMismatchResult(totalMethodCount, mismatchMethodCount, mismatchMethodSet);
}
void CompilationDriver::UpdatePGO()
{
std::unordered_set<EntityId> newMethodIds;
@ -165,6 +178,7 @@ void CompilationDriver::UpdatePGO()
return newMethodIds;
};
pfDecoder_.Update(dfs);
FetchPGOMismatchResult();
}
void CompilationDriver::InitializeCompileQueue()
@ -180,7 +194,7 @@ bool CompilationDriver::FilterMethod(const CString &recordName, const MethodLite
const MethodPcInfo &methodPCInfo, const std::string &methodName) const
{
if (methodPCInfo.methodsSize > bytecodeInfo_.GetMaxMethodSize() ||
!pfDecoder_.Match(jsPandaFile_, recordName, methodLiteral)) {
!pfDecoder_.Match(recordName, methodLiteral->GetMethodId())) {
return true;
}

View File

@ -21,6 +21,7 @@
namespace panda::ecmascript::kungfu {
class AOTFileGenerator;
class CompilerLog;
struct LOptions;
class Module;
class CompilationDriver {
@ -33,6 +34,7 @@ public:
const std::string &fileName,
const std::string &triple,
LOptions *lOptions,
CompilerLog *log,
bool outputAsm,
size_t maxMethodsInModule);
~CompilationDriver();
@ -49,8 +51,7 @@ public:
{
const auto &methodList = bytecodeInfo_.GetMethodList();
auto &resolvedMethodInfo = methodList.at(resolvedMethod.GetOffset());
MethodLiteral *methodLiteral = jsPandaFile_->GetMethodLiteralByIndex(resolvedMethod.GetOffset());
if (pfDecoder_.Match(jsPandaFile_, recordName, methodLiteral) && !resolvedMethodInfo.IsTypeInferAbort()) {
if (pfDecoder_.Match(recordName, resolvedMethod) && !resolvedMethodInfo.IsTypeInferAbort()) {
return;
}
// update profile and update compile queue
@ -136,6 +137,8 @@ public:
CompileLastModuleThenDestroyIfNeeded();
}
void FetchPGOMismatchResult();
void AddResolvedMethod(const CString &recordName, uint32_t classLiteralOffset)
{
if (!IsPGOLoaded() || !bytecodeInfo_.HasClassDefMethod(classLiteralOffset)) {
@ -352,6 +355,7 @@ private:
std::string fileName_ {};
std::string triple_ {};
LOptions *lOptions_ {nullptr};
CompilerLog *log_ {nullptr};
bool outputAsm_ {false};
size_t maxMethodsInModule_ {0};
};

View File

@ -139,6 +139,7 @@ void CompilerLog::Print() const
if (compilerLogTime_) {
PrintTime();
}
PrintPGOMismatchedMethod();
PrintCompiledMethod();
}
@ -200,6 +201,21 @@ void CompilerLog::PrintCompiledMethod() const
}
}
void CompilerLog::PrintPGOMismatchedMethod() const
{
if (totalPGOMethodCount_ == 0) {
return;
}
LOG_COMPILER(INFO) << " ";
LOG_COMPILER(INFO) << " Number of mismatched methods from ap file : " << mismatchPGOMethodCount_ << " / "
<< totalPGOMethodCount_;
for (const auto &it : mismatchPGOMethodSet_) {
LOG_COMPILER(INFO) << " method: " << std::setw(METHOD_LENS) << it.first
<< " in record: " << std::setw(RECORD_LENS) << it.second
<< " has not been found in abc, and will be abandoned.";
}
}
void CompilerLog::AddMethodTime(const std::string& name, uint32_t id, double time)
{
auto methodInfo = std::make_pair(id, name);
@ -289,5 +305,12 @@ void PGOTypeLogList::PrintPGOTypeLog()
{
LOG_COMPILER(INFO) << log_;
}
// namespace panda::ecmascript::kungfu
void CompilerLog::SetPGOMismatchResult(uint32_t &totalMethodCount, uint32_t &mismatchMethodCount,
std::set<std::pair<std::string, CString>> &mismatchMethodSet)
{
totalPGOMethodCount_ = totalMethodCount;
mismatchPGOMethodCount_ = mismatchMethodCount;
mismatchPGOMethodSet_ = std::move(mismatchMethodSet);
}
} // namespace panda::ecmascript::kungfu

View File

@ -108,6 +108,8 @@ public:
void AddMethodTime(const std::string& name, uint32_t id, double time);
void AddPassTime(const std::string& name, double time);
int GetIndex();
void SetPGOMismatchResult(uint32_t &totalMethodCount, uint32_t &mismatchMethodCount,
std::set<std::pair<std::string, CString>> &mismatchMethodSet);
std::map<std::string, int> nameIndex_;
@ -125,6 +127,7 @@ private:
void PrintMethodTime() const;
void PrintTime() const;
void PrintCompiledMethod() const;
void PrintPGOMismatchedMethod() const;
int idx_ {0};
bool allMethod_ {false};
@ -139,6 +142,9 @@ private:
std::map<std::string, double> timePassMap_ {};
std::map<std::pair<uint32_t, std::string>, double> timeMethodMap_ {};
std::set<std::pair<std::string, CString>> compiledMethodSet_ {};
uint32_t totalPGOMethodCount_ {0};
uint32_t mismatchPGOMethodCount_ {0};
std::set<std::pair<std::string, CString>> mismatchPGOMethodSet_ {};
};
class MethodLogList {

View File

@ -45,7 +45,7 @@ bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName,
}
ResolveModule(jsPandaFile, fileName);
BytecodeInfoCollector collector(vm_, jsPandaFile, maxAotMethodSize_, ShouldCollect());
BytecodeInfoCollector collector(vm_, jsPandaFile, profilerDecoder_, maxAotMethodSize_, ShouldCollect());
// Checking released/debuggable pandafile uses method literals, which are initialized in BytecodeInfoCollector,
// should after it.
@ -63,6 +63,7 @@ bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName,
fileName,
triple_,
&lOptions,
log_,
log_->OutputASM(),
maxMethodsInModule_);

View File

@ -170,8 +170,7 @@ void PGOProfilerDecoder::Clear()
}
}
bool PGOProfilerDecoder::Match(const JSPandaFile *jsPandaFile, const CString &recordName,
const MethodLiteral *methodLiteral)
bool PGOProfilerDecoder::Match(const CString &recordName, PGOMethodId methodId)
{
if (!isLoaded_) {
return true;
@ -179,21 +178,7 @@ bool PGOProfilerDecoder::Match(const JSPandaFile *jsPandaFile, const CString &re
if (!isVerifySuccess_) {
return false;
}
EntityId methodId = methodLiteral->GetMethodId();
EntityId pgoMethodId(methodId);
if (IsMethodMatchEnabled()) {
if (jsPandaFile == nullptr) {
return false;
}
const char *methodName = MethodLiteral::GetMethodName(jsPandaFile, methodId);
uint32_t checksum =
PGOMethodInfo::CalcChecksum(methodName, methodLiteral->GetBytecodeArray(),
MethodLiteral::GetCodeSize(jsPandaFile, methodLiteral->GetMethodId()));
if (!GetMethodIdInPGO(recordName, checksum, methodName, pgoMethodId)) {
return false;
}
}
return recordSimpleInfos_->Match(recordName, pgoMethodId);
return recordSimpleInfos_->Match(recordName, methodId);
}
bool PGOProfilerDecoder::GetHClassLayoutDesc(PGOSampleType classType, PGOHClassLayoutDesc **desc) const
@ -203,4 +188,13 @@ bool PGOProfilerDecoder::GetHClassLayoutDesc(PGOSampleType classType, PGOHClassL
}
return recordSimpleInfos_->GetHClassLayoutDesc(classType, desc);
}
void PGOProfilerDecoder::GetMismatchResult(uint32_t &totalMethodCount, uint32_t &mismatchMethodCount,
std::set<std::pair<std::string, CString>> &mismatchMethodSet) const
{
if (!isLoaded_ || !isVerifySuccess_) {
return;
}
return recordSimpleInfos_->GetMismatchResult(totalMethodCount, mismatchMethodCount, mismatchMethodSet);
}
} // namespace panda::ecmascript

View File

@ -35,8 +35,7 @@ public:
NO_COPY_SEMANTIC(PGOProfilerDecoder);
NO_MOVE_SEMANTIC(PGOProfilerDecoder);
bool PUBLIC_API Match(const JSPandaFile *jsPandaFile, const CString &recordName,
const MethodLiteral *methodLiteral);
bool PUBLIC_API Match(const CString &recordName, PGOMethodId methodId);
bool PUBLIC_API LoadAndVerify(uint32_t checksum);
bool PUBLIC_API LoadFull();
@ -69,41 +68,31 @@ public:
if (!isLoaded_ || !isVerifySuccess_) {
return;
}
EntityId methodId(methodLiteral->GetMethodId());
EntityId pgoMethodId(methodId);
const auto *methodName = MethodLiteral::GetMethodName(jsPandaFile, methodLiteral->GetMethodId());
if (IsMethodMatchEnabled()) {
auto checksum =
PGOMethodInfo::CalcChecksum(MethodLiteral::GetMethodName(jsPandaFile, methodLiteral->GetMethodId()),
methodLiteral->GetBytecodeArray(),
PGOMethodInfo::CalcChecksum(methodName, methodLiteral->GetBytecodeArray(),
MethodLiteral::GetCodeSize(jsPandaFile, methodLiteral->GetMethodId()));
const auto *methodName = MethodLiteral::GetMethodName(jsPandaFile, methodId);
if (!GetMethodIdInPGO(recordName, checksum, methodName, pgoMethodId)) {
return;
}
return recordSimpleInfos_->GetTypeInfo(recordName, methodName, checksum, callback);
}
recordSimpleInfos_->GetTypeInfo(recordName, pgoMethodId, callback);
recordSimpleInfos_->GetTypeInfo(recordName, methodName, callback);
}
bool GetMethodIdInPGO(const CString &recordName, uint32_t checksum, const char *methodName,
EntityId &methodId) const
void MatchAndMarkMethod(const CString &recordName, const char *methodName, EntityId methodId)
{
bool hasRecord = true;
if (!isLoaded_ || !isVerifySuccess_) {
hasRecord = false;
return;
}
if (hasRecord) {
hasRecord = recordSimpleInfos_->GetMethodIdInPGO(recordName, checksum, methodName, methodId);
}
if (!hasRecord) {
LOG_COMPILER(DEBUG) << "No matched method found in PGO. recordName: " << recordName
<< ", methodName: " << methodName << ", checksum: " << std::hex << checksum;
}
return hasRecord;
recordSimpleInfos_->MatchAndMarkMethod(recordName, methodName, methodId);
}
void GetMismatchResult(uint32_t &totalMethodCount, uint32_t &mismatchMethodCount,
std::set<std::pair<std::string, CString>> &mismatchMethodSet) const;
bool IsMethodMatchEnabled() const
{
return false;
return header_->SupportMethodChecksum();
}
bool GetHClassLayoutDesc(PGOSampleType classType, PGOHClassLayoutDesc **desc) const;

View File

@ -19,6 +19,7 @@
#include "ecmascript/base/bit_helper.h"
#include "ecmascript/js_function.h"
#include "ecmascript/jspandafile/method_literal.h"
#include "ecmascript/mem/c_string.h"
#include "ecmascript/pgo_profiler/pgo_profiler_encoder.h"
#include "macros.h"
@ -505,7 +506,7 @@ void PGOMethodTypeSet::ObjDefOpTypeInfo::ProcessToText(std::string &text) const
bool PGOMethodInfoMap::AddMethod(Chunk *chunk, Method *jsMethod, SampleMode mode)
{
EntityId methodId(jsMethod->GetMethodId());
PGOMethodId methodId(jsMethod->GetMethodId());
auto result = methodInfos_.find(methodId);
if (result != methodInfos_.end()) {
auto info = result->second;
@ -526,7 +527,7 @@ bool PGOMethodInfoMap::AddMethod(Chunk *chunk, Method *jsMethod, SampleMode mode
}
}
PGOMethodTypeSet *PGOMethodInfoMap::GetOrInsertMethodTypeSet(Chunk *chunk, EntityId methodId)
PGOMethodTypeSet *PGOMethodInfoMap::GetOrInsertMethodTypeSet(Chunk *chunk, PGOMethodId methodId)
{
auto typeInfoSetIter = methodTypeInfos_.find(methodId);
if (typeInfoSetIter != methodTypeInfos_.end()) {
@ -538,7 +539,7 @@ PGOMethodTypeSet *PGOMethodInfoMap::GetOrInsertMethodTypeSet(Chunk *chunk, Entit
}
}
bool PGOMethodInfoMap::AddType(Chunk *chunk, EntityId methodId, int32_t offset, PGOSampleType type)
bool PGOMethodInfoMap::AddType(Chunk *chunk, PGOMethodId methodId, int32_t offset, PGOSampleType type)
{
auto typeInfoSet = GetOrInsertMethodTypeSet(chunk, methodId);
ASSERT(typeInfoSet != nullptr);
@ -547,7 +548,7 @@ bool PGOMethodInfoMap::AddType(Chunk *chunk, EntityId methodId, int32_t offset,
}
bool PGOMethodInfoMap::AddDefine(
Chunk *chunk, EntityId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType)
Chunk *chunk, PGOMethodId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType)
{
auto typeInfoSet = GetOrInsertMethodTypeSet(chunk, methodId);
ASSERT(typeInfoSet != nullptr);
@ -710,7 +711,7 @@ bool PGOMethodInfoMap::ParseFromText(Chunk *chunk, uint32_t threshold, const std
size_t len = methodName.size();
void *infoAddr = chunk->Allocate(PGOMethodInfo::Size(len));
auto info = new (infoAddr) PGOMethodInfo(EntityId(methodId), count, mode, methodName.c_str());
auto info = new (infoAddr) PGOMethodInfo(PGOMethodId(methodId), count, mode, methodName.c_str());
methodInfos_.emplace(methodId, info);
// Parse Type Info
@ -776,8 +777,7 @@ void PGOMethodInfoMap::ProcessToText(uint32_t threshold, const CString &recordNa
}
}
bool PGOMethodIdSet::ParseFromBinary(
NativeAreaAllocator *allocator, uint32_t threshold, void **buffer, PGOProfilerHeader *const header)
bool PGOMethodIdSet::ParseFromBinary(uint32_t threshold, void **buffer, PGOProfilerHeader *const header)
{
SectionInfo secInfo = base::ReadBuffer<SectionInfo>(buffer);
for (uint32_t j = 0; j < secInfo.number_; j++) {
@ -791,29 +791,36 @@ bool PGOMethodIdSet::ParseFromBinary(
}
continue;
}
methodIdSet_.emplace(info->GetMethodId());
methodInfoMap_.emplace(info->GetMethodName(), info->GetMethodId());
auto methodIter = methodInfoMap_.find(info->GetMethodName());
ASSERT(methodIter != methodInfoMap_.end());
auto &methodInfo = methodIter->second;
if (header->SupportMethodChecksum()) {
methodInfo.GetConsistencyInfo().SetChecksum(base::ReadBuffer<uint32_t>(buffer, sizeof(uint32_t)));
}
LOG_ECMA(DEBUG) << "Method:" << info->GetMethodId() << ELEMENT_SEPARATOR << info->GetCount()
<< ELEMENT_SEPARATOR << std::to_string(static_cast<int>(info->GetSampleMode()))
<< ELEMENT_SEPARATOR << info->GetMethodName();
if (header->SupportMethodChecksum()) {
auto checksum = base::ReadBuffer<uint32_t>(buffer, sizeof(uint32_t));
auto checksumIter = methodsChecksumMapping_.find(checksum);
if (checksumIter != methodsChecksumMapping_.end()) {
checksumIter->second.emplace(info->GetMethodId());
} else {
std::unordered_set<EntityId> methodIdSet = { info->GetMethodId() };
methodsChecksumMapping_.emplace(checksum, methodIdSet);
}
methodIdNameMapping_.emplace(info->GetMethodId(), info->GetMethodName());
}
if (header->SupportType()) {
auto typeInfoSet = allocator->New<PGOMethodTypeSet>();
typeInfoSet->ParseFromBinary(buffer);
methodTypeSet_.emplace(info->GetMethodId(), typeInfoSet);
methodInfo.GetPGOMethodTypeSet().ParseFromBinary(buffer);
}
}
return methodIdSet_.size() != 0;
return !methodInfoMap_.empty();
}
void PGOMethodIdSet::GetMismatchResult(const CString &recordName, uint32_t &totalMethodCount,
uint32_t &mismatchMethodCount,
std::set<std::pair<std::string, CString>> &mismatchMethodSet) const
{
totalMethodCount += methodInfoMap_.size();
for (const auto &method : methodInfoMap_) {
if (!method.second.IsMatch()) {
auto info = std::make_pair(method.first, recordName);
mismatchMethodSet.emplace(info);
mismatchMethodCount++;
}
}
}
PGOMethodInfoMap *PGORecordDetailInfos::GetMethodInfoMap(const CString &recordName)
@ -836,7 +843,7 @@ bool PGORecordDetailInfos::AddMethod(const CString &recordName, Method *jsMethod
return curMethodInfos->AddMethod(chunk_.get(), jsMethod, mode);
}
bool PGORecordDetailInfos::AddType(const CString &recordName, EntityId methodId, int32_t offset, PGOSampleType type)
bool PGORecordDetailInfos::AddType(const CString &recordName, PGOMethodId methodId, int32_t offset, PGOSampleType type)
{
auto curMethodInfos = GetMethodInfoMap(recordName);
ASSERT(curMethodInfos != nullptr);
@ -844,7 +851,7 @@ bool PGORecordDetailInfos::AddType(const CString &recordName, EntityId methodId,
}
bool PGORecordDetailInfos::AddDefine(
const CString &recordName, EntityId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType)
const CString &recordName, PGOMethodId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType)
{
auto curMethodInfos = GetMethodInfoMap(recordName);
ASSERT(curMethodInfos != nullptr);
@ -1088,8 +1095,8 @@ void PGORecordSimpleInfos::ParseFromBinary(void *buffer, PGOProfilerHeader *cons
void *addr = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + info->offset_);
for (uint32_t i = 0; i < info->number_; i++) {
auto recordName = base::ReadBuffer(&addr);
PGOMethodIdSet *methodIds = nativeAreaAllocator_.New<PGOMethodIdSet>();
if (methodIds->ParseFromBinary(&nativeAreaAllocator_, hotnessThreshold_, &addr, header)) {
PGOMethodIdSet *methodIds = nativeAreaAllocator_.New<PGOMethodIdSet>(chunk_.get());
if (methodIds->ParseFromBinary(hotnessThreshold_, &addr, header)) {
methodIds_.emplace(recordName, methodIds);
}
}

View File

@ -27,6 +27,7 @@
#include "ecmascript/log_wrapper.h"
#include "ecmascript/mem/c_containers.h"
#include "ecmascript/mem/c_string.h"
#include "ecmascript/mem/chunk_containers.h"
#include "ecmascript/mem/native_area_allocator.h"
#include "ecmascript/mem/slots.h"
#include "ecmascript/pgo_profiler/pgo_profiler_layout.h"
@ -48,6 +49,7 @@ struct SectionInfo {
uint32_t number_ {0};
};
static constexpr size_t ALIGN_SIZE = 4;
using PGOMethodId = EntityId;
/**
* |----PGOProfilerHeader
@ -74,6 +76,7 @@ static constexpr size_t ALIGN_SIZE = 4;
* |----------------count
* |----------------mode
* |----------------methodName
* |----------------methodChecksum
* |----------------...
* |------------PGOMethodTypeSet
* |----------------ScalarOpTypeInfo
@ -252,9 +255,9 @@ public:
static constexpr int METHOD_MODE_INDEX = 2;
static constexpr int METHOD_NAME_INDEX = 3;
explicit PGOMethodInfo(EntityId id) : id_(id) {}
explicit PGOMethodInfo(PGOMethodId id) : id_(id) {}
PGOMethodInfo(EntityId id, uint32_t count, SampleMode mode, const char *methodName)
PGOMethodInfo(PGOMethodId id, uint32_t count, SampleMode mode, const char *methodName)
: id_(id), count_(count), mode_(mode)
{
size_t len = strlen(methodName);
@ -312,7 +315,7 @@ public:
SetSampleMode(info->GetSampleMode());
}
EntityId GetMethodId() const
PGOMethodId GetMethodId() const
{
return id_;
}
@ -375,7 +378,7 @@ public:
private:
uint32_t size_ {0};
EntityId id_;
PGOMethodId id_;
uint32_t count_ {0};
SampleMode mode_ {SampleMode::CALL_MODE};
char methodName_ {0};
@ -593,6 +596,58 @@ private:
std::set<ObjDefOpTypeInfo> objDefOpTypeInfos_;
};
class PGODecodeMethodInfo {
public:
explicit PGODecodeMethodInfo(PGOMethodId id) : methodId_(id) {}
class ConsistencyInfo {
public:
void SetChecksum(uint32_t checksum)
{
checksum_ = checksum;
}
uint32_t GetChecksum() const
{
return checksum_;
}
private:
uint32_t checksum_ {0};
};
PGOMethodId GetMethodId() const
{
return methodId_;
}
PGOMethodTypeSet &GetPGOMethodTypeSet()
{
return pgoMethodTypeSet_;
}
ConsistencyInfo &GetConsistencyInfo()
{
return consistencyInfo_;
}
void SetMatch()
{
methodNameMatch_ = true;
}
bool IsMatch() const
{
return methodNameMatch_;
}
private:
PGOMethodId methodId_ {0};
bool methodNameMatch_ {false};
PGOMethodTypeSet pgoMethodTypeSet_ {};
ConsistencyInfo consistencyInfo_ {};
};
class PGOHClassLayoutDescInner {
public:
PGOHClassLayoutDescInner(size_t size, PGOSampleType type, PGOSampleType superType)
@ -705,8 +760,8 @@ public:
}
bool AddMethod(Chunk *chunk, Method *jsMethod, SampleMode mode);
bool AddType(Chunk *chunk, EntityId methodId, int32_t offset, PGOSampleType type);
bool AddDefine(Chunk *chunk, EntityId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType);
bool AddType(Chunk *chunk, PGOMethodId methodId, int32_t offset, PGOSampleType type);
bool AddDefine(Chunk *chunk, PGOMethodId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType);
void Merge(Chunk *chunk, PGOMethodInfoMap *methodInfos);
bool ParseFromBinary(Chunk *chunk, uint32_t threshold, void **buffer, PGOProfilerHeader *const header);
@ -720,86 +775,87 @@ public:
NO_MOVE_SEMANTIC(PGOMethodInfoMap);
private:
PGOMethodTypeSet *GetOrInsertMethodTypeSet(Chunk *chunk, EntityId methodId);
PGOMethodTypeSet *GetOrInsertMethodTypeSet(Chunk *chunk, PGOMethodId methodId);
CMap<EntityId, PGOMethodInfo *> methodInfos_;
CMap<EntityId, PGOMethodTypeSet *> methodTypeInfos_;
CMap<EntityId, uint32_t> methodsChecksum_;
CMap<PGOMethodId, PGOMethodInfo *> methodInfos_;
CMap<PGOMethodId, PGOMethodTypeSet *> methodTypeInfos_;
CMap<PGOMethodId, uint32_t> methodsChecksum_;
CMap<PGOSampleType, CMap<CString, TrackType>> globalLayoutDescInfos_;
};
class PGOMethodIdSet {
public:
PGOMethodIdSet() = default;
explicit PGOMethodIdSet(Chunk* chunk): methodInfoMap_(chunk) {};
~PGOMethodIdSet() = default;
void Clear(NativeAreaAllocator *allocator)
void Clear()
{
methodIdSet_.clear();
for (auto iter : methodTypeSet_) {
allocator->Delete(iter.second);
}
methodTypeSet_.clear();
methodsChecksumMapping_.clear();
candidateSet_.clear();
methodInfoMap_.clear();
}
bool Match(EntityId methodId)
{
return methodIdSet_.find(methodId) != methodIdSet_.end();
return candidateSet_.find(methodId) != candidateSet_.end();
}
template <typename Callback>
bool Update(const CString &recordName, Callback callback)
{
std::unordered_set<EntityId> newIds = callback(recordName, methodIdSet_);
std::unordered_set<EntityId> newIds = callback(recordName, candidateSet_);
if (!newIds.empty()) {
methodIdSet_.insert(newIds.begin(), newIds.end());
candidateSet_.insert(newIds.begin(), newIds.end());
return true;
}
return false;
}
template <typename Callback>
void GetTypeInfo(EntityId methodId, Callback callback)
void GetTypeInfo(const char *methodName, Callback callback)
{
auto iter = methodTypeSet_.find(methodId);
if (iter != methodTypeSet_.end()) {
iter->second->GetTypeInfo(callback);
auto iter = methodInfoMap_.find(methodName);
if (iter != methodInfoMap_.end()) {
iter->second.GetPGOMethodTypeSet().GetTypeInfo(callback);
}
}
const std::map<EntityId, PGOMethodTypeSet *> &GetMethodTypeSet() const
template <typename Callback>
void GetTypeInfo(const char *methodName, uint32_t checksum, Callback callback)
{
return methodTypeSet_;
auto iter = methodInfoMap_.find(methodName);
if (iter == methodInfoMap_.end()) {
return;
}
auto &methodInfo = iter->second;
if (methodInfo.GetConsistencyInfo().GetChecksum() != checksum) {
LOG_ECMA(DEBUG) << "Method checksum mismatched, name: " << methodName;
return;
}
return methodInfo.GetPGOMethodTypeSet().GetTypeInfo(callback);
}
bool GetMethodIdInPGO(uint32_t checksum, const char *methodName, EntityId &methodId) const
void MatchAndMarkMethod(const char *methodName, EntityId methodId)
{
auto iter = methodsChecksumMapping_.find(checksum);
if (iter == methodsChecksumMapping_.end()) {
return false;
const auto &iter = methodInfoMap_.find(methodName);
if (iter == methodInfoMap_.end()) {
// no matching method in PGO file.
return;
}
for (const auto &pgoMethodId : iter->second) {
auto methodNameIter = methodIdNameMapping_.find(pgoMethodId);
ASSERT(methodNameIter != methodIdNameMapping_.end());
if (methodNameIter->second == methodName) {
methodId = pgoMethodId;
return true;
}
}
return false;
candidateSet_.emplace(methodId);
iter->second.SetMatch();
}
bool ParseFromBinary(
NativeAreaAllocator *allocator, uint32_t threshold, void **buffer, PGOProfilerHeader *const header);
bool ParseFromBinary(uint32_t threshold, void **buffer, PGOProfilerHeader *const header);
void GetMismatchResult(const CString &recordName, uint32_t &totalMethodCount, uint32_t &mismatchMethodCount,
std::set<std::pair<std::string, CString>> &mismatchMethodSet) const;
NO_COPY_SEMANTIC(PGOMethodIdSet);
NO_MOVE_SEMANTIC(PGOMethodIdSet);
private:
std::unordered_set<EntityId> methodIdSet_;
std::map<EntityId, PGOMethodTypeSet *> methodTypeSet_;
std::unordered_map<EntityId, CString> methodIdNameMapping_;
std::unordered_map<uint32_t, std::unordered_set<EntityId>> methodsChecksumMapping_;
std::unordered_set<EntityId> candidateSet_; // methodId in abc file, DO NOT for pgo internal use
ChunkUnorderedMap<CString, PGODecodeMethodInfo> methodInfoMap_;
};
class PGORecordDetailInfos {
@ -826,9 +882,9 @@ public:
// If it is a new method, return true.
bool AddMethod(const CString &recordName, Method *jsMethod, SampleMode mode);
bool AddType(const CString &recordName, EntityId methodId, int32_t offset, PGOSampleType type);
bool AddType(const CString &recordName, PGOMethodId methodId, int32_t offset, PGOSampleType type);
bool AddDefine(
const CString &recordName, EntityId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType);
const CString &recordName, PGOMethodId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType);
bool AddLayout(PGOSampleType type, JSTaggedType hclass, PGOObjLayoutKind kind);
void Merge(const PGORecordDetailInfos &recordInfos);
@ -855,7 +911,11 @@ private:
class PGORecordSimpleInfos {
public:
explicit PGORecordSimpleInfos(uint32_t threshold) : hotnessThreshold_(threshold) {}
explicit PGORecordSimpleInfos(uint32_t threshold) : hotnessThreshold_(threshold)
{
chunk_ = std::make_unique<Chunk>(&nativeAreaAllocator_);
}
~PGORecordSimpleInfos()
{
Clear();
@ -863,11 +923,12 @@ public:
void Clear()
{
for (auto iter : methodIds_) {
iter.second->Clear(&nativeAreaAllocator_);
for (const auto& iter : methodIds_) {
iter.second->Clear();
nativeAreaAllocator_.Delete(iter.second);
}
methodIds_.clear();
chunk_ = std::make_unique<Chunk>(&nativeAreaAllocator_);
}
bool Match(const CString &recordName, EntityId methodId);
@ -889,7 +950,7 @@ public:
if (iter != methodIds_.end()) {
iter->second->Update(recordName, callback);
} else {
PGOMethodIdSet *methodIds = nativeAreaAllocator_.New<PGOMethodIdSet>();
PGOMethodIdSet *methodIds = nativeAreaAllocator_.New<PGOMethodIdSet>(chunk_.get());
if (methodIds->Update(recordName, callback)) {
methodIds_.emplace(recordName, methodIds);
} else {
@ -899,11 +960,20 @@ public:
}
template <typename Callback>
void GetTypeInfo(const CString &recordName, EntityId methodId, Callback callback)
void GetTypeInfo(const CString &recordName, const char *methodName, Callback callback)
{
auto iter = methodIds_.find(recordName);
if (iter != methodIds_.end()) {
iter->second->GetTypeInfo(methodId, callback);
iter->second->GetTypeInfo(methodName, callback);
}
}
template <typename Callback>
void GetTypeInfo(const CString &recordName, const char *methodName, uint32_t checksum, Callback callback)
{
auto iter = methodIds_.find(recordName);
if (iter != methodIds_.end()) {
iter->second->GetTypeInfo(methodName, checksum, callback);
}
}
@ -917,14 +987,21 @@ public:
return false;
}
bool GetMethodIdInPGO(const CString &recordName, uint32_t checksum, const char *methodName,
EntityId &methodId) const
void MatchAndMarkMethod(const CString &recordName, const char *methodName, EntityId methodId)
{
auto iter = methodIds_.find(recordName);
if (iter != methodIds_.end()) {
return iter->second->GetMethodIdInPGO(checksum, methodName, methodId);
return iter->second->MatchAndMarkMethod(methodName, methodId);
}
}
void GetMismatchResult(uint32_t &totalMethodCount, uint32_t &mismatchMethodCount,
std::set<std::pair<std::string, CString>> &mismatchMethodSet) const
{
for (const auto &methodId : methodIds_) {
methodId.second->GetMismatchResult(methodId.first, totalMethodCount, mismatchMethodCount,
mismatchMethodSet);
}
return false;
}
void ParseFromBinary(void *buffer, PGOProfilerHeader *const header);
@ -937,6 +1014,7 @@ private:
uint32_t hotnessThreshold_ {2};
NativeAreaAllocator nativeAreaAllocator_;
std::unique_ptr<Chunk> chunk_;
CUnorderedMap<CString, PGOMethodIdSet *> methodIds_;
std::set<PGOHClassLayoutDesc> moduleLayoutDescInfos_;
};

View File

@ -122,10 +122,10 @@ HWTEST_F_L0(PGOProfilerTest, Sample)
CString expectRecordName = "test";
#if defined(SUPPORT_ENABLE_ASM_INTERP)
ASSERT_TRUE(loader.LoadAndVerify(checksum));
ASSERT_TRUE(!loader.Match(pf.get(), expectRecordName, methodLiterals[0]));
ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
#else
ASSERT_TRUE(!loader.LoadAndVerify(checksum));
ASSERT_TRUE(loader.Match(pf.get(), expectRecordName, methodLiterals[0]));
ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
#endif
unlink("ark-profiler/modules.ap");
rmdir("ark-profiler/");
@ -185,12 +185,17 @@ HWTEST_F_L0(PGOProfilerTest, Sample1)
CString expectRecordName = "test";
#if defined(SUPPORT_ENABLE_ASM_INTERP)
ASSERT_TRUE(loader.LoadAndVerify(checksum));
ASSERT_TRUE(loader.Match(pf.get(), expectRecordName, methodLiterals[0]));
ASSERT_TRUE(loader.Match(pf.get(), expectRecordName, methodLiterals[2]));
ASSERT_TRUE(!loader.Match(pf.get(), expectRecordName, methodLiterals[1]));
for (uint32_t idx = 0; idx < 3; idx++) {
loader.MatchAndMarkMethod(expectRecordName,
methodLiterals[idx]->GetMethodName(pf.get(), methodLiterals[idx]->GetMethodId()),
methodLiterals[idx]->GetMethodId());
}
ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[2]->GetMethodId()));
ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
#else
ASSERT_TRUE(!loader.LoadAndVerify(checksum));
ASSERT_TRUE(loader.Match(pf.get(), expectRecordName, methodLiterals[1]));
ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
#endif
unlink("ark-profiler1/modules.ap");
rmdir("ark-profiler1/");
@ -241,12 +246,20 @@ HWTEST_F_L0(PGOProfilerTest, Sample2)
CString expectRecordName1 = "test1";
#if defined(SUPPORT_ENABLE_ASM_INTERP)
ASSERT_TRUE(loader.LoadAndVerify(checksum));
ASSERT_TRUE(!loader.Match(pf.get(), expectRecordName, methodLiterals[0]));
for (uint32_t idx = 0; idx < 2; idx++) {
loader.MatchAndMarkMethod(expectRecordName,
methodLiterals[idx]->GetMethodName(pf.get(), methodLiterals[idx]->GetMethodId()),
methodLiterals[idx]->GetMethodId());
loader.MatchAndMarkMethod(expectRecordName1,
methodLiterals[idx]->GetMethodName(pf.get(), methodLiterals[idx]->GetMethodId()),
methodLiterals[idx]->GetMethodId());
}
ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
#else
ASSERT_TRUE(!loader.LoadAndVerify(checksum));
ASSERT_TRUE(loader.Match(pf.get(), expectRecordName, methodLiterals[0]));
ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
#endif
ASSERT_TRUE(loader.Match(pf.get(), expectRecordName1, methodLiterals[1]));
ASSERT_TRUE(loader.Match(expectRecordName1, methodLiterals[1]->GetMethodId()));
unlink("ark-profiler2/modules.ap");
rmdir("ark-profiler2/");
}
@ -285,7 +298,7 @@ HWTEST_F_L0(PGOProfilerTest, DisEnableSample)
// path is empty()
ASSERT_TRUE(!loader.LoadAndVerify(checksum));
CString expectRecordName = "test";
ASSERT_TRUE(loader.Match(pf.get(), expectRecordName, methodLiterals[0]));
ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
rmdir("ark-profiler3/");
}
@ -401,15 +414,15 @@ HWTEST_F_L0(PGOProfilerTest, PGOProfilerDoubleVM)
mkdir("ark-profiler5/profiler", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
ASSERT_TRUE(!loader.LoadAndVerify(checksum));
CString expectRecordName = "test";
ASSERT_TRUE(loader.Match(pf.get(), expectRecordName, methodLiterals[1]));
ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
PGOProfilerDecoder loader1("ark-profiler5/modules.ap", 2);
#if defined(SUPPORT_ENABLE_ASM_INTERP)
ASSERT_TRUE(loader1.LoadAndVerify(checksum));
ASSERT_TRUE(!loader1.Match(pf.get(), expectRecordName, methodLiterals[1]));
ASSERT_TRUE(!loader1.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
#else
ASSERT_TRUE(!loader1.LoadAndVerify(checksum));
ASSERT_TRUE(loader1.Match(pf.get(), expectRecordName, methodLiterals[1]));
ASSERT_TRUE(loader1.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
#endif
unlink("ark-profiler5/modules.ap");
@ -449,10 +462,10 @@ HWTEST_F_L0(PGOProfilerTest, PGOProfilerDecoderNoHotMethod)
CString expectRecordName = "test";
#if defined(SUPPORT_ENABLE_ASM_INTERP)
ASSERT_TRUE(loader.LoadAndVerify(checksum));
ASSERT_TRUE(!loader.Match(pf.get(), expectRecordName, methodLiterals[0]));
ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
#else
ASSERT_TRUE(!loader.LoadAndVerify(checksum));
ASSERT_TRUE(loader.Match(pf.get(), expectRecordName, methodLiterals[0]));
ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
#endif
unlink("ark-profiler8/modules.ap");
@ -501,14 +514,18 @@ HWTEST_F_L0(PGOProfilerTest, PGOProfilerPostTask)
ASSERT_TRUE(!loader.LoadAndVerify(checksum));
#endif
CString expectRecordName = "test";
for (int i = 0; i < 100; i++) {
EntityId methodId = methodLiterals[i]->GetMethodId();
loader.MatchAndMarkMethod(expectRecordName, methodLiterals[i]->GetMethodName(pf.get(), methodId), methodId);
}
for (int i = 61; i < 91; i++) {
if (i % 3 == 0) {
ASSERT_TRUE(loader.Match(pf.get(), expectRecordName, methodLiterals[i]));
ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[i]->GetMethodId()));
} else {
#if defined(SUPPORT_ENABLE_ASM_INTERP)
ASSERT_TRUE(!loader.Match(pf.get(), expectRecordName, methodLiterals[i]));
ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[i]->GetMethodId()));
#else
ASSERT_TRUE(loader.Match(pf.get(), expectRecordName, methodLiterals[i]));
ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[i]->GetMethodId()));
#endif
}
}
@ -652,7 +669,7 @@ HWTEST_F_L0(PGOProfilerTest, FailResetProfilerInWorker)
// path is empty()
ASSERT_TRUE(!loader.LoadAndVerify(checksum));
CString expectRecordName = "test";
ASSERT_TRUE(loader.Match(pf.get(), expectRecordName, methodLiterals[0]));
ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
rmdir("ark-profiler12/");
}
} // namespace panda::test