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:
xing-yunhao 2024-08-14 14:54:59 +08:00
parent d037008cee
commit 3eaf375b72
25 changed files with 465 additions and 111 deletions

View File

@ -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

View File

@ -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()
{

View File

@ -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;
}

View File

@ -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);

View File

@ -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_);

View File

@ -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_ {};

View File

@ -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

View File

@ -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

View File

@ -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_;
}

View File

@ -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);

View File

@ -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:

View File

@ -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)

View File

@ -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*);

View File

@ -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;

View File

@ -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};
};

View File

@ -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)

View File

@ -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)

View File

@ -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.

View File

@ -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;
}

View File

@ -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};
};

View File

@ -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",

View 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"
}

View 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

View 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);

View 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