Optimize arkstackmap size and add stackmap dump

Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I6E00K

Signed-off-by: wuzhangda <wuzhangda@huawei.com>
Change-Id: I9961aca3de3da6a727b48bf848bb7338465b0f6f
This commit is contained in:
wuzhangda 2023-03-20 09:26:31 +08:00
parent a051f661ca
commit 682f28bf73
23 changed files with 732 additions and 472 deletions

View File

@ -726,6 +726,7 @@ ecma_source = [
"ecmascript/stackmap/ark_stackmap_builder.cpp",
"ecmascript/stackmap/ark_stackmap_parser.cpp",
"ecmascript/stackmap/llvm_stackmap_parser.cpp",
"ecmascript/stackmap/llvm_stackmap_type.cpp",
"ecmascript/subtyping_operator.cpp",
"ecmascript/taskpool/taskpool.cpp",
"ecmascript/taskpool/runner.cpp",

View File

@ -288,7 +288,6 @@ bool AnFileInfo::Load(const std::string &filename)
}
fileMapMem_ = FileMap(realPath.c_str(), FILE_RDONLY, PAGE_PROT_READ);
if (fileMapMem_.GetOriginAddr() == nullptr) {
LOG_ECMA(ERROR) << "File mmap failed";
return false;
@ -790,7 +789,7 @@ void AOTFileInfo::Destroy()
}
bool AOTFileInfo::CalCallSiteInfo(uintptr_t retAddr,
std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec>& ret) const
std::tuple<uint64_t, uint8_t *, int, CalleeRegAndOffsetVec>& ret) const
{
uint64_t textStart = 0;
uint8_t *stackmapAddr = nullptr;
@ -823,11 +822,11 @@ bool AOTFileInfo::CalCallSiteInfo(uintptr_t retAddr,
ASSERT(it != t);
ASSERT((it->codeAddr_ <= target.codeAddr_) && (target.codeAddr_ < it->codeAddr_ + it->funcSize_));
delta = it->fpDeltaPrevFrameSp_;
kungfu::CalleeRegAndOffsetVec calleeRegInfo;
CalleeRegAndOffsetVec calleeRegInfo;
for (uint32_t j = 0; j < it->calleeRegisterNum_; j++) {
kungfu::DwarfRegType reg = static_cast<kungfu::DwarfRegType>(it->CalleeReg2Offset_[2 * j]);
kungfu::OffsetType offset = static_cast<kungfu::OffsetType>(it->CalleeReg2Offset_[2 * j + 1]);
kungfu::DwarfRegAndOffsetType regAndOffset = std::make_pair(reg, offset);
DwarfRegType reg = static_cast<DwarfRegType>(it->CalleeReg2Offset_[2 * j]);
OffsetType offset = static_cast<OffsetType>(it->CalleeReg2Offset_[2 * j + 1]);
DwarfRegAndOffsetType regAndOffset = std::make_pair(reg, offset);
calleeRegInfo.emplace_back(regAndOffset);
}
ret = std::make_tuple(textStart, stackmapAddr, delta, calleeRegInfo);

View File

@ -182,6 +182,10 @@ private:
class PUBLIC_API AOTFileInfo {
public:
using CallSignature = kungfu::CallSignature;
using CalleeRegAndOffsetVec = kungfu::CalleeRegAndOffsetVec;
using DwarfRegType = kungfu::LLVMStackMapType::DwarfRegType;
using OffsetType = kungfu::LLVMStackMapType::OffsetType;
using DwarfRegAndOffsetType = kungfu::LLVMStackMapType::DwarfRegAndOffsetType;
AOTFileInfo() = default;
virtual ~AOTFileInfo() = default;
@ -260,7 +264,7 @@ public:
}
void AddEntry(CallSignature::TargetKind kind, bool isMainFunc, int indexInKind, uint64_t offset,
uint32_t moduleIndex, int delta, uint32_t size, kungfu::CalleeRegAndOffsetVec info = {})
uint32_t moduleIndex, int delta, uint32_t size, CalleeRegAndOffsetVec info = {})
{
FuncEntryDes des;
if (memset_s(&des, sizeof(des), 0, sizeof(des)) != EOK) {
@ -275,8 +279,8 @@ public:
des.fpDeltaPrevFrameSp_ = delta;
des.funcSize_ = size;
des.calleeRegisterNum_ = info.size();
kungfu::DwarfRegType reg = 0;
kungfu::OffsetType regOffset = 0;
DwarfRegType reg = 0;
OffsetType regOffset = 0;
for (size_t i = 0; i < info.size(); i ++) {
std::tie(reg, regOffset) = info[i];
des.CalleeReg2Offset_[2 * i] = static_cast<int32_t>(reg);
@ -300,7 +304,7 @@ public:
totalCodeSize_ += size;
}
using CallSiteInfo = std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec>;
using CallSiteInfo = std::tuple<uint64_t, uint8_t *, int, CalleeRegAndOffsetVec>;
bool CalCallSiteInfo(uintptr_t retAddr, CallSiteInfo& ret) const;

View File

@ -351,7 +351,6 @@ Section Headers:
*/
void ElfBuilder::PackELFSections(std::ofstream &file)
{
std::map<ElfSecName, std::pair<uint64_t, uint32_t>> &sections = sectionDes_.sectionsInfo_;
uint32_t secNum = sections.size() + 1; // 1 : section id = 0 is null section
std::unique_ptr<llvm::ELF::Elf64_Shdr []> shdr = std::make_unique<llvm::ELF::Elf64_Shdr []>(secNum);
@ -440,7 +439,7 @@ void ElfBuilder::PackELFSegment(std::ofstream &file)
{
llvm::ELF::Elf64_Off e_phoff = file.tellp();
long phoff = (long)offsetof(struct llvm::ELF::Elf64_Ehdr, e_phoff);
// write Elf32_Off e_phoff;
// write Elf32_Off e_phoff
file.seekp(phoff);
file.write(reinterpret_cast<char *>(&e_phoff), sizeof(e_phoff));
file.seekp(e_phoff);

View File

@ -39,6 +39,46 @@ public:
static constexpr int SP = -1;
static constexpr int FP = -1;
#endif
static int GetFpRegByTriple(Triple triple)
{
int fp = -1;
switch (triple) {
case Triple::TRIPLE_AMD64:
fp = 6;
break;
case Triple::TRIPLE_ARM32:
fp = 11;
break;
case Triple::TRIPLE_AARCH64:
fp = 29;
break;
default:
UNREACHABLE();
break;
}
return fp;
}
static int GetSpRegByTriple(Triple triple)
{
int sp = -1;
switch (triple) {
case Triple::TRIPLE_AMD64:
sp = 7;
break;
case Triple::TRIPLE_ARM32:
sp = 13;
break;
case Triple::TRIPLE_AARCH64:
sp = 31;
break;
default:
UNREACHABLE();
break;
}
return sp;
}
};
enum Distance {

View File

@ -100,8 +100,8 @@ public:
bool ShouldDumpToAOTFile() const
{
bool saveForAot = false;
switch (value_) {
bool saveForAot = false;
switch (value_) {
case ElfSecName::RODATA:
case ElfSecName::RODATA_CST4:
case ElfSecName::RODATA_CST8:
@ -119,8 +119,8 @@ public:
default: {
break;
}
}
return saveForAot;
}
return saveForAot;
}
ElfSecName Value() const
@ -144,20 +144,20 @@ public:
void InitShTypeAndFlag()
{
std::map<ElfSecName, std::pair<unsigned, unsigned>> nameToTypeAndFlag = {
{ElfSecName::RODATA, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE)},
{ElfSecName::RODATA_CST4, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE)},
{ElfSecName::RODATA_CST8, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE)},
{ElfSecName::RODATA_CST16, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE)},
{ElfSecName::RODATA_CST32, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE)},
{ElfSecName::TEXT, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR)},
{ElfSecName::DATA, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE)},
{ElfSecName::GOT, std::pair<unsigned, unsigned>(llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE)},
{ElfSecName::RELATEXT, std::pair<unsigned, unsigned>(llvm::ELF::SHT_RELA, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE)},
{ElfSecName::STRTAB, std::pair<unsigned, unsigned>(llvm::ELF::SHT_STRTAB, llvm::ELF::SHF_ALLOC)},
{ElfSecName::SYMTAB, std::pair<unsigned, unsigned>(llvm::ELF::SHT_SYMTAB, llvm::ELF::SHF_ALLOC)},
{ElfSecName::LLVM_STACKMAP, std::pair<unsigned, unsigned>(llvm::ELF::SHT_RELA, llvm::ELF::SHF_ALLOC)},
{ElfSecName::ARK_FUNCENTRY, std::pair<unsigned, unsigned>(llvm::ELF::SHF_WRITE, llvm::ELF::SHF_ALLOC)},
{ElfSecName::ARK_STACKMAP, std::pair<unsigned, unsigned>(llvm::ELF::SHF_WRITE, llvm::ELF::SHF_ALLOC)},
{ElfSecName::RODATA, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}},
{ElfSecName::RODATA_CST4, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}},
{ElfSecName::RODATA_CST8, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}},
{ElfSecName::RODATA_CST16, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}},
{ElfSecName::RODATA_CST32, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE}},
{ElfSecName::TEXT, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR}},
{ElfSecName::DATA, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE}},
{ElfSecName::GOT, {llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE}},
{ElfSecName::RELATEXT, {llvm::ELF::SHT_RELA, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE}},
{ElfSecName::STRTAB, {llvm::ELF::SHT_STRTAB, llvm::ELF::SHF_ALLOC}},
{ElfSecName::SYMTAB, {llvm::ELF::SHT_SYMTAB, llvm::ELF::SHF_ALLOC}},
{ElfSecName::LLVM_STACKMAP, {llvm::ELF::SHT_RELA, llvm::ELF::SHF_ALLOC}},
{ElfSecName::ARK_FUNCENTRY, {llvm::ELF::SHF_WRITE, llvm::ELF::SHF_ALLOC}},
{ElfSecName::ARK_STACKMAP, {llvm::ELF::SHF_WRITE, llvm::ELF::SHF_ALLOC}},
};
auto it = nameToTypeAndFlag.find(value_);
if (it == nameToTypeAndFlag.end()) {

View File

@ -35,12 +35,17 @@ void Module::CollectStackMapDes(ModuleSectionDes& des) const
std::shared_ptr<uint8_t> ptr = nullptr;
uint32_t size = 0;
ArkStackMapBuilder builder;
std::tie(ptr, size) = builder.Run(std::move(stackmapPtr), textAddr);
std::tie(ptr, size) = builder.Run(std::move(stackmapPtr), textAddr, GetTriple());
des.EraseSec(ElfSecName::LLVM_STACKMAP);
des.SetArkStackMapPtr(ptr);
des.SetArkStackMapSize(size);
}
Triple Module::GetTriple() const
{
return llvmModule_->GetCompilationConfig()->GetTriple();
}
void Module::CollectFuncEntryInfo(std::map<uintptr_t, std::string> &addr2name, StubFileInfo &stubInfo,
uint32_t moduleIndex, const CompilerLog &log)
{

View File

@ -46,6 +46,8 @@ public:
void CollectStackMapDes(ModuleSectionDes &moduleDes) const;
Triple GetTriple() const;
const CompilationConfig *GetCompilationConfig()
{
return llvmModule_->GetCompilationConfig();

View File

@ -52,7 +52,7 @@ CalleeReg::CalleeReg()
#endif
}
int CalleeReg::FindCallRegOrder(const DwarfRegType reg) const
int CalleeReg::FindCallRegOrder(const LLVMStackMapType::DwarfRegType reg) const
{
auto it = reg2Location_.find(static_cast<DwarfReg>(reg));
if (it != reg2Location_.end()) {
@ -65,7 +65,7 @@ int CalleeReg::FindCallRegOrder(const DwarfRegType reg) const
int CalleeReg::FindCallRegOrder(const DwarfReg reg) const
{
auto order = FindCallRegOrder(static_cast<DwarfRegType>(reg));
auto order = FindCallRegOrder(static_cast<LLVMStackMapType::DwarfRegType>(reg));
return order;
}

View File

@ -22,7 +22,7 @@
namespace panda::ecmascript::kungfu {
#if defined(PANDA_TARGET_AMD64)
static const int MAX_CALLEE_SAVE_REIGISTER_NUM = 32;
enum class DwarfReg: DwarfRegType {
enum class DwarfReg: LLVMStackMapType::DwarfRegType {
RBX = 3,
R12 = 12,
R13 = 13,
@ -31,7 +31,7 @@ enum class DwarfReg: DwarfRegType {
};
#elif defined(PANDA_TARGET_ARM64)
static const int MAX_CALLEE_SAVE_REIGISTER_NUM = 32;
enum class DwarfReg: DwarfRegType {
enum class DwarfReg: LLVMStackMapType::DwarfRegType {
D8 = 72,
D9 = 73,
D10 = 74,
@ -54,14 +54,14 @@ enum class DwarfReg: DwarfRegType {
};
#else
static const int MAX_CALLEE_SAVE_REIGISTER_NUM = 16;
enum class DwarfReg: DwarfRegType {
enum class DwarfReg: LLVMStackMapType::DwarfRegType {
};
#endif
class CalleeReg {
public:
PUBLIC_API CalleeReg();
virtual PUBLIC_API ~CalleeReg() = default;
int PUBLIC_API FindCallRegOrder(const DwarfRegType reg) const;
int PUBLIC_API FindCallRegOrder(const LLVMStackMapType::DwarfRegType reg) const;
int PUBLIC_API FindCallRegOrder(const DwarfReg reg) const;
int PUBLIC_API GetCallRegNum() const;
private:

View File

@ -69,18 +69,18 @@ private:
JSTaggedType *top_;
};
void Deoptimizier::CollectVregs(const std::vector<kungfu::ARKDeopt>& deoptBundle)
void Deoptimizier::CollectVregs(const std::vector<ARKDeopt>& deoptBundle)
{
deoptVregs_.clear();
for (size_t i = 0; i < deoptBundle.size(); i++) {
kungfu::ARKDeopt deopt = deoptBundle.at(i);
ARKDeopt deopt = deoptBundle.at(i);
JSTaggedType v;
kungfu::OffsetType id = deopt.Id;
if (std::holds_alternative<kungfu::DwarfRegAndOffsetType>(deopt.value)) {
ASSERT(deopt.kind == kungfu::LocationTy::Kind::INDIRECT);
auto value = std::get<kungfu::DwarfRegAndOffsetType>(deopt.value);
kungfu::DwarfRegType dwarfReg = value.first;
kungfu::OffsetType offset = value.second;
VRegId id = deopt.id;
if (std::holds_alternative<DwarfRegAndOffsetType>(deopt.value)) {
ASSERT(deopt.kind == LocationTy::Kind::INDIRECT);
auto value = std::get<DwarfRegAndOffsetType>(deopt.value);
DwarfRegType dwarfReg = value.first;
OffsetType offset = value.second;
ASSERT (dwarfReg == GCStackMapRegisters::FP || dwarfReg == GCStackMapRegisters::SP);
uintptr_t addr;
if (dwarfReg == GCStackMapRegisters::SP) {
@ -89,16 +89,16 @@ void Deoptimizier::CollectVregs(const std::vector<kungfu::ARKDeopt>& deoptBundle
addr = context_.callsiteFp + offset;
}
v = *(reinterpret_cast<JSTaggedType *>(addr));
} else if (std::holds_alternative<kungfu::LargeInt>(deopt.value)) {
ASSERT(deopt.kind == kungfu::LocationTy::Kind::CONSTANTNDEX);
v = JSTaggedType(static_cast<int64_t>(std::get<kungfu::LargeInt>(deopt.value)));
} else if (std::holds_alternative<LargeInt>(deopt.value)) {
ASSERT(deopt.kind == LocationTy::Kind::CONSTANTNDEX);
v = JSTaggedType(static_cast<int64_t>(std::get<LargeInt>(deopt.value)));
} else {
ASSERT(std::holds_alternative<kungfu::OffsetType>(deopt.value));
ASSERT(deopt.kind == kungfu::LocationTy::Kind::CONSTANT);
v = JSTaggedType(static_cast<int64_t>(std::get<kungfu::OffsetType>(deopt.value)));
ASSERT(std::holds_alternative<IntType>(deopt.value));
ASSERT(deopt.kind == LocationTy::Kind::CONSTANT);
v = JSTaggedType(static_cast<int64_t>(std::get<IntType>(deopt.value)));
}
if (id != static_cast<kungfu::OffsetType>(SpecVregIndex::PC_OFFSET_INDEX)) {
if (id == static_cast<kungfu::OffsetType>(SpecVregIndex::ENV_INDEX)) {
if (id != static_cast<VRegId>(SpecVregIndex::PC_OFFSET_INDEX)) {
if (id == static_cast<VRegId>(SpecVregIndex::ENV_INDEX)) {
env_ = JSTaggedValue(v);
} else {
deoptVregs_[id] = JSTaggedValue(v);
@ -155,7 +155,7 @@ void Deoptimizier::CollectVregs(const std::vector<kungfu::ARKDeopt>& deoptBundle
// | ......... | v
// |--------------------------| ---------------
void Deoptimizier::CollectDeoptBundleVec(std::vector<kungfu::ARKDeopt>& deoptBundle)
void Deoptimizier::CollectDeoptBundleVec(std::vector<ARKDeopt>& deoptBundle)
{
JSTaggedType *lastLeave = const_cast<JSTaggedType *>(thread_->GetLastLeaveFrame());
FrameIterator it(lastLeave, thread_);
@ -166,7 +166,7 @@ void Deoptimizier::CollectDeoptBundleVec(std::vector<kungfu::ARKDeopt>& deoptBun
case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
auto frame = it.GetFrame<OptimizedJSFunctionFrame>();
frame->GetDeoptBundleInfo(it, deoptBundle);
kungfu::CalleeRegAndOffsetVec calleeRegInfo;
CalleeRegAndOffsetVec calleeRegInfo;
frame->GetFuncCalleeRegAndOffset(it, calleeRegInfo);
context_.calleeRegAndOffset = calleeRegInfo;
context_.callsiteSp = it.GetCallSiteSp();
@ -208,7 +208,7 @@ Method* Deoptimizier::GetMethod(JSTaggedValue &target)
void Deoptimizier::RelocateCalleeSave()
{
kungfu::CalleeReg callreg;
CalleeReg callreg;
for (auto &it: context_.calleeRegAndOffset) {
auto reg = it.first;
auto offset = it.second;
@ -249,7 +249,7 @@ bool Deoptimizier::CollectVirtualRegisters(Method* method, FrameWriter *frameWri
JSTaggedValue value = JSTaggedValue::Undefined();
// deopt value
if (HasDeoptValue(virtualIndex)) {
value = deoptVregs_.at(static_cast<kungfu::OffsetType>(virtualIndex));
value = deoptVregs_.at(static_cast<VRegId>(virtualIndex));
} else {
value = GetActualFrameArgs(i);
}
@ -259,17 +259,17 @@ bool Deoptimizier::CollectVirtualRegisters(Method* method, FrameWriter *frameWri
// [reserved args]
if (method->HaveThisWithCallField()) {
JSTaggedValue value = deoptVregs_.at(static_cast<kungfu::OffsetType>(SpecVregIndex::THIS_OBJECT_INDEX));
JSTaggedValue value = deoptVregs_.at(static_cast<VRegId>(SpecVregIndex::THIS_OBJECT_INDEX));
frameWriter->PushValue(value.GetRawData());
virtualIndex--;
}
if (method->HaveNewTargetWithCallField()) {
JSTaggedValue value = deoptVregs_.at(static_cast<kungfu::OffsetType>(SpecVregIndex::NEWTARGET_INDEX));
JSTaggedValue value = deoptVregs_.at(static_cast<VRegId>(SpecVregIndex::NEWTARGET_INDEX));
frameWriter->PushValue(value.GetRawData());
virtualIndex--;
}
if (method->HaveFuncWithCallField()) {
JSTaggedValue value = deoptVregs_.at(static_cast<kungfu::OffsetType>(SpecVregIndex::FUNC_INDEX));
JSTaggedValue value = deoptVregs_.at(static_cast<VRegId>(SpecVregIndex::FUNC_INDEX));
frameWriter->PushValue(value.GetRawData());
virtualIndex--;
}
@ -283,7 +283,7 @@ bool Deoptimizier::CollectVirtualRegisters(Method* method, FrameWriter *frameWri
return true;
}
void Deoptimizier::Dump(Method* method, kungfu::DeoptType type)
void Deoptimizier::Dump(Method* method, DeoptType type)
{
if (traceDeopt_) {
std::string checkType = DisplayItems(type);
@ -296,40 +296,40 @@ void Deoptimizier::Dump(Method* method, kungfu::DeoptType type)
}
}
std::string Deoptimizier::DisplayItems(kungfu::DeoptType type)
std::string Deoptimizier::DisplayItems(DeoptType type)
{
switch (type) {
case kungfu::DeoptType::NOTINT:
case DeoptType::NOTINT:
return "NOT INT";
case kungfu::DeoptType::DIVZERO:
case DeoptType::DIVZERO:
return "DIV ZERO";
case kungfu::DeoptType::NOTDOUBLE:
case DeoptType::NOTDOUBLE:
return "NOT DOUBLE";
case kungfu::DeoptType::NOTNUMBER:
case DeoptType::NOTNUMBER:
return "NOT NUMBER";
case kungfu::DeoptType::NOTBOOL:
case DeoptType::NOTBOOL:
return "NOT BOOL";
case kungfu::DeoptType::NOTHEAPOBJECT:
case DeoptType::NOTHEAPOBJECT:
return "NOT HEAP OBJECT";
case kungfu::DeoptType::NOTSARRAY:
case DeoptType::NOTSARRAY:
return "NOT SARRAY";
case kungfu::DeoptType::NOTF32ARRAY:
case DeoptType::NOTF32ARRAY:
return "NOT F32ARRAY";
case kungfu::DeoptType::INCONSISTENTHCLASS:
case DeoptType::INCONSISTENTHCLASS:
return "INCONSISTENT HCLASS";
case kungfu::DeoptType::NOTNEWOBJ:
return "NOT NEWOBJ TYPE";
case kungfu::DeoptType::NOTARRAYIDX:
case DeoptType::NOTARRAYIDX:
return "NOT ARRAY IDX";
case kungfu::DeoptType::NOTF32ARRAYIDX:
case DeoptType::NOTF32ARRAYIDX:
return "NOT F32 ARRAY IDX";
case kungfu::DeoptType::NOTINCOV:
case DeoptType::NOTINCOV:
return "NOT INC OVERFLOW";
case kungfu::DeoptType::NOTDECOV:
case DeoptType::NOTDECOV:
return "NOT DEC OVERFLOW";
case kungfu::DeoptType::NOTNEGOV:
case DeoptType::NOTNEGOV:
return "NOT NEG OVERFLOW";
case kungfu::DeoptType::NOTCALLTGT:
case DeoptType::NOTCALLTGT:
return "NOT CALL TARGET";
default: {
return "NOT CHECK";
@ -337,7 +337,7 @@ std::string Deoptimizier::DisplayItems(kungfu::DeoptType type)
}
}
JSTaggedType Deoptimizier::ConstructAsmInterpretFrame(kungfu::DeoptType type)
JSTaggedType Deoptimizier::ConstructAsmInterpretFrame(DeoptType type)
{
JSTaggedValue callTarget = GetDeoptValue(static_cast<int32_t>(SpecVregIndex::FUNC_INDEX));
auto method = GetMethod(callTarget);

View File

@ -90,17 +90,30 @@ struct AsmStackContext : public base::AlignedStruct<base::AlignedPointer::Size()
class FrameWriter;
class Deoptimizier {
public:
using ARKDeopt = kungfu::ARKDeopt;
using CalleeReg = kungfu::CalleeReg;
using CalleeRegAndOffsetVec = kungfu::CalleeRegAndOffsetVec;
using CommonArgIdx = kungfu::CommonArgIdx;
using DeoptType = kungfu::DeoptType;
using DwarfRegType = kungfu::LLVMStackMapType::DwarfRegType;
using DwarfRegAndOffsetType = kungfu::LLVMStackMapType::DwarfRegAndOffsetType;
using IntType = kungfu::LLVMStackMapType::IntType;
using LargeInt = kungfu::LLVMStackMapType::LargeInt;
using LocationTy = kungfu::LocationTy;
using OffsetType = kungfu::LLVMStackMapType::OffsetType;
using VRegId = kungfu::LLVMStackMapType::VRegId;
explicit Deoptimizier(JSThread *thread) : thread_(thread)
{
kungfu::CalleeReg callreg;
CalleeReg callreg;
numCalleeRegs_ = static_cast<size_t>(callreg.GetCallRegNum());
JSRuntimeOptions options = thread_->GetEcmaVM()->GetJSOptions();
traceDeopt_ = options.GetTraceDeopt();
}
void CollectVregs(const std::vector<kungfu::ARKDeopt>& deoptBundle);
void CollectDeoptBundleVec(std::vector<kungfu::ARKDeopt>& deoptBundle);
JSTaggedType ConstructAsmInterpretFrame(kungfu::DeoptType type);
static std::string DisplayItems(kungfu::DeoptType type);
void CollectVregs(const std::vector<ARKDeopt>& deoptBundle);
void CollectDeoptBundleVec(std::vector<ARKDeopt>& deoptBundle);
JSTaggedType ConstructAsmInterpretFrame(DeoptType type);
static std::string DisplayItems(DeoptType type);
JSThread *GetThread() const
{
@ -113,9 +126,9 @@ public:
}
private:
size_t GetFrameIndex(kungfu::CommonArgIdx index)
size_t GetFrameIndex(CommonArgIdx index)
{
return static_cast<size_t>(index) - static_cast<size_t>(kungfu::CommonArgIdx::FUNC);
return static_cast<size_t>(index) - static_cast<size_t>(CommonArgIdx::FUNC);
}
JSTaggedValue GetFrameArgv(size_t idx)
{
@ -123,7 +136,7 @@ private:
ASSERT(idx < frameArgc_);
return JSTaggedValue(frameArgvs_[idx]);
}
JSTaggedValue GetFrameArgv(kungfu::CommonArgIdx index)
JSTaggedValue GetFrameArgv(CommonArgIdx index)
{
return GetFrameArgv(GetFrameIndex(index));
}
@ -135,24 +148,24 @@ private:
bool CollectVirtualRegisters(Method* method, FrameWriter *frameWriter);
bool HasDeoptValue(int32_t index) const
{
return deoptVregs_.find(static_cast<kungfu::OffsetType>(index)) != deoptVregs_.end();
return deoptVregs_.find(static_cast<VRegId>(index)) != deoptVregs_.end();
}
JSTaggedValue GetDeoptValue(int32_t index) const
{
if (!HasDeoptValue(index)) {
return JSTaggedValue::Undefined();
}
return deoptVregs_.at(static_cast<kungfu::OffsetType>(index));
return deoptVregs_.at(static_cast<VRegId>(index));
}
Method* GetMethod(JSTaggedValue &target);
void RelocateCalleeSave();
void Dump(Method* method, kungfu::DeoptType type);
void Dump(Method* method, DeoptType type);
JSThread *thread_ {nullptr};
uintptr_t *calleeRegAddr_ {nullptr};
size_t numCalleeRegs_ {0};
AsmStackContext stackContext_;
std::unordered_map<kungfu::OffsetType, JSTaggedValue> deoptVregs_;
std::unordered_map<VRegId, JSTaggedValue> deoptVregs_;
struct Context context_ {0, 0, {}};
uint32_t pc_ {0};
JSTaggedValue env_ {JSTaggedValue::Undefined()};

View File

@ -393,7 +393,7 @@ uint32_t FrameIterator::GetBytecodeOffset() const
}
case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
auto frame = this->GetFrame<OptimizedJSFunctionFrame>();
kungfu::ConstInfo constInfo;
ConstInfo constInfo;
frame->CollectPcOffsetInfo(*this, constInfo);
if (!constInfo.empty()) {
return constInfo[0];
@ -460,7 +460,7 @@ ARK_INLINE void OptimizedFrame::GCIterate(const FrameIterator &it,
}
}
void FrameIterator::CollectPcOffsetInfo(kungfu::ConstInfo &info) const
void FrameIterator::CollectPcOffsetInfo(ConstInfo &info) const
{
arkStackMapParser_->GetConstInfo(optimizedReturnAddr_, info, stackMapAddr_);
}
@ -486,7 +486,7 @@ ARK_INLINE uintptr_t* OptimizedJSFunctionFrame::ComputePrevFrameSp(const FrameIt
}
void OptimizedJSFunctionFrame::CollectPcOffsetInfo(const FrameIterator &it, kungfu::ConstInfo &info) const
void OptimizedJSFunctionFrame::CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const
{
it.CollectPcOffsetInfo(info);
}

View File

@ -439,6 +439,7 @@ struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::Tagg
base::AlignedPointer,
base::AlignedPointer> {
public:
using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
enum class Index : size_t {
JSFuncIndex = 0,
TypeIndex,
@ -477,7 +478,7 @@ public:
void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
const RootBaseAndDerivedVisitor &derivedVisitor) const;
void CollectPcOffsetInfo(const FrameIterator &it, kungfu::ConstInfo &info) const;
void CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const;
inline JSTaggedValue GetFunction() const
{
@ -1427,6 +1428,7 @@ enum class GCVisitedFlag : bool {
class FrameIterator {
public:
using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr);
FrameType GetFrameType() const
{
@ -1483,7 +1485,7 @@ public:
return thread_;
}
bool IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const;
void CollectPcOffsetInfo(kungfu::ConstInfo &info) const;
void CollectPcOffsetInfo(ConstInfo &info) const;
void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const;
std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const;
int GetCallSiteDelta(uintptr_t retAddr) const;

View File

@ -20,67 +20,78 @@
namespace panda::ecmascript::kungfu {
struct ARKConst {
OffsetType offset;
LLVMStackMapType::IntType offset;
};
struct StackMapSecHead {
uint32_t totalSize;
struct ArkStackMapHeader {
uint32_t secSize;
uint32_t callsiteNum;
uint32_t callsitStart;
uint32_t callsitEnd;
};
struct CallsiteHead {
#pragma pack(1)
struct CallsiteHeader {
uint32_t calliteOffset {0}; // relative text start addr
uint32_t stackmapOffset {0}; // relative stackmap start addr
uint32_t arkStackMapNum {0};
uint32_t deoptOffset {0};
uint32_t deoptNum {0};
uint16_t stackmapNum {0};
uint16_t deoptNum {0};
};
#pragma pack ()
/* <deoptId, kind, value> */
/* <vregId and kind, value> */
struct ARKDeopt {
OffsetType Id; // deoptid
LLVMStackMapType::VRegId id; // deoptid
LocationTy::Kind kind;
std::variant<OffsetType, DwarfRegAndOffsetType, LargeInt> value;
std::variant<LLVMStackMapType::IntType, LLVMStackMapType::LargeInt, LLVMStackMapType::DwarfRegAndOffsetType> value;
};
struct ARKCallsite {
CallsiteHead head;
CallSiteInfo stackmaps;
CallsiteHeader head;
LLVMStackMapType::CallSiteInfo stackmaps;
std::vector<kungfu::ARKDeopt> callsite2Deopt;
bool operator < (const ARKCallsite & x) const
{
return head.calliteOffset < x.head.calliteOffset;
}
uint32_t CalHeadSize() const;
uint32_t CalStackMapSize() const;
uint32_t CalStackMapSize(Triple triple) const;
};
struct ARKCallsiteAOTFileInfo {
StackMapSecHead secHead;
ArkStackMapHeader secHead;
std::vector<ARKCallsite> callsites;
};
using ArkStackMap = CallSiteInfo;
using CalleeRegAndOffsetVec = std::vector<DwarfRegAndOffsetType>;
/*
totalSize callsiteNum callsitStart callsitEnd
-----head1--------
-----head2--------
|
|
-----head[N]------
-----stackmap1----
-----stackmap2----
|
|
-----stackmap2[N]-
-----deopt1-----
-<deoptid, LocationTy::Kind, LocationTy
- CONSTANT, <OffsetType OffsetOrSmallConstant>
- INDIRECT <loc.DwarfRegNum, loc.OffsetOrSmallConstant>
- CONSTANTNDEX <LargeInt>
*/
using ArkStackMap = LLVMStackMapType::CallSiteInfo;
using CalleeRegAndOffsetVec = std::vector<LLVMStackMapType::DwarfRegAndOffsetType>;
// * ArkStackMap layout as the following:
// +-----------------------------------------+ ---------
// | secSize | ^
// |-----------------------------------------| ArkStackMapHeader
// | callsiteNum | v
// +-----------------------------------------+ ---------
// | calliteOffset | ^
// |-----------------------------------------| |
// | stackmapOffset | |
// |-----------------------------------------| |
// | deoptOffset | CallsiteHeader[0]
// |-----------------------------------------| |
// | stackmapNum | |
// |-----------------------------------------| |
// | deoptNum | v
// |-----------------------------------------| ---------
// | . . . . . |
// +-----------------------------------------+ ---------
// | dwarfRegAndOff(sleb128) | StackMaps[0]
// |-----------------------------------------| ---------
// | . . . . . |
// +-----------------------------------------+ ---------
// | vregIdAndKind(sleb128) | ^
// |-----------------------------------------| Deopts[0]
// | value(sleb128) | v
// |-----------------------------------------| ---------
// | . . . . . |
// +-----------------------------------------+ ---------
//
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_ARK_STACKMAP_H

View File

@ -37,8 +37,25 @@ void BinaryBufferWriter::WriteBuffer(const uint8_t *src, uint32_t count, bool fl
}
}
void ArkStackMapBuilder::Dump(const StackMapDumper& dumpInfo) const
{
LOG_COMPILER(INFO) << "total callsite num: " << dumpInfo.callsiteNum
<< ", total ark stack map num: " << dumpInfo.stackmapNum
<< ", total deopt num: " << dumpInfo.deoptNum;
double callsiteHeadsSize = static_cast<double>(dumpInfo.callsiteHeadSize);
double stackMapsSize = static_cast<double>(dumpInfo.arkStackMapSize);
double deoptsSize = static_cast<double>(dumpInfo.deoptSize);
LOG_COMPILER(INFO) << "total callsite head size: "
<< std::fixed << std::setprecision(DECIMAL_LENS)
<< (callsiteHeadsSize / 1_KB) << "KB, total stackmap size: "
<< std::fixed << std::setprecision(DECIMAL_LENS)
<< (stackMapsSize / 1_KB) << "KB, total deopt size: "
<< std::fixed << std::setprecision(DECIMAL_LENS)
<< (deoptsSize / 1_KB) << "KB";
}
std::pair<std::shared_ptr<uint8_t>, uint32_t> ArkStackMapBuilder::Run(std::unique_ptr<uint8_t []> stackMapAddr,
uintptr_t hostCodeSectionAddr)
uintptr_t hostCodeSectionAddr, Triple triple)
{
LLVMStackMapParser parser;
auto result = parser.CalculateStackMap(std::move(stackMapAddr), hostCodeSectionAddr);
@ -49,41 +66,48 @@ std::pair<std::shared_ptr<uint8_t>, uint32_t> ArkStackMapBuilder::Run(std::uniqu
auto pc2stackMapVec = parser.GetPc2StackMapVec();
auto pc2DeoptVec = parser.GetPc2Deopt();
ARKCallsiteAOTFileInfo AOTFileInfo;
GenArkCallsiteAOTFileInfo(pc2stackMapVec, pc2DeoptVec, AOTFileInfo);
uint32_t totalSize = AOTFileInfo.secHead.totalSize;
uint8_t *p = new(std::nothrow) uint8_t[totalSize];
GenArkCallsiteAOTFileInfo(pc2stackMapVec, pc2DeoptVec, AOTFileInfo, triple);
uint32_t secSize = AOTFileInfo.secHead.secSize;
uint8_t *p = new(std::nothrow) uint8_t[secSize];
if (p == nullptr) {
LOG_FULL(FATAL) << "new totalSize:0x" << std::hex << totalSize << " failed";
LOG_FULL(FATAL) << "new secSize:0x" << std::hex << secSize << " failed";
}
std::shared_ptr<uint8_t> ptr(p, [](uint8_t *p) { delete []p;});
SaveArkCallsiteAOTFileInfo(ptr.get(), totalSize, AOTFileInfo);
return std::make_pair(ptr, totalSize);
SaveArkCallsiteAOTFileInfo(ptr.get(), secSize, AOTFileInfo, triple);
if (traceStackMap_) {
Dump(dumper_);
}
return std::make_pair(ptr, secSize);
}
void ArkStackMapBuilder::SaveArkStackMap(const ARKCallsiteAOTFileInfo& info, BinaryBufferWriter& writer)
void ArkStackMapBuilder::SaveArkStackMap(const ARKCallsiteAOTFileInfo& info, BinaryBufferWriter& writer, Triple triple)
{
size_t n = info.callsites.size();
for (size_t i = 0; i < n; i++) {
auto &callSite = info.callsites.at(i);
CallSiteInfo stackmaps = callSite.stackmaps;
LLVMStackMapType::CallSiteInfo stackmaps = callSite.stackmaps;
size_t m = stackmaps.size();
for (size_t j = 0; j < m; j++) {
auto &stackmap = stackmaps.at(j);
DwarfRegType reg = stackmap.first;
OffsetType offset = stackmap.second;
LLVMStackMapType::DwarfRegType reg = stackmap.first;
LLVMStackMapType::OffsetType offset = stackmap.second;
if (j == 0) {
ASSERT(callSite.head.stackmapOffset == writer.GetOffset());
}
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(&(reg)), sizeof(DwarfRegType));
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(&(offset)), sizeof(OffsetType));
std::vector<uint8_t> regOffset;
size_t regOffsetSize = 0;
LLVMStackMapType::EncodeRegAndOffset(regOffset, regOffsetSize, reg, offset, triple);
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(regOffset.data()), regOffset.size());
dumper_.arkStackMapSize += regOffsetSize;
if (j == m - 1) {
ASSERT((callSite.head.stackmapOffset + callSite.CalStackMapSize()) == writer.GetOffset());
ASSERT((callSite.head.stackmapOffset + callSite.CalStackMapSize(triple)) == writer.GetOffset());
}
}
}
writer.AlignOffset();
}
void ArkStackMapBuilder::SaveArkDeopt(const ARKCallsiteAOTFileInfo& info, BinaryBufferWriter& writer)
void ArkStackMapBuilder::SaveArkDeopt(const ARKCallsiteAOTFileInfo& info, BinaryBufferWriter& writer, Triple triple)
{
for (auto &it: info.callsites) {
auto& callsite2Deopt = it.callsite2Deopt;
@ -93,19 +117,33 @@ void ArkStackMapBuilder::SaveArkDeopt(const ARKCallsiteAOTFileInfo& info, Binary
if (j == 0) {
ASSERT(it.head.deoptOffset == writer.GetOffset());
}
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(&(deopt.Id)), sizeof(deopt.Id));
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(&(deopt.kind)), sizeof(deopt.kind));
std::vector<uint8_t> vregsInfo;
size_t vregsInfoSize = 0;
LLVMStackMapType::EncodeVRegsInfo(vregsInfo, vregsInfoSize, deopt.id, deopt.kind);
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(vregsInfo.data()), vregsInfoSize);
dumper_.deoptSize += vregsInfoSize;
auto& value = deopt.value;
if (std::holds_alternative<OffsetType>(value)) {
OffsetType v = std::get<OffsetType>(value);
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(&(v)), sizeof(v));
} else if (std::holds_alternative<LargeInt>(value)) {
LargeInt v = std::get<LargeInt>(value);
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(&(v)), sizeof(v));
} else if (std::holds_alternative<DwarfRegAndOffsetType>(value)) {
DwarfRegAndOffsetType v = std::get<DwarfRegAndOffsetType>(value);
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(&(v.first)), sizeof(v.first));
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(&(v.second)), sizeof(v.second));
if (std::holds_alternative<LLVMStackMapType::IntType>(value)) {
LLVMStackMapType::IntType v = std::get<LLVMStackMapType::IntType>(value);
std::vector<uint8_t> num;
size_t numSize = 0;
LLVMStackMapType::EncodeData(num, numSize, v);
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(num.data()), numSize);
dumper_.deoptSize += numSize;
} else if (std::holds_alternative<LLVMStackMapType::LargeInt>(value)) {
LLVMStackMapType::LargeInt v = std::get<LLVMStackMapType::LargeInt>(value);
std::vector<uint8_t> num;
size_t numSize = 0;
LLVMStackMapType::EncodeData(num, numSize, v);
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(num.data()), numSize);
dumper_.deoptSize += numSize;
} else if (std::holds_alternative<LLVMStackMapType::DwarfRegAndOffsetType>(value)) {
LLVMStackMapType::DwarfRegAndOffsetType v = std::get<LLVMStackMapType::DwarfRegAndOffsetType>(value);
std::vector<uint8_t> regOffset;
size_t regOffsetSize = 0;
LLVMStackMapType::EncodeRegAndOffset(regOffset, regOffsetSize, v.first, v.second, triple);
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(regOffset.data()), regOffset.size());
dumper_.arkStackMapSize += regOffsetSize;
} else {
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
@ -114,110 +152,19 @@ void ArkStackMapBuilder::SaveArkDeopt(const ARKCallsiteAOTFileInfo& info, Binary
}
}
void ArkStackMapParser::ParseArkStackMap(const CallsiteHead& callsiteHead, BinaryBufferParser& binBufparser,
uint8_t *ptr, ArkStackMap &arkStackMaps) const
{
DwarfRegType reg;
OffsetType offsetType;
uint32_t offset = callsiteHead.stackmapOffset;
uint32_t arkStackMapNum = callsiteHead.arkStackMapNum;
ASSERT(arkStackMapNum % 2 == 0); // 2:base and derive
for (uint32_t j = 0; j < arkStackMapNum; j++) {
binBufparser.ParseBuffer(reinterpret_cast<uint8_t *>(&reg), sizeof(DwarfRegType), ptr + offset);
offset += sizeof(DwarfRegType);
binBufparser.ParseBuffer(reinterpret_cast<uint8_t *>(&offsetType), sizeof(OffsetType), ptr + offset);
offset += sizeof(OffsetType);
LOG_COMPILER(VERBOSE) << " reg: " << std::dec << reg << " offset:" << offsetType;
arkStackMaps.emplace_back(std::make_pair(reg, offsetType));
}
}
void ArkStackMapParser::ParseArkDeopt(const CallsiteHead& callsiteHead,
BinaryBufferParser& binBufparser, uint8_t *ptr, std::vector<kungfu::ARKDeopt> &deopts) const
{
kungfu::ARKDeopt deopt;
uint32_t deoptOffset = callsiteHead.deoptOffset;
uint32_t deoptNum = callsiteHead.deoptNum;
OffsetType id;
LocationTy::Kind kind;
DwarfRegType reg;
OffsetType offsetType;
ASSERT(deoptNum % 2 == 0); // 2:<id, value>
for (uint32_t j = 0; j < deoptNum; j += 2) { // 2:<id, value>
binBufparser.ParseBuffer(reinterpret_cast<uint8_t *>(&id), sizeof(id), ptr + deoptOffset);
deoptOffset += sizeof(id);
deopt.Id = id;
binBufparser.ParseBuffer(reinterpret_cast<uint8_t *>(&kind), sizeof(kind), ptr + deoptOffset);
deoptOffset += sizeof(kind);
deopt.kind = kind;
switch (kind) {
case LocationTy::Kind::CONSTANT: {
OffsetType v;
binBufparser.ParseBuffer(reinterpret_cast<uint8_t *>(&v), sizeof(v), ptr + deoptOffset);
deoptOffset += sizeof(v);
LOG_COMPILER(VERBOSE) << "const offset:" << deoptOffset;
deopt.value = v;
break;
}
case LocationTy::Kind::CONSTANTNDEX: {
LargeInt v;
binBufparser.ParseBuffer(reinterpret_cast<uint8_t *>(&v), sizeof(v), ptr + deoptOffset);
deoptOffset += sizeof(v);
LOG_COMPILER(VERBOSE) << "large Int:" << v;
deopt.value = v;
break;
}
case LocationTy::Kind::INDIRECT: {
binBufparser.ParseBuffer(reinterpret_cast<uint8_t *>(&reg), sizeof(reg), ptr + deoptOffset);
deoptOffset += sizeof(reg);
binBufparser.ParseBuffer(reinterpret_cast<uint8_t *>(&offsetType),
sizeof(offsetType), ptr + deoptOffset);
deoptOffset += sizeof(offsetType);
LOG_COMPILER(VERBOSE) << " reg:" << std::dec << reg << " offset:" << static_cast<int>(offsetType);
deopt.value = std::make_pair(reg, offsetType);
break;
}
default: {
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
}
deopts.emplace_back(deopt);
}
}
void ArkStackMapParser::ParseArkStackMapAndDeopt(uint8_t *ptr, uint32_t length) const
{
CallsiteHead callsiteHead;
StackMapSecHead secHead;
BinaryBufferParser binBufparser(ptr, length);
binBufparser.ParseBuffer(&secHead, sizeof(StackMapSecHead));
for (uint32_t i = 0; i < secHead.callsiteNum; i++) {
binBufparser.ParseBuffer(&callsiteHead, sizeof(CallsiteHead));
uint32_t offset = callsiteHead.stackmapOffset;
uint32_t arkStackMapNum = callsiteHead.arkStackMapNum;
uint32_t deoptOffset = callsiteHead.deoptOffset;
uint32_t deoptNum = callsiteHead.deoptNum;
std::vector<kungfu::ARKDeopt> deopts;
ArkStackMap arkStackMaps;
LOG_COMPILER(VERBOSE) << " calliteOffset:0x" << std::hex << callsiteHead.calliteOffset
<< " stackmap offset:0x" << std::hex << offset << " num:" << arkStackMapNum
<< " deopt Offset:0x" << deoptOffset << " num:" << deoptNum;
ParseArkStackMap(callsiteHead, binBufparser, ptr, arkStackMaps);
ParseArkDeopt(callsiteHead, binBufparser, ptr, deopts);
}
}
void ArkStackMapBuilder::SaveArkCallsiteAOTFileInfo(uint8_t *ptr, uint32_t length, const ARKCallsiteAOTFileInfo& info)
void ArkStackMapBuilder::SaveArkCallsiteAOTFileInfo(uint8_t *ptr, uint32_t length,
const ARKCallsiteAOTFileInfo& info, Triple triple)
{
BinaryBufferWriter writer(ptr, length);
ASSERT(length >= info.secHead.totalSize);
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(&(info.secHead)), sizeof(StackMapSecHead));
ASSERT(length >= info.secHead.secSize);
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(&(info.secHead)), sizeof(ArkStackMapHeader));
dumper_.callsiteHeadSize += sizeof(ArkStackMapHeader);
for (auto &it: info.callsites) {
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(&(it.head)), sizeof(CallsiteHead));
writer.WriteBuffer(reinterpret_cast<const uint8_t *>(&(it.head)), sizeof(CallsiteHeader));
dumper_.callsiteHeadSize += sizeof(CallsiteHeader);
}
SaveArkStackMap(info, writer);
SaveArkDeopt(info, writer);
SaveArkStackMap(info, writer, triple);
SaveArkDeopt(info, writer, triple);
#ifndef NDEBUG
ArkStackMapParser parser;
parser.ParseArkStackMapAndDeopt(ptr, length);
@ -241,8 +188,8 @@ void ArkStackMapBuilder::SortCallSite(
});
}
void ArkStackMapBuilder::CalcCallsitePc(std::vector<std::pair<uintptr_t, DeoptInfoType>> &pc2Deopt,
std::vector<std::pair<uintptr_t, CallSiteInfo>> &pc2StackMap, std::vector<intptr_t> &callsitePcs)
void ArkStackMapBuilder::CalcCallsitePc(std::vector<std::pair<uintptr_t, LLVMStackMapType::DeoptInfoType>> &pc2Deopt,
std::vector<std::pair<uintptr_t, LLVMStackMapType::CallSiteInfo>> &pc2StackMap, std::vector<intptr_t> &callsitePcs)
{
std::set<uintptr_t> pcSet;
for (auto &it: pc2Deopt) {
@ -264,31 +211,46 @@ int ArkStackMapBuilder::FindLoc(std::vector<intptr_t> &CallsitePcs, intptr_t pc)
return -1;
}
void ArkStackMapBuilder::GenARKDeopt(const DeoptInfoType& deopt, std::pair<uint32_t,
std::vector<kungfu::ARKDeopt>> &sizeAndArkDeopt)
void ArkStackMapBuilder::GenARKDeopt(const LLVMStackMapType::DeoptInfoType& deopt, std::pair<uint32_t,
std::vector<ARKDeopt>> &sizeAndArkDeopt, Triple triple)
{
ASSERT(deopt.size() % 2 == 0); // 2:<id, value>
uint32_t total = 0;
ARKDeopt v;
for (size_t i = 0; i < deopt.size(); i += 2) { // 2:<id, value>
ASSERT(std::holds_alternative<OffsetType>(deopt[i]));
const auto &id = std::get<OffsetType>(deopt[i]);
total += sizeof(OffsetType);
v.Id = id;
total += sizeof(LocationTy::Kind); // derive
ASSERT(std::holds_alternative<LLVMStackMapType::IntType>(deopt[i]));
LLVMStackMapType::VRegId id = static_cast<LLVMStackMapType::VRegId>(
std::get<LLVMStackMapType::IntType>(deopt[i]));
v.id = id;
auto value = deopt[i + 1];
if (std::holds_alternative<OffsetType>(value)) {
total += sizeof(OffsetType);
if (std::holds_alternative<LLVMStackMapType::IntType>(value)) {
v.kind = LocationTy::Kind::CONSTANT;
v.value = std::get<OffsetType>(value);
} else if (std::holds_alternative<LargeInt>(value)) {
total += sizeof(LargeInt);
v.value = std::get<LLVMStackMapType::IntType>(value);
std::vector<uint8_t> vregsInfo;
size_t vregsInfoSize = 0;
LLVMStackMapType::EncodeVRegsInfo(vregsInfo, vregsInfoSize, v.id, v.kind);
size_t valueSize = panda::leb128::SignedEncodingSize(std::get<LLVMStackMapType::IntType>(value));
total += (vregsInfoSize + valueSize);
} else if (std::holds_alternative<LLVMStackMapType::LargeInt>(value)) {
v.kind = LocationTy::Kind::CONSTANTNDEX;
v.value = std::get<LargeInt>(value);
} else if (std::holds_alternative<DwarfRegAndOffsetType>(value)) {
total += (sizeof(DwarfRegType) + sizeof(OffsetType));
v.value = std::get<LLVMStackMapType::LargeInt>(value);
std::vector<uint8_t> vregsInfo;
size_t vregsInfoSize = 0;
LLVMStackMapType::EncodeVRegsInfo(vregsInfo, vregsInfoSize, v.id, v.kind);
size_t valueSize = panda::leb128::SignedEncodingSize(std::get<LLVMStackMapType::LargeInt>(value));
total += (vregsInfoSize + valueSize);
} else if (std::holds_alternative<LLVMStackMapType::DwarfRegAndOffsetType>(value)) {
v.kind = LocationTy::Kind::INDIRECT;
v.value = std::get<DwarfRegAndOffsetType>(value);
v.value = std::get<LLVMStackMapType::DwarfRegAndOffsetType>(value);
std::vector<uint8_t> vregsInfo;
size_t vregsInfoSize = 0;
LLVMStackMapType::EncodeVRegsInfo(vregsInfo, vregsInfoSize, v.id, v.kind);
LLVMStackMapType::DwarfRegType reg = std::get<LLVMStackMapType::DwarfRegAndOffsetType>(value).first;
LLVMStackMapType::OffsetType offset = std::get<LLVMStackMapType::DwarfRegAndOffsetType>(value).second;
std::vector<uint8_t> regOffset;
size_t regOffsetSize = 0;
LLVMStackMapType::EncodeRegAndOffset(regOffset, regOffsetSize, reg, offset, triple);
total += (vregsInfoSize + regOffsetSize);
} else {
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
@ -297,54 +259,58 @@ void ArkStackMapBuilder::GenARKDeopt(const DeoptInfoType& deopt, std::pair<uint3
}
std::sort(sizeAndArkDeopt.second.begin(), sizeAndArkDeopt.second.end(),
[](const ARKDeopt &a, const ARKDeopt &b) {
return a.Id < b.Id;
return a.id < b.id;
});
sizeAndArkDeopt.first = total;
}
void ArkStackMapBuilder::GenArkCallsiteAOTFileInfo(std::vector<Pc2CallSiteInfo> &pc2stackMapVec,
std::vector<Pc2Deopt>& pc2DeoptVec, ARKCallsiteAOTFileInfo &result)
void ArkStackMapBuilder::GenArkCallsiteAOTFileInfo(std::vector<LLVMStackMapType::Pc2CallSiteInfo> &pc2stackMapVec,
std::vector<LLVMStackMapType::Pc2Deopt>& pc2DeoptVec, ARKCallsiteAOTFileInfo &result, Triple triple)
{
ARKCallsite callsite;
uint32_t totalSize = 0;
std::vector<std::pair<uintptr_t, CallSiteInfo>> pc2stackMaps;
std::vector<std::pair<uintptr_t, DeoptInfoType>> pc2Deopts;
uint32_t secSize = 0;
std::vector<std::pair<uintptr_t, LLVMStackMapType::CallSiteInfo>> pc2StackMaps;
std::vector<std::pair<uintptr_t, LLVMStackMapType::DeoptInfoType>> pc2Deopts;
std::vector<intptr_t> CallsitePcs;
SortCallSite(pc2stackMapVec, pc2stackMaps);
SortCallSite(pc2stackMapVec, pc2StackMaps);
SortCallSite(pc2DeoptVec, pc2Deopts);
CalcCallsitePc(pc2Deopts, pc2stackMaps, CallsitePcs);
CalcCallsitePc(pc2Deopts, pc2StackMaps, CallsitePcs);
uint32_t callsiteNum = CallsitePcs.size();
dumper_.callsiteNum = callsiteNum;
result.callsites.resize(callsiteNum);
uint32_t stackmapOffset = sizeof(StackMapSecHead) + sizeof(CallsiteHead) * callsiteNum;
for (auto &x: pc2stackMaps) {
CallSiteInfo i = x.second;
uint32_t stackmapOffset = sizeof(ArkStackMapHeader) + sizeof(CallsiteHeader) * callsiteNum;
for (auto &x: pc2StackMaps) {
LLVMStackMapType::CallSiteInfo i = x.second;
callsite.head.calliteOffset = x.first;
callsite.head.arkStackMapNum = i.size();
ASSERT(std::numeric_limits<uint16_t>::min() <= i.size() && i.size() <= std::numeric_limits<uint16_t>::max());
callsite.head.stackmapNum = i.size();
callsite.head.stackmapOffset = stackmapOffset;
callsite.head.deoptOffset = 0;
callsite.head.deoptNum = 0;
callsite.stackmaps = i;
stackmapOffset += callsite.CalStackMapSize();
stackmapOffset += callsite.CalStackMapSize(triple);
int loc = FindLoc(CallsitePcs, x.first);
ASSERT(loc >= 0 && loc < static_cast<int>(callsiteNum));
result.callsites[static_cast<uint32_t>(loc)] = callsite;
dumper_.stackmapNum += i.size();
}
totalSize = stackmapOffset;
stackmapOffset = AlignUp(stackmapOffset, LLVMStackMapType::STACKMAP_ALIGN_BYTES);
secSize = stackmapOffset;
for (auto &x: pc2Deopts) {
int loc = FindLoc(CallsitePcs, x.first);
ASSERT(loc >= 0 && loc < static_cast<int>(callsiteNum));
DeoptInfoType deopt = x.second;
LLVMStackMapType::DeoptInfoType deopt = x.second;
result.callsites[static_cast<uint32_t>(loc)].head.calliteOffset = x.first;
ASSERT(std::numeric_limits<uint16_t>::min() <= deopt.size() && deopt.size() <= std::numeric_limits<uint16_t>::max());
result.callsites[static_cast<uint32_t>(loc)].head.deoptNum = deopt.size();
result.callsites[static_cast<uint32_t>(loc)].head.deoptOffset = totalSize;
std::pair<uint32_t, std::vector<kungfu::ARKDeopt>> sizeAndArkDeopt;
GenARKDeopt(deopt, sizeAndArkDeopt);
totalSize += sizeAndArkDeopt.first;
result.callsites[static_cast<uint32_t>(loc)].head.deoptOffset = secSize;
std::pair<uint32_t, std::vector<ARKDeopt>> sizeAndArkDeopt;
GenARKDeopt(deopt, sizeAndArkDeopt, triple);
secSize += sizeAndArkDeopt.first;
result.callsites[static_cast<uint32_t>(loc)].callsite2Deopt = sizeAndArkDeopt.second;
dumper_.deoptNum += deopt.size();
}
result.secHead.callsiteNum = callsiteNum;
result.secHead.callsitStart = sizeof(StackMapSecHead);
result.secHead.callsitEnd = result.secHead.callsitStart + (result.secHead.callsiteNum - 1) * sizeof(CallsiteHead);
result.secHead.totalSize = totalSize;
result.secHead.secSize = secSize;
}
} // namespace panda::ecmascript::kungfu

View File

@ -21,10 +21,13 @@
#include <tuple>
#include <unordered_map>
#include <vector>
#include <iomanip>
#include "ecmascript/frames.h"
#include "ecmascript/stackmap/ark_stackmap.h"
#include "ecmascript/stackmap/llvm_stackmap_type.h"
#include "libpandabase/utils/leb128.h"
namespace panda::ecmascript {
class BinaryBufferParser;
}
@ -39,33 +42,57 @@ public:
{
return offset_;
}
void AlignOffset()
{
offset_ = AlignUp(offset_, LLVMStackMapType::STACKMAP_ALIGN_BYTES);
}
private:
uint8_t *buffer_ {nullptr};
uint32_t length_ {0};
uint32_t offset_ {0};
};
struct StackMapDumper {
uint32_t callsiteHeadSize {0};
uint32_t arkStackMapSize {0};
uint32_t deoptSize {0};
uint32_t callsiteNum {0};
uint32_t stackmapNum {0};
uint32_t deoptNum {0};
};
class ArkStackMapBuilder {
public:
ArkStackMapBuilder() = default;
~ArkStackMapBuilder() = default;
std::pair<std::shared_ptr<uint8_t>, uint32_t> PUBLIC_API Run(std::unique_ptr<uint8_t []> stackMapAddr,
uintptr_t hostCodeSectionAddr);
uintptr_t hostCodeSectionAddr, Triple triple);
void SetTraceStackMap(bool flag)
{
traceStackMap_ = flag;
}
private:
static constexpr int DECIMAL_LENS = 2;
StackMapDumper dumper_;
template <class Vec>
void SortCallSite(std::vector<std::unordered_map<uintptr_t, Vec>> &infos,
std::vector<std::pair<uintptr_t, Vec>>& result);
void CalcCallsitePc(std::vector<std::pair<uintptr_t, DeoptInfoType>> &pc2Deopt,
std::vector<std::pair<uintptr_t, CallSiteInfo>> &pc2StackMap, std::vector<intptr_t> &callsitePcs);
void GenArkCallsiteAOTFileInfo(std::vector<Pc2CallSiteInfo> &pc2stackMaps,
std::vector<Pc2Deopt>& pc2DeoptVec, ARKCallsiteAOTFileInfo &result);
void SaveArkDeopt(const ARKCallsiteAOTFileInfo& info, BinaryBufferWriter& writer);
void SaveArkStackMap(const ARKCallsiteAOTFileInfo& info, BinaryBufferWriter& writer);
void SaveArkCallsiteAOTFileInfo(uint8_t *ptr, uint32_t length, const ARKCallsiteAOTFileInfo& info);
void CalcCallsitePc(std::vector<std::pair<uintptr_t, LLVMStackMapType::DeoptInfoType>> &pc2Deopt,
std::vector<std::pair<uintptr_t, LLVMStackMapType::CallSiteInfo>> &pc2StackMap,
std::vector<intptr_t> &callsitePcs);
void GenArkCallsiteAOTFileInfo(std::vector<LLVMStackMapType::Pc2CallSiteInfo> &pc2StackMaps,
std::vector<LLVMStackMapType::Pc2Deopt>& pc2DeoptVec, ARKCallsiteAOTFileInfo &result, Triple triple);
void SaveArkDeopt(const ARKCallsiteAOTFileInfo& info, BinaryBufferWriter& writer, Triple triple);
void SaveArkStackMap(const ARKCallsiteAOTFileInfo& info, BinaryBufferWriter& writer, Triple triple);
void SaveArkCallsiteAOTFileInfo(uint8_t *ptr, uint32_t length, const ARKCallsiteAOTFileInfo& info, Triple triple);
int FindLoc(std::vector<intptr_t> &CallsitePcs, intptr_t pc);
void GenARKDeopt(const DeoptInfoType& deopt, std::pair<uint32_t, std::vector<kungfu::ARKDeopt>> &sizeAndArkDeopt);
void GenARKDeopt(const LLVMStackMapType::DeoptInfoType& deopt,
std::pair<uint32_t, std::vector<ARKDeopt>> &sizeAndArkDeopt, Triple triple);
void Dump(const StackMapDumper& dumpInfo) const;
bool traceStackMap_{false};
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_ARK_STACKMAP_BUILD_H

View File

@ -20,8 +20,8 @@
#include "ecmascript/stackmap/ark_stackmap_builder.h"
namespace panda::ecmascript::kungfu {
// implement simple binary-search is improve performance. if use std api, it'll trigger copy CallsiteHead.
int ArkStackMapParser::BinaraySearch(CallsiteHead *callsiteHead, uint32_t callsiteNum, uintptr_t callSiteAddr) const
// implement simple binary-search is improve performance. if use std api, it'll trigger copy CallsiteHeader.
int ArkStackMapParser::BinaraySearch(CallsiteHeader *callsiteHead, uint32_t callsiteNum, uintptr_t callSiteAddr) const
{
int slow = 0;
int high = static_cast<int>(callsiteNum) - 1;
@ -41,56 +41,54 @@ int ArkStackMapParser::BinaraySearch(CallsiteHead *callsiteHead, uint32_t callsi
return -1;
}
void ArkStackMapParser::GetArkDeopt(uint8_t *stackmapAddr, uint32_t length,
const CallsiteHead& callsiteHead, std::vector<kungfu::ARKDeopt> &deopts) const
void ArkStackMapParser::GetArkDeopt(uint8_t *stackmapAddr,
const CallsiteHeader& callsiteHead, std::vector<ARKDeopt>& deopts) const
{
BinaryBufferParser binBufparser(stackmapAddr, length);
ParseArkDeopt(callsiteHead, binBufparser, stackmapAddr, deopts);
ParseArkDeopt(callsiteHead, stackmapAddr, deopts);
}
void ArkStackMapParser::GetArkDeopt(uintptr_t callSiteAddr, uint8_t *stackmapAddr,
std::vector<kungfu::ARKDeopt> &deopts) const
std::vector<ARKDeopt>& deopts) const
{
StackMapSecHead *head = reinterpret_cast<StackMapSecHead *>(stackmapAddr);
ArkStackMapHeader *head = reinterpret_cast<ArkStackMapHeader *>(stackmapAddr);
ASSERT(head != nullptr);
uint32_t callsiteNum = head->callsiteNum;
uint32_t length = head->totalSize;
ASSERT((head->callsitEnd - head->callsitStart) == ((callsiteNum - 1) * sizeof(CallsiteHead)));
CallsiteHead *callsiteHead = reinterpret_cast<CallsiteHead *>(stackmapAddr + sizeof(StackMapSecHead));
CallsiteHeader *callsiteHead = reinterpret_cast<CallsiteHeader *>(stackmapAddr + sizeof(ArkStackMapHeader));
int mid = BinaraySearch(callsiteHead, callsiteNum, callSiteAddr);
if (mid == -1) {
return;
}
CallsiteHead *found = callsiteHead + mid;
GetArkDeopt(stackmapAddr, length, *found, deopts);
CallsiteHeader *found = callsiteHead + mid;
GetArkDeopt(stackmapAddr, *found, deopts);
}
void ArkStackMapParser::GetConstInfo(uintptr_t callSiteAddr, ConstInfo &info, uint8_t *stackmapAddr) const
void ArkStackMapParser::GetConstInfo(uintptr_t callSiteAddr, LLVMStackMapType::ConstInfo& info,
uint8_t *stackmapAddr) const
{
std::vector<kungfu::ARKDeopt> deopts;
std::vector<ARKDeopt> deopts;
GetArkDeopt(callSiteAddr, stackmapAddr, deopts);
if (deopts.empty()) {
return;
}
ARKDeopt target;
OffsetType id = static_cast<OffsetType>(SpecVregIndex::PC_OFFSET_INDEX);
target.Id = id;
LLVMStackMapType::VRegId id = static_cast<LLVMStackMapType::VRegId>(SpecVregIndex::PC_OFFSET_INDEX);
target.id = id;
auto it = std::lower_bound(deopts.begin(), deopts.end(), target,
[](const ARKDeopt& a, const ARKDeopt& b) {
return a.Id < b.Id;
return a.id < b.id;
});
if (it == deopts.end() || (it->Id > id)) {
if (it == deopts.end() || (it->id > id)) {
return;
}
ASSERT(it->kind == LocationTy::Kind::CONSTANT);
ASSERT(std::holds_alternative<OffsetType>(it->value));
auto v = std::get<OffsetType>(it->value);
ASSERT(std::holds_alternative<LLVMStackMapType::IntType>(it->value));
auto v = std::get<LLVMStackMapType::IntType>(it->value);
info.emplace_back(v);
}
uintptr_t ArkStackMapParser::GetStackSlotAddress(const DwarfRegAndOffsetType info,
uintptr_t ArkStackMapParser::GetStackSlotAddress(const LLVMStackMapType::DwarfRegAndOffsetType info,
uintptr_t callSiteSp, uintptr_t callsiteFp) const
{
uintptr_t address = 0;
@ -105,36 +103,33 @@ uintptr_t ArkStackMapParser::GetStackSlotAddress(const DwarfRegAndOffsetType inf
return address;
}
bool ArkStackMapParser::IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor,
bool ArkStackMapParser::IteratorStackMap(const RootVisitor& visitor, const RootBaseAndDerivedVisitor& derivedVisitor,
uintptr_t callSiteAddr, uintptr_t callsiteFp, uintptr_t callSiteSp, uint8_t *stackmapAddr) const
{
StackMapSecHead *head = reinterpret_cast<StackMapSecHead *>(stackmapAddr);
ArkStackMapHeader *head = reinterpret_cast<ArkStackMapHeader *>(stackmapAddr);
ASSERT(head != nullptr);
uint32_t callsiteNum = head->callsiteNum;
uint32_t length = head->totalSize;
ArkStackMap arkStackMap;
// BuiltinsStub current only sample stub, don't have stackmap&deopt.
if (callsiteNum == 0) {
return false;
}
ASSERT((head->callsitEnd - head->callsitStart) == ((callsiteNum - 1) * sizeof(CallsiteHead)));
CallsiteHead *callsiteHead = reinterpret_cast<CallsiteHead *>(stackmapAddr + sizeof(StackMapSecHead));
CallsiteHeader *callsiteHead = reinterpret_cast<CallsiteHeader *>(stackmapAddr + sizeof(ArkStackMapHeader));
int mid = BinaraySearch(callsiteHead, callsiteNum, callSiteAddr);
if (mid == -1) {
return false;
}
CallsiteHead *found = callsiteHead + mid;
BinaryBufferParser binBufparser(stackmapAddr, length);
ParseArkStackMap(*found, binBufparser, stackmapAddr, arkStackMap);
CallsiteHeader *found = callsiteHead + mid;
ParseArkStackMap(*found, stackmapAddr, arkStackMap);
if (arkStackMap.size() == 0) {
return false;
}
ASSERT(callsiteFp != callSiteSp);
std::map<uintptr_t, uintptr_t> baseSet;
for (size_t i = 0; i < arkStackMap.size(); i += 2) { // 2:base and derive
const DwarfRegAndOffsetType baseInfo = arkStackMap.at(i);
const DwarfRegAndOffsetType derivedInfo = arkStackMap.at(i + 1);
const LLVMStackMapType::DwarfRegAndOffsetType baseInfo = arkStackMap.at(i);
const LLVMStackMapType::DwarfRegAndOffsetType derivedInfo = arkStackMap.at(i + 1);
uintptr_t base = GetStackSlotAddress(baseInfo, callSiteSp, callsiteFp);
uintptr_t derived = GetStackSlotAddress(derivedInfo, callSiteSp, callsiteFp);
if (*reinterpret_cast<uintptr_t *>(base) == 0) {
@ -155,4 +150,82 @@ bool ArkStackMapParser::IteratorStackMap(const RootVisitor &visitor, const RootB
baseSet.clear();
return true;
}
void ArkStackMapParser::ParseArkStackMap(const CallsiteHeader& callsiteHead, uint8_t *ptr,
ArkStackMap& arkStackMaps) const
{
LLVMStackMapType::DwarfRegType reg;
LLVMStackMapType::OffsetType offsetType;
uint32_t offset = callsiteHead.stackmapOffset;
uint16_t stackmapNum = callsiteHead.stackmapNum;
ASSERT(stackmapNum % 2 == 0); // 2:base and derive
for (uint32_t j = 0; j < stackmapNum; j++) {
auto [regOffset, regOffsetSize, is_full] =
panda::leb128::DecodeSigned<LLVMStackMapType::SLeb128Type>(ptr + offset);
LLVMStackMapType::DecodeRegAndOffset(regOffset, reg, offsetType);
offset += regOffsetSize;
LOG_COMPILER(VERBOSE) << " reg: " << std::dec << reg << " offset:" << offsetType;
arkStackMaps.emplace_back(std::make_pair(reg, offsetType));
}
offset = AlignUp(offset, LLVMStackMapType::STACKMAP_ALIGN_BYTES);
}
void ArkStackMapParser::ParseArkDeopt(const CallsiteHeader& callsiteHead, uint8_t *ptr,
std::vector<ARKDeopt> &deopts) const
{
ARKDeopt deopt;
uint32_t deoptOffset = callsiteHead.deoptOffset;
uint16_t deoptNum = callsiteHead.deoptNum;
LLVMStackMapType::KindType kindType;
LLVMStackMapType::DwarfRegType reg;
LLVMStackMapType::OffsetType offsetType;
ASSERT(deoptNum % 2 == 0); // 2:<id, value>
for (uint32_t j = 0; j < deoptNum; j += 2) { // 2:<id, value>
auto [vregsInfo, vregsInfoSize, InfoIsFull] =
panda::leb128::DecodeSigned<LLVMStackMapType::SLeb128Type>(ptr + deoptOffset);
LLVMStackMapType::DecodeVRegsInfo(vregsInfo, deopt.id, kindType);
deoptOffset += vregsInfoSize;
ASSERT(kindType == LLVMStackMapType::CONSTANT_TYPE || kindType == LLVMStackMapType::OFFSET_TYPE);
if (kindType == LLVMStackMapType::CONSTANT_TYPE) {
auto [constant, constantSize, constIsFull] =
panda::leb128::DecodeSigned<LLVMStackMapType::SLeb128Type>(ptr + deoptOffset);
if (constant > INT32_MAX || constant < INT32_MIN) {
deopt.kind = LocationTy::Kind::CONSTANTNDEX;
deopt.value = static_cast<LLVMStackMapType::LargeInt>(constant);
} else {
deopt.kind = LocationTy::Kind::CONSTANT;
deopt.value = static_cast<LLVMStackMapType::IntType>(constant);
}
deoptOffset += constantSize;
} else {
auto [regOffset, regOffsetSize, regOffIsFull] =
panda::leb128::DecodeSigned<LLVMStackMapType::SLeb128Type>(ptr + deoptOffset);
LLVMStackMapType::DecodeRegAndOffset(regOffset, reg, offsetType);
deopt.kind = LocationTy::Kind::INDIRECT;
deopt.value = std::make_pair(reg, offsetType);
deoptOffset += regOffsetSize;
}
deopts.emplace_back(deopt);
}
}
void ArkStackMapParser::ParseArkStackMapAndDeopt(uint8_t *ptr, uint32_t length) const
{
CallsiteHeader callsiteHead;
ArkStackMapHeader secHead;
BinaryBufferParser binBufparser(ptr, length);
binBufparser.ParseBuffer(&secHead, sizeof(ArkStackMapHeader));
for (uint32_t i = 0; i < secHead.callsiteNum; i++) {
binBufparser.ParseBuffer(&callsiteHead, sizeof(CallsiteHeader));
std::vector<ARKDeopt> deopts;
ArkStackMap arkStackMaps;
LOG_COMPILER(VERBOSE) << " calliteOffset:0x" << std::hex << callsiteHead.calliteOffset
<< " stackmap offset:0x" << std::hex << callsiteHead.stackmapOffset
<< " num:" << callsiteHead.stackmapNum
<< " deopt Offset:0x" << std::hex << callsiteHead.deoptOffset
<< " num:" << callsiteHead.deoptNum;
ParseArkStackMap(callsiteHead, ptr, arkStackMaps);
ParseArkDeopt(callsiteHead, ptr, deopts);
}
}
} // namespace panda::ecmascript::kungfu

View File

@ -37,22 +37,20 @@ public:
{
enableLog_ = false;
}
void GetConstInfo(uintptr_t callsite, ConstInfo &info, uint8_t *stackmapAddr = nullptr) const;
bool IteratorStackMap(const RootVisitor &visitor,
const RootBaseAndDerivedVisitor &derivedVisitor,
void GetConstInfo(uintptr_t callsite, LLVMStackMapType::ConstInfo& info, uint8_t *stackmapAddr = nullptr) const;
bool IteratorStackMap(const RootVisitor& visitor,
const RootBaseAndDerivedVisitor& derivedVisitor,
uintptr_t callSiteAddr, uintptr_t callsiteFp,
uintptr_t callSiteSp, uint8_t *stackmapAddr) const;
void GetArkDeopt(uintptr_t callSiteAddr, uint8_t *stackmapAddr, std::vector<kungfu::ARKDeopt>& deopts) const;
void GetArkDeopt(uintptr_t callSiteAddr, uint8_t *stackmapAddr, std::vector<ARKDeopt>& deopts) const;
private:
int BinaraySearch(CallsiteHead *callsiteHead, uint32_t callsiteNum, uintptr_t callSiteAddr) const;
void GetArkDeopt(uint8_t *stackmapAddr, uint32_t length, const CallsiteHead& callsiteHead,
std::vector<kungfu::ARKDeopt>& deopt) const;
void ParseArkDeopt(const CallsiteHead& callsiteHead, BinaryBufferParser& binBufparser,
uint8_t *ptr, std::vector<kungfu::ARKDeopt> &deopts) const;
void ParseArkStackMap(const CallsiteHead& callsiteHead, BinaryBufferParser& binBufparser,
uint8_t *ptr, ArkStackMap &stackMap) const;
int BinaraySearch(CallsiteHeader *callsiteHead, uint32_t callsiteNum, uintptr_t callSiteAddr) const;
void GetArkDeopt(uint8_t *stackmapAddr, const CallsiteHeader& callsiteHead,
std::vector<ARKDeopt>& deopt) const;
void ParseArkDeopt(const CallsiteHeader& callsiteHead, uint8_t *ptr, std::vector<ARKDeopt>& deopts) const;
void ParseArkStackMap(const CallsiteHeader& callsiteHead, uint8_t *ptr, ArkStackMap& stackMap) const;
void ParseArkStackMapAndDeopt(uint8_t *ptr, uint32_t length) const;
uintptr_t GetStackSlotAddress(const DwarfRegAndOffsetType info,
uintptr_t GetStackSlotAddress(const LLVMStackMapType::DwarfRegAndOffsetType info,
uintptr_t callSiteSp, uintptr_t callsiteFp) const;
friend class ArkStackMapBuilder;
bool enableLog_ {false};

View File

@ -41,7 +41,7 @@ std::string LocationTy::TypeToString(Kind loc) const
}
}
const CallSiteInfo* LLVMStackMapParser::GetCallSiteInfoByPc(uintptr_t callSiteAddr) const
const LLVMStackMapType::CallSiteInfo* LLVMStackMapParser::GetCallSiteInfoByPc(uintptr_t callSiteAddr) const
{
for (auto &pc2CallSiteInfo: pc2CallSiteInfoVec_) {
auto it = pc2CallSiteInfo.find(callSiteAddr);
@ -55,31 +55,31 @@ const CallSiteInfo* LLVMStackMapParser::GetCallSiteInfoByPc(uintptr_t callSiteAd
void LLVMStackMapParser::CalcCallSite()
{
uint64_t recordNum = 0;
Pc2CallSiteInfo pc2CallSiteInfo;
Pc2Deopt deoptbundles;
LLVMStackMapType::Pc2CallSiteInfo pc2CallSiteInfo;
LLVMStackMapType::Pc2Deopt deoptbundles;
auto calStkMapRecordFunc =
[this, &recordNum, &pc2CallSiteInfo, &deoptbundles](uintptr_t address, uint32_t recordId) {
struct StkMapRecordHeadTy recordHead = llvmStackMap_.StkMapRecord[recordNum + recordId].head;
struct StkMapRecordHeadTy recordHead = llvmStackMap_.stkMapRecord[recordNum + recordId].head;
int lastDeoptIndex = -1;
for (int j = 0; j < recordHead.NumLocations; j++) {
struct LocationTy loc = llvmStackMap_.StkMapRecord[recordNum + recordId].Locations[j];
uint32_t instructionOffset = recordHead.InstructionOffset;
for (int j = 0; j < recordHead.numLocations; j++) {
struct LocationTy loc = llvmStackMap_.stkMapRecord[recordNum + recordId].locations[j];
uint32_t instructionOffset = recordHead.instructionOffset;
uintptr_t callsite = address + instructionOffset;
uint64_t patchPointID = recordHead.PatchPointID;
uint64_t patchPointID = recordHead.patchPointID;
if (j == LocationTy::CONSTANT_DEOPT_CNT_INDEX) {
ASSERT(loc.location == LocationTy::Kind::CONSTANT);
lastDeoptIndex = loc.OffsetOrSmallConstant + LocationTy::CONSTANT_DEOPT_CNT_INDEX;
lastDeoptIndex = loc.offsetOrSmallConstant + LocationTy::CONSTANT_DEOPT_CNT_INDEX;
}
if (loc.location == LocationTy::Kind::INDIRECT) {
OPTIONAL_LOG_COMPILER(DEBUG) << "DwarfRegNum:" << loc.DwarfRegNum << " loc.OffsetOrSmallConstant:"
<< loc.OffsetOrSmallConstant << "address:" << address << " instructionOffset:" <<
OPTIONAL_LOG_COMPILER(DEBUG) << "DwarfRegNum:" << loc.dwarfRegNum << " loc.OffsetOrSmallConstant:"
<< loc.offsetOrSmallConstant << "address:" << address << " instructionOffset:" <<
instructionOffset << " callsite:" << " patchPointID :" << std::hex << patchPointID <<
callsite;
DwarfRegAndOffsetType info(loc.DwarfRegNum, loc.OffsetOrSmallConstant);
LLVMStackMapType::DwarfRegAndOffsetType info(loc.dwarfRegNum, loc.offsetOrSmallConstant);
auto it = pc2CallSiteInfo.find(callsite);
if (j > lastDeoptIndex) {
if (pc2CallSiteInfo.find(callsite) == pc2CallSiteInfo.end()) {
pc2CallSiteInfo.insert(std::pair<uintptr_t, CallSiteInfo>(callsite, {info}));
pc2CallSiteInfo.insert(std::pair<uintptr_t, LLVMStackMapType::CallSiteInfo>(callsite, {info}));
} else {
it->second.emplace_back(info);
}
@ -88,17 +88,17 @@ void LLVMStackMapParser::CalcCallSite()
}
} else if (loc.location == LocationTy::Kind::CONSTANT) {
if (j >= LocationTy::CONSTANT_FIRST_ELEMENT_INDEX && j <= lastDeoptIndex) {
deoptbundles[callsite].push_back(loc.OffsetOrSmallConstant);
deoptbundles[callsite].push_back(loc.offsetOrSmallConstant);
}
} else if (loc.location == LocationTy::Kind::DIRECT) {
if (j >= LocationTy::CONSTANT_FIRST_ELEMENT_INDEX && j <= lastDeoptIndex) {
DwarfRegAndOffsetType info(loc.DwarfRegNum, loc.OffsetOrSmallConstant);
LLVMStackMapType::DwarfRegAndOffsetType info(loc.dwarfRegNum, loc.offsetOrSmallConstant);
deoptbundles[callsite].push_back(info);
}
} else if (loc.location == LocationTy::Kind::CONSTANTNDEX) {
if (j >= LocationTy::CONSTANT_FIRST_ELEMENT_INDEX && j <= lastDeoptIndex) {
LargeInt v = static_cast<LargeInt>(llvmStackMap_.
Constants[loc.OffsetOrSmallConstant].LargeConstant);
LLVMStackMapType::LargeInt v = static_cast<LLVMStackMapType::LargeInt>(llvmStackMap_.
constants[loc.offsetOrSmallConstant].largeConstant);
deoptbundles[callsite].push_back(v);
}
} else {
@ -107,10 +107,10 @@ void LLVMStackMapParser::CalcCallSite()
}
}
};
for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) {
for (size_t i = 0; i < llvmStackMap_.stkSizeRecords.size(); i++) {
// relative offset
uintptr_t address = llvmStackMap_.StkSizeRecords[i].functionAddress;
uint64_t recordCount = llvmStackMap_.StkSizeRecords[i].recordCount;
uintptr_t address = llvmStackMap_.stkSizeRecords[i].functionAddress;
uint64_t recordCount = llvmStackMap_.stkSizeRecords[i].recordCount;
fun2RecordNum_.emplace_back(std::make_pair(address, recordCount));
for (uint64_t k = 0; k < recordCount; k++) {
calStkMapRecordFunc(address, k);
@ -134,21 +134,21 @@ bool LLVMStackMapParser::CalculateStackMap(std::unique_ptr<uint8_t []> stackMapA
numConstants = dataInfo_->Read<uint32_t>();
numRecords = dataInfo_->Read<uint32_t>();
for (uint32_t i = 0; i < numFunctions; i++) {
auto stkRecord = dataInfo_->Read<struct StkSizeRecordTy>();
llvmStackMap_.StkSizeRecords.push_back(stkRecord);
auto stkRecord = dataInfo_->Read<struct StkMapSizeRecordTy>();
llvmStackMap_.stkSizeRecords.push_back(stkRecord);
}
for (uint32_t i = 0; i < numConstants; i++) {
auto val = dataInfo_->Read<struct ConstantsTy>();
llvmStackMap_.Constants.push_back(val);
llvmStackMap_.constants.push_back(val);
}
for (uint32_t i = 0; i < numRecords; i++) {
struct StkMapRecordTy stkSizeRecord;
auto head = dataInfo_->Read<struct StkMapRecordHeadTy>();
stkSizeRecord.head = head;
for (uint16_t j = 0; j < head.NumLocations; j++) {
for (uint16_t j = 0; j < head.numLocations; j++) {
auto location = dataInfo_->Read<struct LocationTy>();
stkSizeRecord.Locations.push_back(location);
stkSizeRecord.locations.push_back(location);
}
while (dataInfo_->GetOffset() & 7) { // 7: 8 byte align
dataInfo_->Read<uint16_t>();
@ -157,13 +157,13 @@ bool LLVMStackMapParser::CalculateStackMap(std::unique_ptr<uint8_t []> stackMapA
if (numLiveOuts > 0) {
for (uint32_t j = 0; j < numLiveOuts; j++) {
auto liveOut = dataInfo_->Read<struct LiveOutsTy>();
stkSizeRecord.LiveOuts.push_back(liveOut);
stkSizeRecord.liveOuts.push_back(liveOut);
}
}
while (dataInfo_->GetOffset() & 7) { // 7: 8 byte align
dataInfo_->Read<uint16_t>();
}
llvmStackMap_.StkMapRecord.push_back(stkSizeRecord);
llvmStackMap_.stkMapRecord.push_back(stkSizeRecord);
}
CalcCallSite();
return true;
@ -175,9 +175,15 @@ uint32_t ARKCallsite::CalHeadSize() const
return headSize;
}
uint32_t ARKCallsite::CalStackMapSize() const
uint32_t ARKCallsite::CalStackMapSize(Triple triple) const
{
size_t stackmapSize = stackmaps.size() * (sizeof(OffsetType) + sizeof(DwarfRegType));
size_t stackmapSize = 0;
for (auto &x : stackmaps) {
std::vector<uint8_t> value;
size_t valueSize = 0;
LLVMStackMapType::EncodeRegAndOffset(value, valueSize, x.first, x.second, triple);
stackmapSize += value.size();
}
return stackmapSize;
}
@ -191,10 +197,10 @@ bool LLVMStackMapParser::CalculateStackMap(std::unique_ptr<uint8_t []> stackMapA
OPTIONAL_LOG_COMPILER(DEBUG) << "stackmap calculate update funcitonaddress ";
for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) {
uintptr_t hostAddr = llvmStackMap_.StkSizeRecords[i].functionAddress;
for (size_t i = 0; i < llvmStackMap_.stkSizeRecords.size(); i++) {
uintptr_t hostAddr = llvmStackMap_.stkSizeRecords[i].functionAddress;
uintptr_t offset = hostAddr - hostCodeSectionAddr;
llvmStackMap_.StkSizeRecords[i].functionAddress = offset;
llvmStackMap_.stkSizeRecords[i].functionAddress = offset;
OPTIONAL_LOG_COMPILER(DEBUG) << std::dec << i << "th function " << std::hex << hostAddr << " ---> "
<< " offset:" << offset;
}
@ -205,9 +211,9 @@ bool LLVMStackMapParser::CalculateStackMap(std::unique_ptr<uint8_t []> stackMapA
return true;
}
void LLVMStackMapParser::CalculateFuncFpDelta(Func2FpDelta info, uint32_t moduleIndex)
void LLVMStackMapParser::CalculateFuncFpDelta(LLVMStackMapType::Func2FpDelta info, uint32_t moduleIndex)
{
std::vector<Func2FpDelta> fun2FpDelta;
std::vector<LLVMStackMapType::Func2FpDelta> fun2FpDelta;
auto it = module2fun2FpDelta_.find(moduleIndex);
if (it != module2fun2FpDelta_.end()) {
fun2FpDelta = module2fun2FpDelta_.at(moduleIndex);

View File

@ -26,6 +26,7 @@
#include "ecmascript/ecma_macros.h"
#include "ecmascript/interpreter/interpreter-inl.h"
#include "ecmascript/stackmap/ark_stackmap.h"
#include "ecmascript/stackmap/ark_stackmap_builder.h"
#include "ecmascript/stackmap/llvm_stackmap_type.h"
namespace panda::ecmascript::kungfu {
@ -40,13 +41,13 @@ public:
llvmStackMap_.Print();
}
}
const CallSiteInfo *GetCallSiteInfoByPc(uintptr_t funcAddr) const;
const LLVMStackMapType::CallSiteInfo *GetCallSiteInfoByPc(uintptr_t funcAddr) const;
bool IsLogEnabled() const
{
return enableLog_;
}
void PUBLIC_API CalculateFuncFpDelta(Func2FpDelta info, uint32_t moduleIndex);
void PUBLIC_API CalculateFuncFpDelta(LLVMStackMapType::Func2FpDelta info, uint32_t moduleIndex);
explicit LLVMStackMapParser(bool enableLog = false)
{
@ -67,25 +68,25 @@ public:
fun2FpDelta_.clear();
pc2DeoptVec_.clear();
}
std::vector<Pc2CallSiteInfo> PUBLIC_API GetPc2StackMapVec() const
std::vector<LLVMStackMapType::Pc2CallSiteInfo> PUBLIC_API GetPc2StackMapVec() const
{
return pc2CallSiteInfoVec_;
}
std::vector<Pc2Deopt> GetPc2Deopt() const
std::vector<LLVMStackMapType::Pc2Deopt> GetPc2Deopt() const
{
return pc2DeoptVec_;
}
private:
void CalcCallSite();
struct LLVMStackMap llvmStackMap_;
std::vector<Pc2CallSiteInfo> pc2CallSiteInfoVec_;
std::vector<LLVMStackMapType::Pc2CallSiteInfo> pc2CallSiteInfoVec_;
std::vector<std::pair<uintptr_t, uint64_t>> fun2RecordNum_;
std::unique_ptr<DataInfo> dataInfo_;
bool enableLog_ {false};
std::set<uintptr_t> funAddr_;
std::vector<Func2FpDelta> fun2FpDelta_;
std::vector<Pc2Deopt> pc2DeoptVec_;
std::map<uint32_t, std::vector<Func2FpDelta>> module2fun2FpDelta_;
std::vector<LLVMStackMapType::Func2FpDelta> fun2FpDelta_;
std::vector<LLVMStackMapType::Pc2Deopt> pc2DeoptVec_;
std::map<uint32_t, std::vector<LLVMStackMapType::Func2FpDelta>> module2fun2FpDelta_;
std::map<uint32_t, std::set<uintptr_t>> module2funAddr_;
};
} // namespace panda::ecmascript::kungfu

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/stackmap/llvm_stackmap_type.h"
namespace panda::ecmascript::kungfu {
void LLVMStackMapType::EncodeRegAndOffset(std::vector<uint8_t> &regOffset, size_t &regOffsetSize,
DwarfRegType reg, OffsetType offset, Triple triple)
{
SLeb128Type dwarfRegAndOff = offset;
auto fpReg = GCStackMapRegisters::GetFpRegByTriple(triple);
auto spReg = GCStackMapRegisters::GetSpRegByTriple(triple);
if (reg == fpReg) {
dwarfRegAndOff = (dwarfRegAndOff << 1) + FP_VALUE;
} else if (reg == spReg) {
dwarfRegAndOff = (dwarfRegAndOff << 1) + SP_VALUE;
} else {
LOG_ECMA(FATAL) << "dwarfreg branch is unreachable";
UNREACHABLE();
}
size_t valueSize = panda::leb128::SignedEncodingSize(dwarfRegAndOff);
regOffset.resize(valueSize);
regOffsetSize = panda::leb128::EncodeSigned(dwarfRegAndOff, regOffset.data());
}
void LLVMStackMapType::DecodeRegAndOffset(SLeb128Type regOffset, DwarfRegType &reg, OffsetType &offset)
{
if (regOffset % STACKMAP_TYPE_NUM == LLVMStackMapType::FP_VALUE) {
reg = GCStackMapRegisters::FP;
} else {
reg = GCStackMapRegisters::SP;
}
offset = static_cast<LLVMStackMapType::OffsetType>(regOffset >> 1);
}
void LLVMStackMapType::EncodeVRegsInfo(std::vector<uint8_t> &vregsInfo, size_t &vregsInfoSize,
VRegId id, LocationTy::Kind kind)
{
SLeb128Type vregIdAndKind = id;
if (kind == LocationTy::Kind::CONSTANT || kind == LocationTy::Kind::CONSTANTNDEX) {
vregIdAndKind = (vregIdAndKind << 1) + CONSTANT_TYPE;
} else if (kind == LocationTy::Kind::INDIRECT) {
vregIdAndKind = (vregIdAndKind << 1) + OFFSET_TYPE;
} else {
LOG_ECMA(FATAL) << "vreg kind branch is unreachable";
UNREACHABLE();
}
size_t vregIdAndKindSize = panda::leb128::SignedEncodingSize(vregIdAndKind);
vregsInfo.resize(vregIdAndKindSize);
vregsInfoSize = panda::leb128::EncodeSigned(vregIdAndKind, vregsInfo.data());
}
void LLVMStackMapType::DecodeVRegsInfo(SLeb128Type vregsInfo, VRegId &id, KindType &kind)
{
if (vregsInfo % STACKMAP_TYPE_NUM == CONSTANT_TYPE) {
kind = CONSTANT_TYPE;
} else {
kind = OFFSET_TYPE;
}
id = static_cast<VRegId>(vregsInfo >> 1);
}
} // namespace panda::ecmascript::kungfu

View File

@ -21,27 +21,96 @@
#include <unordered_map>
#include <variant>
#include <vector>
#include <cmath>
#include "ecmascript/base/bit_helper.h"
#include "ecmascript/common.h"
#include "ecmascript/compiler/assembler/assembler.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/mem/mem.h"
#include "libpandabase/utils/leb128.h"
namespace panda::ecmascript::kungfu {
using OffsetType = int32_t;
using DwarfRegType = uint16_t;
using LargeInt = int64_t;
using DwarfRegAndOffsetType = std::pair<DwarfRegType, OffsetType>;
using CallSiteInfo = std::vector<DwarfRegAndOffsetType>;
using Fun2InfoType = std::pair<uintptr_t, DwarfRegAndOffsetType>;
using Pc2CallSiteInfo = std::unordered_map<uintptr_t, CallSiteInfo>;
using FpDelta = std::pair<int, uint32_t>;
using Func2FpDelta = std::unordered_map<uintptr_t, FpDelta>; // value: fpDelta & funcSize
using ConstInfo = std::vector<OffsetType>;
using DeoptInfoType = std::vector<std::variant<OffsetType, LargeInt, DwarfRegAndOffsetType>>;
using Pc2Deopt = std::unordered_map<uintptr_t, DeoptInfoType>;
struct LocationTy {
enum class Kind: uint8_t {
REGISTER = 1,
DIRECT = 2,
INDIRECT = 3,
CONSTANT = 4,
CONSTANTNDEX = 5,
};
static constexpr int CONSTANT_FIRST_ELEMENT_INDEX = 3;
static constexpr int CONSTANT_DEOPT_CNT_INDEX = 2;
Kind location;
uint8_t reserved_0;
uint16_t locationSize;
uint16_t dwarfRegNum;
uint16_t reserved_1;
int32_t offsetOrSmallConstant;
std::string PUBLIC_API TypeToString(Kind loc) const;
void Print() const
{
LOG_COMPILER(DEBUG) << TypeToString(location);
LOG_COMPILER(DEBUG) << ", size:" << std::dec << locationSize;
LOG_COMPILER(DEBUG) << "\tDwarfRegNum:" << dwarfRegNum;
LOG_COMPILER(DEBUG) << "\t OffsetOrSmallConstant:" << offsetOrSmallConstant;
}
};
class LLVMStackMapType {
public:
using OffsetType = int32_t;
using DwarfRegType = uint16_t;
using IntType = int32_t;
using LargeInt = int64_t;
using RegType = int8_t;
using KindType = int8_t;
using VRegId = int16_t;
using SLeb128Type = int64_t;
using DwarfRegAndOffsetType = std::pair<DwarfRegType, OffsetType>;
using CallSiteInfo = std::vector<DwarfRegAndOffsetType>;
using Fun2InfoType = std::pair<uintptr_t, DwarfRegAndOffsetType>;
using Pc2CallSiteInfo = std::unordered_map<uintptr_t, CallSiteInfo>;
using FpDelta = std::pair<int, uint32_t>;
using Func2FpDelta = std::unordered_map<uintptr_t, FpDelta>; // value: fpDelta & funcSize
using ConstInfo = std::vector<IntType>;
using DeoptInfoType = std::vector<std::variant<IntType, LargeInt, DwarfRegAndOffsetType>>;
using Pc2Deopt = std::unordered_map<uintptr_t, DeoptInfoType>;
static constexpr size_t STACKMAP_ALIGN_BYTES = 2;
static constexpr KindType CONSTANT_TYPE = 0;
static constexpr KindType OFFSET_TYPE = 1;
template <typename T>
static void EncodeData(std::vector<uint8_t> &outData, size_t &dataSize, T value)
{
static_assert(std::is_signed_v<T>, "T must be signed");
SLeb128Type data = value;
size_t valueSize = panda::leb128::SignedEncodingSize(data);
outData.resize(valueSize);
dataSize = panda::leb128::EncodeSigned(data, outData.data());
}
static void EncodeRegAndOffset(std::vector<uint8_t> &regOffset, size_t &regOffsetSize,
DwarfRegType reg, OffsetType offset, Triple triple);
static void DecodeRegAndOffset(SLeb128Type regOffset, DwarfRegType &reg, OffsetType &offset);
static void EncodeVRegsInfo(std::vector<uint8_t> &vregsInfo, size_t &vregsInfoSize,
VRegId id, LocationTy::Kind kind);
static void DecodeVRegsInfo(SLeb128Type vregsInfo, VRegId &id, KindType &kind);
private:
static constexpr size_t STACKMAP_TYPE_NUM = 2;
static constexpr RegType FP_VALUE = 0;
static constexpr RegType SP_VALUE = 1;
};
struct Header {
uint8_t stackmapversion; // Stack Map Version (current version is 3)
uint8_t Reserved0; // Reserved (expected to be 0)
uint16_t Reserved1; // Reserved (expected to be 0)
uint8_t reserved0; // Reserved (expected to be 0)
uint16_t reserved1; // Reserved (expected to be 0)
void Print() const
{
LOG_COMPILER(DEBUG) << "----- head ----";
@ -51,7 +120,7 @@ struct Header {
};
#pragma pack(1)
struct StkSizeRecordTy {
struct StkMapSizeRecordTy {
uintptr_t functionAddress;
uint64_t stackSize;
uint64_t recordCount;
@ -65,79 +134,50 @@ struct StkSizeRecordTy {
#pragma pack()
struct ConstantsTy {
uintptr_t LargeConstant;
uintptr_t largeConstant;
void Print() const
{
LOG_COMPILER(DEBUG) << " LargeConstant:0x" << std::hex << LargeConstant;
LOG_COMPILER(DEBUG) << " LargeConstant:0x" << std::hex << largeConstant;
}
};
struct StkMapRecordHeadTy {
uint64_t PatchPointID;
uint32_t InstructionOffset;
uint16_t Reserved;
uint16_t NumLocations;
uint64_t patchPointID;
uint32_t instructionOffset;
uint16_t reserved;
uint16_t numLocations;
void Print() const
{
LOG_COMPILER(DEBUG) << " PatchPointID:0x" << std::hex << PatchPointID;
LOG_COMPILER(DEBUG) << " instructionOffset:0x" << std::hex << InstructionOffset;
LOG_COMPILER(DEBUG) << " Reserved:0x" << std::hex << Reserved;
LOG_COMPILER(DEBUG) << " NumLocations:0x" << std::hex << NumLocations;
LOG_COMPILER(DEBUG) << " PatchPointID:0x" << std::hex << patchPointID;
LOG_COMPILER(DEBUG) << " instructionOffset:0x" << std::hex << instructionOffset;
LOG_COMPILER(DEBUG) << " Reserved:0x" << std::hex << reserved;
LOG_COMPILER(DEBUG) << " NumLocations:0x" << std::hex << numLocations;
}
};
struct LocationTy {
enum class Kind: uint8_t {
REGISTER = 1,
DIRECT = 2,
INDIRECT = 3,
CONSTANT = 4,
CONSTANTNDEX = 5,
};
static constexpr int CONSTANT_FIRST_ELEMENT_INDEX = 3;
static constexpr int CONSTANT_DEOPT_CNT_INDEX = 2;
Kind location;
uint8_t Reserved_0;
uint16_t LocationSize;
uint16_t DwarfRegNum;
uint16_t Reserved_1;
OffsetType OffsetOrSmallConstant;
std::string PUBLIC_API TypeToString(Kind loc) const;
void Print() const
{
LOG_COMPILER(DEBUG) << TypeToString(location);
LOG_COMPILER(DEBUG) << ", size:" << std::dec << LocationSize;
LOG_COMPILER(DEBUG) << "\tDwarfRegNum:" << DwarfRegNum;
LOG_COMPILER(DEBUG) << "\t OffsetOrSmallConstant:" << OffsetOrSmallConstant;
}
};
struct LiveOutsTy {
DwarfRegType DwarfRegNum;
uint8_t Reserved;
uint8_t SizeinBytes;
LLVMStackMapType::DwarfRegType dwarfRegNum;
uint8_t reserved;
uint8_t sizeinBytes;
void Print() const
{
LOG_COMPILER(DEBUG) << " Dwarf RegNum:" << DwarfRegNum;
LOG_COMPILER(DEBUG) << " Reserved:" << Reserved;
LOG_COMPILER(DEBUG) << " SizeinBytes:" << SizeinBytes;
LOG_COMPILER(DEBUG) << " Dwarf RegNum:" << dwarfRegNum;
LOG_COMPILER(DEBUG) << " Reserved:" << reserved;
LOG_COMPILER(DEBUG) << " SizeinBytes:" << sizeinBytes;
}
};
struct StkMapRecordTy {
struct StkMapRecordHeadTy head;
std::vector<struct LocationTy> Locations;
std::vector<struct LiveOutsTy> LiveOuts;
std::vector<struct LocationTy> locations;
std::vector<struct LiveOutsTy> liveOuts;
void Print() const
{
head.Print();
auto size = Locations.size();
auto size = locations.size();
for (size_t i = 0; i < size; i++) {
LOG_COMPILER(DEBUG) << " #" << std::dec << i << ":";
Locations[i].Print();
locations[i].Print();
}
size = LiveOuts.size();
size = liveOuts.size();
for (size_t i = 0; i < size; i++) {
LOG_COMPILER(DEBUG) << " liveOuts[" << i << "] info:";
}
@ -170,23 +210,23 @@ private:
struct LLVMStackMap {
struct Header head;
std::vector<struct StkSizeRecordTy> StkSizeRecords;
std::vector<struct ConstantsTy> Constants;
std::vector<struct StkMapRecordTy> StkMapRecord;
std::vector<struct StkMapSizeRecordTy> stkSizeRecords;
std::vector<struct ConstantsTy> constants;
std::vector<struct StkMapRecordTy> stkMapRecord;
void Print() const
{
head.Print();
for (size_t i = 0; i < StkSizeRecords.size(); i++) {
LOG_COMPILER(DEBUG) << "stkSizeRecord[" << i << "] info:";
StkSizeRecords[i].Print();
for (size_t i = 0; i < stkSizeRecords.size(); i++) {
LOG_COMPILER(DEBUG) << "StkSizeRecord[" << i << "] info:";
stkSizeRecords[i].Print();
}
for (size_t i = 0; i < Constants.size(); i++) {
LOG_COMPILER(DEBUG) << "constants[" << i << "] info:";
Constants[i].Print();
for (size_t i = 0; i < constants.size(); i++) {
LOG_COMPILER(DEBUG) << "Constants[" << i << "] info:";
constants[i].Print();
}
for (size_t i = 0; i < StkMapRecord.size(); i++) {
for (size_t i = 0; i < stkMapRecord.size(); i++) {
LOG_COMPILER(DEBUG) << "StkMapRecord[" << i << "] info:";
StkMapRecord[i].Print();
stkMapRecord[i].Print();
}
}
};