mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 01:59:58 +00:00
Optimize frame iteration
1. In ArkStackMapParser::IteratorStackMap, it will traverse stackmap twice, once for storing info and another for handling info Now, it traverse only one time. 2. Storing fp delta in 'method.extraLiteralInfo' and skip finding FuncEntryDes in AOTFileInfo::CalCallSiteInfo which will accelerate FrameIterator::Advance 3. Skip storing callee register info if CalCallSiteInfo is not called when handling deopt 4. Add an aottest case to test branches of Advance with different GCVisitedFlag and frame type Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IAJX4B?from=project-issue Signed-off-by: xing-yunhao <xingyunhao1@huawei.com> Change-Id: I3f2c8e8f49fb46218496d131ca253cc845d11746
This commit is contained in:
parent
d037008cee
commit
3eaf375b72
@ -47,6 +47,7 @@ using StringHelper = base::StringHelper;
|
||||
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
||||
constexpr char FILEDIR[] = "/data/storage/el2/base/files/";
|
||||
#endif
|
||||
|
||||
JSTaggedValue BuiltinsArkTools::ObjectDump(EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
ASSERT(info);
|
||||
@ -1461,4 +1462,44 @@ JSTaggedValue BuiltinsArkTools::StopRuntimeStat(EcmaRuntimeCallInfo *msg)
|
||||
thread->GetCurrentEcmaContext()->SetRuntimeStatEnable(false);
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsArkTools::IterateFrame(EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
ASSERT(info);
|
||||
JSThread *thread = info->GetThread();
|
||||
RETURN_IF_DISALLOW_ARKTOOLS(thread);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
|
||||
JSTaggedType *currentFrame = const_cast<JSTaggedType *>(thread->GetCurrentFrame());
|
||||
RootVisitor visitor = []([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot slot) {};
|
||||
RootBaseAndDerivedVisitor derivedVisitor = []([[maybe_unused]] Root Type, [[maybe_unused]] ObjectSlot base,
|
||||
[[maybe_unused]] ObjectSlot derived,
|
||||
[[maybe_unused]] uintptr_t baseOldObject) {};
|
||||
|
||||
for (FrameIterator it(currentFrame, thread); !it.Done(); it.Advance<GCVisitedFlag::VISITED>()) {
|
||||
bool ret = it.IteratorStackMap(visitor, derivedVisitor);
|
||||
FrameType type = it.GetFrameType();
|
||||
int delta = it.ComputeDelta();
|
||||
kungfu::CalleeRegAndOffsetVec calleeRegInfo;
|
||||
it.GetCalleeRegAndOffsetVec(calleeRegInfo);
|
||||
LOG_BUILTINS(INFO) << "IterateFrameType: " << (int)type;
|
||||
LOG_BUILTINS(INFO) << "IterateFrameDelta: " << delta;
|
||||
LOG_BUILTINS(INFO) << "IterateFrameCalleeRegInfo: " << calleeRegInfo.size();
|
||||
if (!ret) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (FrameIterator it(currentFrame, thread); !it.Done(); it.Advance<GCVisitedFlag::DEOPT>()) {
|
||||
FrameType type = it.GetFrameType();
|
||||
int delta = it.ComputeDelta();
|
||||
kungfu::CalleeRegAndOffsetVec calleeRegInfo;
|
||||
it.GetCalleeRegAndOffsetVec(calleeRegInfo);
|
||||
LOG_BUILTINS(INFO) << "DeoptIterateFrameType: " << (int)type;
|
||||
LOG_BUILTINS(INFO) << "DeoptIterateFrameDelta: " << delta;
|
||||
LOG_BUILTINS(INFO) << "DeoptIterateFrameCalleeRegInfo: " << calleeRegInfo.size();
|
||||
}
|
||||
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
} // namespace panda::ecmascript::builtins
|
||||
|
@ -56,7 +56,8 @@
|
||||
V("checkCircularImport", CheckCircularImport, 2, INVALID) \
|
||||
V("hashCode", HashCode, 1, ArkToolsHashCode) \
|
||||
V("startRuntimeStat", StartRuntimeStat, 0, INVALID) \
|
||||
V("stopRuntimeStat", StopRuntimeStat, 0, INVALID)
|
||||
V("stopRuntimeStat", StopRuntimeStat, 0, INVALID) \
|
||||
V("iterateFrame", IterateFrame, 0, INVALID)
|
||||
|
||||
#define BUILTIN_ARK_TOOLS_FUNCTIONS_REGRESS(V) \
|
||||
V("prepareFunctionForOptimization", PrepareFunctionForOptimization, 1, INVALID) \
|
||||
@ -386,6 +387,8 @@ public:
|
||||
|
||||
static JSTaggedValue StartRuntimeStat(EcmaRuntimeCallInfo *info);
|
||||
static JSTaggedValue StopRuntimeStat(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue IterateFrame(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static Span<const base::BuiltinFunctionEntry> GetArkToolsFunctions()
|
||||
{
|
||||
|
@ -234,21 +234,21 @@ bool AnFileDataManager::SafeInsideAOT(uintptr_t pc)
|
||||
return false;
|
||||
}
|
||||
|
||||
AOTFileInfo::CallSiteInfo AnFileDataManager::SafeCalCallSiteInfo(uintptr_t retAddr)
|
||||
AOTFileInfo::CallSiteInfo AnFileDataManager::SafeCalCallSiteInfo(uintptr_t retAddr, bool isDeopt)
|
||||
{
|
||||
ReadLockHolder lock(lock_);
|
||||
AOTFileInfo::CallSiteInfo callsiteInfo;
|
||||
|
||||
bool ans = false;
|
||||
if (loadedStub_ != nullptr) {
|
||||
ans = loadedStub_->CalCallSiteInfo(retAddr, callsiteInfo);
|
||||
ans = loadedStub_->CalCallSiteInfo(retAddr, callsiteInfo, true, isDeopt);
|
||||
}
|
||||
if (ans) {
|
||||
return callsiteInfo;
|
||||
}
|
||||
// aot
|
||||
for (auto &info : loadedAn_) {
|
||||
ans = info->CalCallSiteInfo(retAddr, callsiteInfo);
|
||||
ans = info->CalCallSiteInfo(retAddr, callsiteInfo, false, isDeopt);
|
||||
if (ans) {
|
||||
return callsiteInfo;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
bool SafeTryReadLock();
|
||||
bool SafeInsideStub(uintptr_t pc);
|
||||
bool SafeInsideAOT(uintptr_t pc);
|
||||
AOTFileInfo::CallSiteInfo SafeCalCallSiteInfo(uintptr_t retAddr);
|
||||
AOTFileInfo::CallSiteInfo SafeCalCallSiteInfo(uintptr_t retAddr, bool isDeopt);
|
||||
static void DestroyFileMapMem(MemMap &fileMapMem);
|
||||
void SafeDestroyAllData();
|
||||
void SafeDestroyAnData(const std::string &fileName);
|
||||
|
@ -149,7 +149,7 @@ void AnFileInfo::UpdateFuncEntries()
|
||||
funcDes.codeAddr_ += des.GetSecAddr(ElfSecName::TEXT);
|
||||
if (funcDes.isMainFunc_) {
|
||||
EntryKey key = std::make_pair(funcDes.abcIndexInAi_, funcDes.indexInKindOrMethodId_);
|
||||
mainEntryMap_[key] = std::make_pair(funcDes.codeAddr_, funcDes.isFastCall_);
|
||||
mainEntryMap_[key] = MainFuncEntry { funcDes.codeAddr_, funcDes.fpDeltaPrevFrameSp_, funcDes.isFastCall_ };
|
||||
#ifndef NDEBUG
|
||||
LOG_COMPILER(INFO) << "AnFileInfo Load main method id: " << funcDes.indexInKindOrMethodId_
|
||||
<< " code addr: " << reinterpret_cast<void *>(funcDes.codeAddr_);
|
||||
|
@ -19,6 +19,12 @@
|
||||
#include "ecmascript/compiler/assembler/assembler.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
struct MainFuncEntry {
|
||||
uint64_t mainEntry {0};
|
||||
int32_t fpDelta {0};
|
||||
bool isFastCall {false};
|
||||
};
|
||||
|
||||
class PUBLIC_API AnFileInfo : public AOTFileInfo {
|
||||
public:
|
||||
using FuncEntryIndexKey = std::pair<std::string, uint32_t>; // (compilefileName, MethodID)
|
||||
@ -37,11 +43,11 @@ public:
|
||||
accumulateTotalSize(moduleDes.GetArkStackMapSize());
|
||||
}
|
||||
|
||||
std::pair<uint64_t, bool> GetMainFuncEntry(uint32_t fileIndex, uint32_t methodId) const
|
||||
MainFuncEntry GetMainFuncEntry(uint32_t fileIndex, uint32_t methodId) const
|
||||
{
|
||||
auto it = mainEntryMap_.find(std::make_pair(fileIndex, methodId));
|
||||
if (it == mainEntryMap_.end()) {
|
||||
return std::make_pair(0, false);
|
||||
return MainFuncEntry { 0, 0, false };
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
@ -103,7 +109,7 @@ private:
|
||||
void AddFuncEntrySec();
|
||||
uint64_t curTextSecOffset_ {0};
|
||||
// Future work: add main entry mapping to ai file
|
||||
std::map<EntryKey, std::pair<uint64_t, bool>> mainEntryMap_ {};
|
||||
std::map<EntryKey, MainFuncEntry> mainEntryMap_ {};
|
||||
bool isLoad_ {false};
|
||||
CUnorderedMap<uint32_t, std::string> entryIdxToFileNameMap_ {};
|
||||
CMap<FuncEntryIndexKey, uint32_t> methodToEntryIndexMap_ {};
|
||||
|
@ -26,18 +26,14 @@ void AOTFileInfo::Destroy()
|
||||
ExecutedMemoryAllocator::DestroyBuf(stubsMem_);
|
||||
}
|
||||
|
||||
bool AOTFileInfo::CalCallSiteInfo(uintptr_t retAddr,
|
||||
std::tuple<uint64_t, uint8_t *, int, CalleeRegAndOffsetVec> &ret) const
|
||||
bool AOTFileInfo::CalCallSiteInfo(uintptr_t retAddr, std::tuple<uint64_t, uint8_t *, int, CalleeRegAndOffsetVec> &ret,
|
||||
bool isInStub, bool isDeopt) const
|
||||
{
|
||||
uint64_t textStart = 0;
|
||||
uint8_t *stackmapAddr = nullptr;
|
||||
int delta = 0;
|
||||
const auto &des = GetCodeUnits();
|
||||
const auto &funcEntryDes = GetStubs();
|
||||
|
||||
auto cmp = [](const AOTFileInfo::FuncEntryDes &a, const AOTFileInfo::FuncEntryDes &b) {
|
||||
return a.codeAddr_ < b.codeAddr_;
|
||||
};
|
||||
size_t len = des.size();
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
auto &d = des[i];
|
||||
@ -46,31 +42,58 @@ bool AOTFileInfo::CalCallSiteInfo(uintptr_t retAddr,
|
||||
if (retAddr < addr || retAddr >= addr + size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
stackmapAddr = d.GetArkStackMapRawPtr();
|
||||
ASSERT(stackmapAddr != nullptr);
|
||||
textStart = addr;
|
||||
auto startIndex = d.GetStartIndex();
|
||||
auto funcCount = d.GetFuncCount();
|
||||
auto s = funcEntryDes.begin() + startIndex;
|
||||
auto t = funcEntryDes.begin() + startIndex + funcCount;
|
||||
AOTFileInfo::FuncEntryDes target;
|
||||
ASSERT(retAddr > 0);
|
||||
target.codeAddr_ = retAddr - 1; // -1: for pc
|
||||
auto it = std::upper_bound(s, t, target, cmp);
|
||||
--it;
|
||||
ASSERT(it != t);
|
||||
ASSERT((it->codeAddr_ <= target.codeAddr_) && (target.codeAddr_ < it->codeAddr_ + it->funcSize_));
|
||||
delta = it->fpDeltaPrevFrameSp_;
|
||||
CalleeRegAndOffsetVec calleeRegInfo;
|
||||
for (uint32_t j = 0; j < it->calleeRegisterNum_; j++) {
|
||||
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);
|
||||
if (!isInStub && !isDeopt) { // no need for getting funcEntryDes when not in stub nor in deopt
|
||||
ret = std::make_tuple(textStart, stackmapAddr, delta, calleeRegInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
ASSERT(retAddr > 0);
|
||||
auto it = GetFuncEntryDesWithCallsite(retAddr - 1, d.GetStartIndex(), d.GetFuncCount()); // -1: for pc
|
||||
delta = it.fpDeltaPrevFrameSp_;
|
||||
if (!isDeopt) { // no need for getting calleeRegInfo when in stub but not in deopt
|
||||
ret = std::make_tuple(textStart, stackmapAddr, delta, calleeRegInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
StoreCalleeRegInfo(it.calleeRegisterNum_, it.CalleeReg2Offset_, calleeRegInfo);
|
||||
ret = std::make_tuple(textStart, stackmapAddr, delta, calleeRegInfo);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
AOTFileInfo::FuncEntryDes AOTFileInfo::GetFuncEntryDesWithCallsite(uintptr_t codeAddr, uint32_t startIndex,
|
||||
uint32_t funcCount) const
|
||||
{
|
||||
const auto &funcEntryDes = GetStubs();
|
||||
|
||||
auto cmp = [](const AOTFileInfo::FuncEntryDes &a, const AOTFileInfo::FuncEntryDes &b) {
|
||||
return a.codeAddr_ < b.codeAddr_;
|
||||
};
|
||||
auto s = funcEntryDes.begin() + startIndex;
|
||||
auto t = funcEntryDes.begin() + startIndex + funcCount;
|
||||
AOTFileInfo::FuncEntryDes target;
|
||||
target.codeAddr_ = codeAddr;
|
||||
auto it = std::upper_bound(s, t, target, cmp);
|
||||
--it;
|
||||
ASSERT(it != t);
|
||||
ASSERT((it->codeAddr_ <= target.codeAddr_) && (target.codeAddr_ < it->codeAddr_ + it->funcSize_));
|
||||
return *it;
|
||||
}
|
||||
|
||||
void AOTFileInfo::StoreCalleeRegInfo(uint32_t calleeRegNum, int32_t *calleeReg2Offset,
|
||||
CalleeRegAndOffsetVec &calleeRegInfo) const
|
||||
{
|
||||
for (uint32_t j = 0; j < calleeRegNum; j++) {
|
||||
DwarfRegType reg = static_cast<DwarfRegType>(calleeReg2Offset[2 * j]);
|
||||
OffsetType offset = static_cast<OffsetType>(calleeReg2Offset[2 * j + 1]);
|
||||
DwarfRegAndOffsetType regAndOffset = std::make_pair(reg, offset);
|
||||
calleeRegInfo.emplace_back(regAndOffset);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -127,7 +127,7 @@ public:
|
||||
|
||||
using CallSiteInfo = std::tuple<uint64_t, uint8_t *, int, CalleeRegAndOffsetVec>;
|
||||
|
||||
bool CalCallSiteInfo(uintptr_t retAddr, CallSiteInfo &ret) const;
|
||||
bool CalCallSiteInfo(uintptr_t retAddr, CallSiteInfo &ret, bool isInStub, bool isDeopt) const;
|
||||
|
||||
virtual void Destroy();
|
||||
|
||||
@ -149,6 +149,13 @@ protected:
|
||||
std::vector<ModuleSectionDes> des_ {};
|
||||
ExecutedMemoryAllocator::ExeMem stubsMem_ {};
|
||||
MemMap fileMapMem_ {};
|
||||
|
||||
private:
|
||||
AOTFileInfo::FuncEntryDes GetFuncEntryDesWithCallsite(uintptr_t codeAddr, uint32_t startIndex,
|
||||
uint32_t funcCount) const;
|
||||
|
||||
void StoreCalleeRegInfo(uint32_t calleeRegNum, int32_t *calleeReg2Offset,
|
||||
CalleeRegAndOffsetVec &calleeRegInfo) const;
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_COMPILER_AOT_FILE_AOT_FILE_INFO_H
|
||||
|
@ -316,10 +316,10 @@ bool AOTFileManager::InsideAOT(uintptr_t pc)
|
||||
return anFileDataManager->SafeInsideAOT(pc);
|
||||
}
|
||||
|
||||
AOTFileInfo::CallSiteInfo AOTFileManager::CalCallSiteInfo(uintptr_t retAddr)
|
||||
AOTFileInfo::CallSiteInfo AOTFileManager::CalCallSiteInfo(uintptr_t retAddr, bool isDeopt)
|
||||
{
|
||||
AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
|
||||
return anFileDataManager->SafeCalCallSiteInfo(retAddr);
|
||||
return anFileDataManager->SafeCalCallSiteInfo(retAddr, isDeopt);
|
||||
}
|
||||
|
||||
void AOTFileManager::PrintAOTEntry(const JSPandaFile *file, const Method *method, uintptr_t entry)
|
||||
@ -350,15 +350,17 @@ void AOTFileManager::SetAOTMainFuncEntry(JSHandle<JSFunction> mainFunc, const JS
|
||||
}
|
||||
// get main func method
|
||||
auto mainFuncMethodId = jsPandaFile->GetMainMethodIndex(entryPoint.data());
|
||||
uint64_t mainEntry;
|
||||
bool isFastCall;
|
||||
std::tie(mainEntry, isFastCall) = anFileInfo->GetMainFuncEntry(fileIndex, mainFuncMethodId);
|
||||
MainFuncEntry mainFuncEntry = anFileInfo->GetMainFuncEntry(fileIndex, mainFuncMethodId);
|
||||
uint64_t mainEntry = mainFuncEntry.mainEntry;
|
||||
int32_t fpDelta = mainFuncEntry.fpDelta;
|
||||
bool isFastCall = mainFuncEntry.isFastCall;
|
||||
MethodLiteral *mainMethod = jsPandaFile->FindMethodLiteral(mainFuncMethodId);
|
||||
mainMethod->SetAotCodeBit(true);
|
||||
mainMethod->SetNativeBit(false);
|
||||
Method *method = mainFunc->GetCallTarget();
|
||||
method->SetDeoptThreshold(vm_->GetJSOptions().GetDeoptThreshold());
|
||||
method->SetCodeEntryAndMarkAOTWhenBinding(static_cast<uintptr_t>(mainEntry));
|
||||
method->SetFpDelta(fpDelta);
|
||||
method->SetIsFastCall(isFastCall);
|
||||
mainFunc->SetCompiledFuncEntry(static_cast<uintptr_t>(mainEntry), isFastCall);
|
||||
#ifndef NDEBUG
|
||||
@ -392,6 +394,7 @@ void AOTFileManager::SetAOTFuncEntry(const JSPandaFile *jsPandaFile, JSFunction
|
||||
method->SetDeoptThreshold(vm_->GetJSOptions().GetDeoptThreshold());
|
||||
method->SetCodeEntryAndMarkAOTWhenBinding(codeEntry);
|
||||
method->SetIsFastCall(entry.isFastCall_);
|
||||
method->SetFpDelta(entry.fpDeltaPrevFrameSp_);
|
||||
if (canFastCall != nullptr) {
|
||||
*canFastCall = entry.isFastCall_;
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ public:
|
||||
#endif
|
||||
void LoadStubFile(const std::string& fileName);
|
||||
static bool LoadAnFile(const std::string& fileName);
|
||||
static AOTFileInfo::CallSiteInfo CalCallSiteInfo(uintptr_t retAddr);
|
||||
static AOTFileInfo::CallSiteInfo CalCallSiteInfo(uintptr_t retAddr, bool isDeopt);
|
||||
static bool TryReadLock();
|
||||
static bool InsideStub(uintptr_t pc);
|
||||
static bool InsideAOT(uintptr_t pc);
|
||||
|
@ -282,7 +282,7 @@ void Deoptimizier::CollectDeoptBundleVec(std::vector<ARKDeopt>& deoptBundle)
|
||||
JSTaggedType *lastLeave = const_cast<JSTaggedType *>(thread_->GetLastLeaveFrame());
|
||||
FrameIterator it(lastLeave, thread_);
|
||||
// note: last deopt bridge frame is generated by DeoptHandlerAsm, callee Regs is grow from this frame
|
||||
for (; !it.Done() && deoptBundle.empty(); it.Advance<GCVisitedFlag::VISITED>()) {
|
||||
for (; !it.Done() && deoptBundle.empty(); it.Advance<GCVisitedFlag::DEOPT>()) {
|
||||
FrameType type = it.GetFrameType();
|
||||
switch (type) {
|
||||
case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
|
||||
|
@ -1210,10 +1210,10 @@ void EcmaContext::JoinStackPop(JSHandle<JSTaggedValue> receiver)
|
||||
}
|
||||
|
||||
std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> EcmaContext::CalCallSiteInfo(
|
||||
uintptr_t retAddr) const
|
||||
uintptr_t retAddr, bool isDeopt) const
|
||||
{
|
||||
auto loader = aotFileManager_;
|
||||
return loader->CalCallSiteInfo(retAddr);
|
||||
return loader->CalCallSiteInfo(retAddr, isDeopt);
|
||||
}
|
||||
|
||||
void EcmaContext::AddSustainingJSHandle(SustainingJSHandle *sustainingHandle)
|
||||
|
@ -608,7 +608,8 @@ public:
|
||||
return isAotEntry_;
|
||||
}
|
||||
|
||||
std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const;
|
||||
std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr,
|
||||
bool isDeopt) const;
|
||||
|
||||
void AddSustainingJSHandle(SustainingJSHandle*);
|
||||
void RemoveSustainingJSHandle(SustainingJSHandle*);
|
||||
|
@ -28,16 +28,12 @@ FrameIterator::FrameIterator(JSTaggedType *sp, const JSThread *thread) : current
|
||||
}
|
||||
}
|
||||
|
||||
int FrameIterator::ComputeDelta() const
|
||||
int FrameIterator::ComputeDelta(const Method *method) const
|
||||
{
|
||||
return fpDeltaPrevFrameSp_;
|
||||
}
|
||||
|
||||
int FrameIterator::GetCallSiteDelta(uintptr_t returnAddr) const
|
||||
{
|
||||
auto callsiteInfo = CalCallSiteInfo(returnAddr);
|
||||
int delta = std::get<2>(callsiteInfo); // 2:delta index
|
||||
return delta;
|
||||
if (method == nullptr || isJITFrame_) {
|
||||
return fpDeltaPrevFrameSp_;
|
||||
}
|
||||
return method->GetFpDelta();
|
||||
}
|
||||
|
||||
Method *FrameIterator::CheckAndGetMethod() const
|
||||
@ -126,15 +122,15 @@ AOTFileInfo::CallSiteInfo FrameIterator::TryCalCallSiteInfoFromMachineCode(uintp
|
||||
return {};
|
||||
}
|
||||
|
||||
AOTFileInfo::CallSiteInfo FrameIterator::CalCallSiteInfo(uintptr_t retAddr) const
|
||||
std::pair<AOTFileInfo::CallSiteInfo, bool> FrameIterator::CalCallSiteInfo(uintptr_t retAddr, bool isDeopt) const
|
||||
{
|
||||
auto callSiteInfo = const_cast<JSThread *>(thread_)->GetCurrentEcmaContext()->CalCallSiteInfo(retAddr);
|
||||
auto callSiteInfo = const_cast<JSThread *>(thread_)->GetCurrentEcmaContext()->CalCallSiteInfo(retAddr, isDeopt);
|
||||
if (std::get<1>(callSiteInfo) != nullptr) { // 1 : stackMapAddr
|
||||
return callSiteInfo;
|
||||
return std::make_pair(callSiteInfo, false);
|
||||
}
|
||||
// try get jit code
|
||||
callSiteInfo = TryCalCallSiteInfoFromMachineCode(retAddr);
|
||||
return callSiteInfo;
|
||||
return std::make_pair(callSiteInfo, true);
|
||||
}
|
||||
|
||||
template <GCVisitedFlag GCVisit>
|
||||
@ -146,7 +142,9 @@ void FrameIterator::Advance()
|
||||
switch (t) {
|
||||
case FrameType::OPTIMIZED_FRAME : {
|
||||
auto frame = GetFrame<OptimizedFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
needCalCallSiteInfo = true;
|
||||
@ -156,7 +154,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::OPTIMIZED_ENTRY_FRAME : {
|
||||
auto frame = GetFrame<OptimizedEntryFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedReturnAddr_ = 0;
|
||||
optimizedCallSiteSp_ = 0;
|
||||
}
|
||||
@ -165,7 +165,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::BASELINE_BUILTIN_FRAME: {
|
||||
auto frame = GetFrame<BaselineBuiltinFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedCallSiteSp_ = 0;
|
||||
optimizedReturnAddr_ = 0;
|
||||
}
|
||||
@ -174,7 +176,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::ASM_BRIDGE_FRAME : {
|
||||
auto frame = GetFrame<AsmBridgeFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
needCalCallSiteInfo = true;
|
||||
@ -184,7 +188,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: {
|
||||
auto frame = GetFrame<OptimizedJSFunctionUnfoldArgVFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedCallSiteSp_ = frame->GetPrevFrameSp();
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
needCalCallSiteInfo = true;
|
||||
@ -194,7 +200,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME: {
|
||||
auto frame = GetFrame<OptimizedJSFunctionFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
needCalCallSiteInfo = true;
|
||||
@ -205,7 +213,9 @@ void FrameIterator::Advance()
|
||||
case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
|
||||
case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
|
||||
auto frame = GetFrame<OptimizedJSFunctionFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
needCalCallSiteInfo = true;
|
||||
@ -215,7 +225,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::LEAVE_FRAME : {
|
||||
auto frame = GetFrame<OptimizedLeaveFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
needCalCallSiteInfo = true;
|
||||
@ -225,7 +237,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::LEAVE_FRAME_WITH_ARGV : {
|
||||
auto frame = GetFrame<OptimizedWithArgvLeaveFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
needCalCallSiteInfo = true;
|
||||
@ -235,7 +249,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::BUILTIN_CALL_LEAVE_FRAME : {
|
||||
auto frame = GetFrame<OptimizedBuiltinLeaveFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
needCalCallSiteInfo = true;
|
||||
@ -246,7 +262,9 @@ void FrameIterator::Advance()
|
||||
case FrameType::INTERPRETER_FRAME:
|
||||
case FrameType::INTERPRETER_FAST_NEW_FRAME : {
|
||||
auto frame = GetFrame<InterpretedFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedReturnAddr_ = 0;
|
||||
optimizedCallSiteSp_ = 0;
|
||||
}
|
||||
@ -255,7 +273,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::INTERPRETER_BUILTIN_FRAME: {
|
||||
auto frame = GetFrame<InterpretedBuiltinFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedReturnAddr_ = 0;
|
||||
optimizedCallSiteSp_ = 0;
|
||||
}
|
||||
@ -265,7 +285,9 @@ void FrameIterator::Advance()
|
||||
case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
|
||||
case FrameType::ASM_INTERPRETER_FRAME : {
|
||||
auto frame = GetFrame<AsmInterpretedFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedReturnAddr_ = 0;
|
||||
optimizedCallSiteSp_ = 0;
|
||||
}
|
||||
@ -274,7 +296,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::BUILTIN_FRAME : {
|
||||
auto frame = GetFrame<BuiltinFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
needCalCallSiteInfo = true;
|
||||
@ -284,7 +308,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::BUILTIN_ENTRY_FRAME : {
|
||||
auto frame = GetFrame<BuiltinFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
needCalCallSiteInfo = false;
|
||||
@ -294,7 +320,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::BUILTIN_FRAME_WITH_ARGV : {
|
||||
auto frame = GetFrame<BuiltinWithArgvFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
needCalCallSiteInfo = true;
|
||||
@ -304,7 +332,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME : {
|
||||
auto frame = GetFrame<BuiltinWithArgvFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
needCalCallSiteInfo = true;
|
||||
@ -314,7 +344,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::INTERPRETER_ENTRY_FRAME : {
|
||||
auto frame = GetFrame<InterpretedEntryFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedReturnAddr_ = 0;
|
||||
optimizedCallSiteSp_ = 0;
|
||||
}
|
||||
@ -323,7 +355,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::ASM_INTERPRETER_ENTRY_FRAME : {
|
||||
auto frame = GetFrame<AsmInterpretedEntryFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedReturnAddr_ = 0;
|
||||
optimizedCallSiteSp_ = 0;
|
||||
}
|
||||
@ -332,7 +366,9 @@ void FrameIterator::Advance()
|
||||
}
|
||||
case FrameType::ASM_INTERPRETER_BRIDGE_FRAME : {
|
||||
auto frame = GetFrame<AsmInterpretedBridgeFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
needCalCallSiteInfo = true;
|
||||
@ -343,7 +379,9 @@ void FrameIterator::Advance()
|
||||
case FrameType::FASTJIT_FUNCTION_FRAME:
|
||||
case FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME: {
|
||||
auto frame = GetFrame<FASTJITFunctionFrame>();
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
|
||||
optimizedReturnAddr_ = frame->GetReturnAddr();
|
||||
needCalCallSiteInfo = true;
|
||||
@ -360,18 +398,28 @@ void FrameIterator::Advance()
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED || GCVisit == GCVisitedFlag::HYBRID_STACK) {
|
||||
if constexpr (GCVisit == GCVisitedFlag::VISITED ||
|
||||
GCVisit == GCVisitedFlag::HYBRID_STACK ||
|
||||
GCVisit == GCVisitedFlag::DEOPT) {
|
||||
if (!needCalCallSiteInfo) {
|
||||
return;
|
||||
}
|
||||
uint64_t textStart = 0;
|
||||
std::tie(textStart, stackMapAddr_, fpDeltaPrevFrameSp_, calleeRegInfo_) = CalCallSiteInfo(optimizedReturnAddr_);
|
||||
AOTFileInfo::CallSiteInfo callSiteInfo;
|
||||
if constexpr (GCVisit == GCVisitedFlag::DEOPT) {
|
||||
std::tie(callSiteInfo, isJITFrame_) = CalCallSiteInfo(optimizedReturnAddr_, true);
|
||||
} else {
|
||||
std::tie(callSiteInfo, isJITFrame_) = CalCallSiteInfo(optimizedReturnAddr_, false);
|
||||
}
|
||||
std::tie(textStart, stackMapAddr_, fpDeltaPrevFrameSp_, calleeRegInfo_) = callSiteInfo;
|
||||
ASSERT(optimizedReturnAddr_ >= textStart);
|
||||
optimizedReturnAddr_ = optimizedReturnAddr_ - textStart;
|
||||
}
|
||||
}
|
||||
template void FrameIterator::Advance<GCVisitedFlag::VISITED>();
|
||||
template void FrameIterator::Advance<GCVisitedFlag::IGNORED>();
|
||||
template void FrameIterator::Advance<GCVisitedFlag::HYBRID_STACK>();
|
||||
template void FrameIterator::Advance<GCVisitedFlag::DEOPT>();
|
||||
|
||||
uintptr_t FrameIterator::GetPrevFrameCallSiteSp() const
|
||||
{
|
||||
@ -409,15 +457,22 @@ uintptr_t FrameIterator::GetPrevFrameCallSiteSp() const
|
||||
return frame->GetCallSiteSp();
|
||||
}
|
||||
case FrameType::OPTIMIZED_FRAME:
|
||||
case FrameType::BASELINE_BUILTIN_FRAME:
|
||||
case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
|
||||
case FrameType::OPTIMIZED_JS_FUNCTION_FRAME:
|
||||
case FrameType::BASELINE_BUILTIN_FRAME: // maybe we can store fpDelta somewhere else for these 2 cases
|
||||
case FrameType::FASTJIT_FUNCTION_FRAME:
|
||||
case FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME: {
|
||||
ASSERT(thread_ != nullptr);
|
||||
auto callSiteSp = reinterpret_cast<uintptr_t>(current_) + fpDeltaPrevFrameSp_;
|
||||
return callSiteSp;
|
||||
}
|
||||
case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
|
||||
case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
|
||||
ASSERT(thread_ != nullptr);
|
||||
auto method = CheckAndGetMethod();
|
||||
ASSERT(method != nullptr);
|
||||
int delta = ComputeDelta(method);
|
||||
auto callSiteSp = reinterpret_cast<uintptr_t>(current_) + delta;
|
||||
return callSiteSp;
|
||||
}
|
||||
case FrameType::ASM_BRIDGE_FRAME: {
|
||||
auto frame = GetFrame<AsmBridgeFrame>();
|
||||
return frame->GetCallSiteSp();
|
||||
@ -604,7 +659,9 @@ ARK_INLINE JSTaggedType* OptimizedJSFunctionFrame::GetArgv(const FrameIterator &
|
||||
ARK_INLINE uintptr_t* OptimizedJSFunctionFrame::ComputePrevFrameSp(const FrameIterator &it) const
|
||||
{
|
||||
const JSTaggedType *sp = it.GetSp();
|
||||
int delta = it.ComputeDelta();
|
||||
Method *method = it.CheckAndGetMethod();
|
||||
ASSERT(method != nullptr);
|
||||
int delta = it.ComputeDelta(method);
|
||||
ASSERT((delta > 0) && (delta % sizeof(uintptr_t) == 0));
|
||||
uintptr_t *preFrameSp = reinterpret_cast<uintptr_t *>(const_cast<JSTaggedType *>(sp)) + delta / sizeof(uintptr_t);
|
||||
return preFrameSp;
|
||||
|
@ -1918,15 +1918,17 @@ private:
|
||||
// dynamic callee saveregisters for arm64
|
||||
};
|
||||
|
||||
enum class GCVisitedFlag : bool {
|
||||
VISITED = true,
|
||||
IGNORED = false,
|
||||
HYBRID_STACK = true,
|
||||
enum class GCVisitedFlag : uint8_t {
|
||||
VISITED = 0,
|
||||
IGNORED,
|
||||
HYBRID_STACK,
|
||||
DEOPT,
|
||||
};
|
||||
|
||||
class FrameIterator {
|
||||
public:
|
||||
using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
|
||||
using CallSiteInfo = std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec>;
|
||||
explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr);
|
||||
FrameType GetFrameType() const
|
||||
{
|
||||
@ -1964,7 +1966,7 @@ public:
|
||||
{
|
||||
ret = calleeRegInfo_;
|
||||
}
|
||||
int ComputeDelta() const;
|
||||
int ComputeDelta(const Method *method = nullptr) const;
|
||||
template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED>
|
||||
void Advance();
|
||||
std::map<uint32_t, uint32_t> GetInlinedMethodInfo();
|
||||
@ -1987,10 +1989,8 @@ public:
|
||||
void CollectPcOffsetInfo(ConstInfo &info) const;
|
||||
void CollectMethodOffsetInfo(std::map<uint32_t, uint32_t> &info) const;
|
||||
void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const;
|
||||
std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const;
|
||||
std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> TryCalCallSiteInfoFromMachineCode(
|
||||
uintptr_t retAddr) const;
|
||||
int GetCallSiteDelta(uintptr_t retAddr) const;
|
||||
std::pair<CallSiteInfo, bool> CalCallSiteInfo(uintptr_t retAddr, bool isDeopt) const;
|
||||
CallSiteInfo TryCalCallSiteInfoFromMachineCode(uintptr_t retAddr) const;
|
||||
|
||||
Method *CheckAndGetMethod() const;
|
||||
JSTaggedValue GetFunction() const;
|
||||
@ -2059,9 +2059,12 @@ private:
|
||||
uintptr_t optimizedCallSiteSp_ {0};
|
||||
uintptr_t optimizedReturnAddr_ {0};
|
||||
uint8_t *stackMapAddr_ {nullptr};
|
||||
int fpDeltaPrevFrameSp_ {0};
|
||||
kungfu::CalleeRegAndOffsetVec calleeRegInfo_;
|
||||
|
||||
// in jit, delta on method is not set, get it from iterator
|
||||
bool isJITFrame_ {false};
|
||||
int fpDeltaPrevFrameSp_ {0};
|
||||
|
||||
// cache current machine code, it's nonmovable
|
||||
JSTaggedType machineCode_ {JSTaggedValue::VALUE_UNDEFINED};
|
||||
};
|
||||
|
@ -285,6 +285,16 @@ public:
|
||||
return DeoptTypeBits::Update(extraLiteralInfo, type);
|
||||
}
|
||||
|
||||
uint64_t SetFpDelta(uint64_t extraLitearalInfo, int32_t delta)
|
||||
{
|
||||
return FpDeltaBits::Update(extraLitearalInfo, delta);
|
||||
}
|
||||
|
||||
int32_t GetFpDelta(uint64_t extraLiteralInfo) const
|
||||
{
|
||||
return static_cast<int32_t>(FpDeltaBits::Decode(extraLiteralInfo));
|
||||
}
|
||||
|
||||
void SetDeoptType(kungfu::DeoptType type)
|
||||
{
|
||||
uint64_t extraLiteralInfo = GetExtraLiteralInfo();
|
||||
@ -368,6 +378,19 @@ public:
|
||||
return GetDeoptThreshold(extraLiteralInfo);
|
||||
}
|
||||
|
||||
void SetFpDelta(int32_t delta)
|
||||
{
|
||||
uint64_t extraLiteralInfo = GetExtraLiteralInfo();
|
||||
uint64_t newValue = SetFpDelta(extraLiteralInfo, delta);
|
||||
SetExtraLiteralInfo(newValue);
|
||||
}
|
||||
|
||||
int32_t GetFpDelta() const
|
||||
{
|
||||
uint64_t extraLiteralInfo = GetExtraLiteralInfo();
|
||||
return GetFpDelta(extraLiteralInfo);
|
||||
}
|
||||
|
||||
const void* GetNativePointer() const
|
||||
{
|
||||
return GetNativePointerOrBytecodeArray();
|
||||
@ -432,6 +455,7 @@ public:
|
||||
static constexpr size_t FUNCTION_KIND_NUM_BITS = 4;
|
||||
static constexpr size_t DEOPT_THRESHOLD_BITS = 8;
|
||||
static constexpr size_t DEOPTTYPE_NUM_BITS = 8;
|
||||
static constexpr size_t FP_DELTA_BITS = 32;
|
||||
using BuiltinIdBits = BitField<uint8_t, 0, BUILTINID_NUM_BITS>; // offset 0-7
|
||||
using FunctionKindBits = BuiltinIdBits::NextField<FunctionKind, FUNCTION_KIND_NUM_BITS>; // offset 8-11
|
||||
using DeoptCountBits = FunctionKindBits::NextField<uint8_t, DEOPT_THRESHOLD_BITS>; // offset 12-19
|
||||
@ -439,6 +463,7 @@ public:
|
||||
using IsCallNapiBit = DeoptTypeBits::NextFlag; // offset 28
|
||||
using IsJitCompiledCodeBit = IsCallNapiBit::NextFlag; // offset 29
|
||||
using IsSharedBit = IsJitCompiledCodeBit::NextFlag; // offset 30
|
||||
using FpDeltaBits = IsSharedBit::NextField<int32_t, FP_DELTA_BITS>; // offset 31-62
|
||||
|
||||
static constexpr size_t CONSTANT_POOL_OFFSET = TaggedObjectSize();
|
||||
ACCESSORS(ConstantPool, CONSTANT_POOL_OFFSET, CALL_FIELD_OFFSET)
|
||||
|
@ -1962,6 +1962,7 @@ void ObjectFactory::InitializeMethod(const MethodLiteral *methodLiteral, JSHandl
|
||||
}
|
||||
method->SetCodeEntryOrLiteral(reinterpret_cast<uintptr_t>(methodLiteral));
|
||||
method->SetConstantPool(thread_, JSTaggedValue::Undefined());
|
||||
method->SetFpDelta(0);
|
||||
}
|
||||
|
||||
JSHandle<Method> ObjectFactory::NewMethod(const MethodLiteral *methodLiteral, MemSpaceType spaceType)
|
||||
|
@ -251,6 +251,7 @@ void PatchLoader::ReplaceMethod(JSThread *thread,
|
||||
destMethod->SetNativePointerOrBytecodeArray(const_cast<void *>(srcMethodLiteral->GetNativePointer()));
|
||||
destMethod->SetConstantPool(thread, srcConstpool);
|
||||
destMethod->SetAotCodeBit(false);
|
||||
destMethod->SetFpDelta(0);
|
||||
}
|
||||
|
||||
// Iterator heap to update module in JSFunction.
|
||||
|
@ -123,19 +123,30 @@ void ArkStackMapParser::GetMethodOffsetInfo(uintptr_t callSiteAddr,
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t ArkStackMapParser::GetStackSlotAddress(const LLVMStackMapType::DwarfRegAndOffsetType info,
|
||||
uintptr_t callSiteSp,
|
||||
uintptr_t callsiteFp) const
|
||||
// this function will increase the value of 'offset'
|
||||
uintptr_t ArkStackMapParser::GetStackSlotAddress(uint8_t *stackmapAddr, uintptr_t callSiteSp, uintptr_t callsiteFp,
|
||||
uint32_t &offset) const
|
||||
{
|
||||
LLVMStackMapType::DwarfRegType regType;
|
||||
LLVMStackMapType::OffsetType offsetType;
|
||||
LLVMStackMapType::SLeb128Type regOffset;
|
||||
size_t regOffsetSize;
|
||||
[[maybe_unused]] bool isFull;
|
||||
uintptr_t address = 0;
|
||||
if (info.first == GCStackMapRegisters::SP) {
|
||||
address = callSiteSp + info.second;
|
||||
} else if (info.first == GCStackMapRegisters::FP) {
|
||||
address = callsiteFp + info.second;
|
||||
|
||||
std::tie(regOffset, regOffsetSize, isFull) =
|
||||
panda::leb128::DecodeSigned<LLVMStackMapType::SLeb128Type>(stackmapAddr + offset);
|
||||
LLVMStackMapType::DecodeRegAndOffset(regOffset, regType, offsetType);
|
||||
if (regType == GCStackMapRegisters::SP) {
|
||||
address = callSiteSp + offsetType;
|
||||
} else if (regType == GCStackMapRegisters::FP) {
|
||||
address = callsiteFp + offsetType;
|
||||
} else {
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
offset += regOffsetSize;
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
@ -149,7 +160,6 @@ bool ArkStackMapParser::IteratorStackMap(const RootVisitor& visitor,
|
||||
ArkStackMapHeader *head = reinterpret_cast<ArkStackMapHeader *>(stackmapAddr);
|
||||
ASSERT(head != nullptr);
|
||||
uint32_t callsiteNum = head->callsiteNum;
|
||||
ArkStackMap arkStackMap;
|
||||
// BuiltinsStub current only sample stub, don't have stackmap&deopt.
|
||||
if (callsiteNum == 0) {
|
||||
return false;
|
||||
@ -161,18 +171,18 @@ bool ArkStackMapParser::IteratorStackMap(const RootVisitor& visitor,
|
||||
return false;
|
||||
}
|
||||
CallsiteHeader *found = callsiteHead + mid;
|
||||
ParseArkStackMap(*found, stackmapAddr, arkStackMap);
|
||||
if (arkStackMap.size() == 0) {
|
||||
|
||||
uint32_t offset = found->stackmapOffsetInSMSec;
|
||||
uint16_t stackmapNum = found->stackmapNum;
|
||||
ASSERT(stackmapNum % GC_ENTRY_SIZE == 0);
|
||||
if (stackmapNum == 0) {
|
||||
return false;
|
||||
}
|
||||
ASSERT(callsiteFp != callSiteSp);
|
||||
std::map<uintptr_t, uintptr_t> baseSet;
|
||||
ASSERT(arkStackMap.size() % GC_ENTRY_SIZE == 0);
|
||||
for (size_t i = 0; i < arkStackMap.size(); i += GC_ENTRY_SIZE) { // GC_ENTRY_SIZE=<base, derive>
|
||||
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);
|
||||
for (size_t i = 0; i < stackmapNum; i += GC_ENTRY_SIZE) { // GC_ENTRY_SIZE=<base, derive>
|
||||
uintptr_t base = GetStackSlotAddress(stackmapAddr, callSiteSp, callsiteFp, offset);
|
||||
uintptr_t derived = GetStackSlotAddress(stackmapAddr, callSiteSp, callsiteFp, offset);
|
||||
if (*reinterpret_cast<uintptr_t *>(base) == 0) {
|
||||
base = derived;
|
||||
}
|
||||
|
@ -58,8 +58,8 @@ private:
|
||||
#ifndef NDEBUG
|
||||
void ParseArkStackMapAndDeopt(uint8_t *ptr, uint32_t length) const;
|
||||
#endif
|
||||
uintptr_t GetStackSlotAddress(const LLVMStackMapType::DwarfRegAndOffsetType info,
|
||||
uintptr_t callSiteSp, uintptr_t callsiteFp) const;
|
||||
uintptr_t GetStackSlotAddress(uint8_t *stackmapAddr, uintptr_t callSiteSp, uintptr_t callsiteFp,
|
||||
uint32_t &offset) const;
|
||||
friend class ArkStackMapBuilder;
|
||||
bool enableLog_ {false};
|
||||
};
|
||||
|
@ -136,6 +136,7 @@ group("ark_aot_ts_test") {
|
||||
"exp",
|
||||
"extends_builtins",
|
||||
"fast_call_builtins",
|
||||
"frame_iteration",
|
||||
"frame_states",
|
||||
"forin_delete_property",
|
||||
"forin_dictionary_mode",
|
||||
|
23
test/aottest/frame_iteration/BUILD.gn
Normal file
23
test/aottest/frame_iteration/BUILD.gn
Normal file
@ -0,0 +1,23 @@
|
||||
# Copyright (c) 2024 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.
|
||||
|
||||
import("//arkcompiler/ets_runtime/test/test_helper.gni")
|
||||
|
||||
host_aot_test_action("frame_iteration") {
|
||||
deps = []
|
||||
is_only_typed_path = true
|
||||
is_enable_pgo = true
|
||||
is_enable_opt_inlining = true
|
||||
is_enable_enableArkTools = true
|
||||
log_option = " --log-info=builtins"
|
||||
}
|
40
test/aottest/frame_iteration/expect_output.txt
Normal file
40
test/aottest/frame_iteration/expect_output.txt
Normal file
@ -0,0 +1,40 @@
|
||||
# Copyright (c) 2024 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.
|
||||
|
||||
true
|
||||
0
|
||||
[builtins] IterateFrameType: 9
|
||||
[builtins] IterateFrameDelta: 0
|
||||
[builtins] IterateFrameCalleeRegInfo: 0
|
||||
[builtins] IterateFrameType: 3
|
||||
[builtins] IterateFrameDelta: 0
|
||||
[builtins] IterateFrameCalleeRegInfo: 0
|
||||
[builtins] IterateFrameType: 22
|
||||
[builtins] IterateFrameDelta: 0
|
||||
[builtins] IterateFrameCalleeRegInfo: 0
|
||||
[builtins] IterateFrameType: 1
|
||||
[builtins] IterateFrameDelta: 0
|
||||
[builtins] IterateFrameCalleeRegInfo: 0
|
||||
[builtins] DeoptIterateFrameType: 9
|
||||
[builtins] DeoptIterateFrameDelta: 0
|
||||
[builtins] DeoptIterateFrameCalleeRegInfo: 0
|
||||
[builtins] DeoptIterateFrameType: 3
|
||||
[builtins] DeoptIterateFrameDelta: 16
|
||||
[builtins] DeoptIterateFrameCalleeRegInfo: 5
|
||||
[builtins] DeoptIterateFrameType: 22
|
||||
[builtins] DeoptIterateFrameDelta: 0
|
||||
[builtins] DeoptIterateFrameCalleeRegInfo: 0
|
||||
[builtins] DeoptIterateFrameType: 1
|
||||
[builtins] DeoptIterateFrameDelta: 0
|
||||
[builtins] DeoptIterateFrameCalleeRegInfo: 0
|
||||
0
|
63
test/aottest/frame_iteration/frame_iteration.ts
Normal file
63
test/aottest/frame_iteration/frame_iteration.ts
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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.
|
||||
*/
|
||||
|
||||
class Var {
|
||||
x_: number;
|
||||
constructor(x: number) {
|
||||
this.x_ = x;
|
||||
}
|
||||
|
||||
get getx() {
|
||||
return this.x_;
|
||||
}
|
||||
|
||||
set setx(x: number) {
|
||||
this.x_ = x;
|
||||
}
|
||||
}
|
||||
|
||||
let globalVar = new Var(0);
|
||||
|
||||
function func3() {
|
||||
let curVar = globalVar.getx;
|
||||
ArkTools.iterateFrame();
|
||||
globalVar.setx = curVar;
|
||||
}
|
||||
|
||||
function func2() {
|
||||
let curVar = globalVar.getx;
|
||||
globalVar.setx = 3;
|
||||
func3();
|
||||
globalVar.setx = curVar;
|
||||
}
|
||||
|
||||
function func1() {
|
||||
let curVar = globalVar.getx;
|
||||
globalVar.setx = 2;
|
||||
func2();
|
||||
globalVar.setx = curVar;
|
||||
}
|
||||
|
||||
function func0() {
|
||||
let curVar = globalVar.getx;
|
||||
globalVar.setx = 1;
|
||||
func1();
|
||||
globalVar.setx = curVar;
|
||||
}
|
||||
|
||||
print(ArkTools.isAOTCompiled(func0));
|
||||
print(globalVar.getx);
|
||||
func0();
|
||||
print(globalVar.getx);
|
46
test/aottest/frame_iteration/pgo_expect_output.txt
Normal file
46
test/aottest/frame_iteration/pgo_expect_output.txt
Normal file
@ -0,0 +1,46 @@
|
||||
# Copyright (c) 2024 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.
|
||||
|
||||
false
|
||||
0
|
||||
[builtins] IterateFrameType: 13
|
||||
[builtins] IterateFrameDelta: 0
|
||||
[builtins] IterateFrameCalleeRegInfo: 0
|
||||
[builtins] IterateFrameType: 11
|
||||
[builtins] IterateFrameDelta: 0
|
||||
[builtins] IterateFrameCalleeRegInfo: 0
|
||||
[builtins] IterateFrameType: 11
|
||||
[builtins] IterateFrameDelta: 0
|
||||
[builtins] IterateFrameCalleeRegInfo: 0
|
||||
[builtins] DeoptIterateFrameType: 13
|
||||
[builtins] DeoptIterateFrameDelta: 0
|
||||
[builtins] DeoptIterateFrameCalleeRegInfo: 0
|
||||
[builtins] DeoptIterateFrameType: 11
|
||||
[builtins] DeoptIterateFrameDelta: 0
|
||||
[builtins] DeoptIterateFrameCalleeRegInfo: 0
|
||||
[builtins] DeoptIterateFrameType: 11
|
||||
[builtins] DeoptIterateFrameDelta: 0
|
||||
[builtins] DeoptIterateFrameCalleeRegInfo: 0
|
||||
[builtins] DeoptIterateFrameType: 11
|
||||
[builtins] DeoptIterateFrameDelta: 0
|
||||
[builtins] DeoptIterateFrameCalleeRegInfo: 0
|
||||
[builtins] DeoptIterateFrameType: 11
|
||||
[builtins] DeoptIterateFrameDelta: 0
|
||||
[builtins] DeoptIterateFrameCalleeRegInfo: 0
|
||||
[builtins] DeoptIterateFrameType: 11
|
||||
[builtins] DeoptIterateFrameDelta: 0
|
||||
[builtins] DeoptIterateFrameCalleeRegInfo: 0
|
||||
[builtins] DeoptIterateFrameType: 19
|
||||
[builtins] DeoptIterateFrameDelta: 0
|
||||
[builtins] DeoptIterateFrameCalleeRegInfo: 0
|
||||
0
|
Loading…
Reference in New Issue
Block a user