diff --git a/ecmascript/deoptimizer/deoptimizer.cpp b/ecmascript/deoptimizer/deoptimizer.cpp index c9de821f1a3002d926458672e97ceebbae7eb055..fa754de32e461ce2da691cec08d9105cf58c6c13 100644 --- a/ecmascript/deoptimizer/deoptimizer.cpp +++ b/ecmascript/deoptimizer/deoptimizer.cpp @@ -311,6 +311,7 @@ void Deoptimizier::AssistCollectDeoptBundleVec(FrameIterator &it, T &frame) void Deoptimizier::CollectDeoptBundleVec(std::vector& deoptBundle) { + JSTaggedValue jsFunction = JSTaggedValue::Undefined(); JSTaggedType *lastLeave = const_cast(thread_->GetLastLeaveFrame()); FrameIterator it(lastLeave, thread_); // note: last deopt bridge frame is generated by DeoptHandlerAsm, callee Regs is grow from this frame @@ -322,6 +323,7 @@ void Deoptimizier::CollectDeoptBundleVec(std::vector& deoptBundle) auto frame = it.GetFrame(); frame->GetDeoptBundleInfo(it, deoptBundle); AssistCollectDeoptBundleVec(it, frame); + jsFunction = it.GetFunction(); break; } case FrameType::FASTJIT_FUNCTION_FRAME: @@ -329,6 +331,7 @@ void Deoptimizier::CollectDeoptBundleVec(std::vector& deoptBundle) auto frame = it.GetFrame(); frame->GetDeoptBundleInfo(it, deoptBundle); AssistCollectDeoptBundleVec(it, frame); + jsFunction = it.GetFunction(); break; } case FrameType::ASM_BRIDGE_FRAME: { @@ -349,6 +352,28 @@ void Deoptimizier::CollectDeoptBundleVec(std::vector& deoptBundle) } } ASSERT(!it.Done()); + isRecursiveCall_ = IsRecursiveCall(it, jsFunction); +} + +bool Deoptimizier::IsRecursiveCall(FrameIterator& it, JSTaggedValue& jsFunction) +{ + if (jsFunction.IsUndefined()) { + return false; + } + for (it.Advance(); !it.Done(); it.Advance()) { + switch (it.GetFrameType()) { + case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME: + case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: { + if (it.GetFunction() == jsFunction) { + return true; + } + } + default: { + break; + } + } + } + return false; } Method* Deoptimizier::GetMethod(JSTaggedValue &target) @@ -615,7 +640,7 @@ void Deoptimizier::ResetJitHotness(JSThread *thread, JSFunction *jsFunc) // static void Deoptimizier::ClearCompiledCodeStatusWhenDeopt(JSThread *thread, JSFunction *func, - Method *method, kungfu::DeoptType type) + Method *method, kungfu::DeoptType type, bool clearMachineCode) { method->SetDeoptType(type); if (func->GetMachineCode(thread).IsMachineCodeObject()) { @@ -629,8 +654,10 @@ void Deoptimizier::ClearCompiledCodeStatusWhenDeopt(JSThread *thread, JSFunction func->SetCodeEntry(entry); method->ClearAOTStatusWhenDeopt(entry); func->ClearCompiledCodeFlags(); - ResetJitHotness(thread, func); - func->ClearMachineCode(thread); + if (clearMachineCode) { + ResetJitHotness(thread, func); + func->ClearMachineCode(thread); + } } // Do not change the func code entry if the method is not aot or deopt has happened already } @@ -657,7 +684,7 @@ void Deoptimizier::UpdateAndDumpDeoptInfo(kungfu::DeoptType type) method->SetDeoptType(type); method->SetDeoptThreshold(--deoptThreshold); } else { - ClearCompiledCodeStatusWhenDeopt(thread_, func, method, type); + ClearCompiledCodeStatusWhenDeopt(thread_, func, method, type, !isRecursiveCall_); } } } diff --git a/ecmascript/deoptimizer/deoptimizer.h b/ecmascript/deoptimizer/deoptimizer.h index ce47d3d82c91d929919deb316c13ec73436d8b4f..3311ffde0ce8df27f69bcb6f7004719a0652bf3c 100644 --- a/ecmascript/deoptimizer/deoptimizer.h +++ b/ecmascript/deoptimizer/deoptimizer.h @@ -137,6 +137,7 @@ public: template void AssistCollectDeoptBundleVec(FrameIterator &it, T &frame); void CollectDeoptBundleVec(std::vector& deoptBundle); + bool IsRecursiveCall(FrameIterator& it, JSTaggedValue& jsFunction); JSTaggedType ConstructAsmInterpretFrame(JSHandle maybeAcc); void UpdateAndDumpDeoptInfo(kungfu::DeoptType type); static PUBLIC_API std::string DisplayItems(kungfu::DeoptType type); @@ -146,7 +147,7 @@ public: static size_t DecodeDeoptDepth(OffsetType id, size_t shift); static size_t GetInlineDepth(JSThread *thread); static void ClearCompiledCodeStatusWhenDeopt(JSThread *thread, JSFunction *fun, - Method *method, kungfu::DeoptType type); + Method *method, kungfu::DeoptType type, bool clearMachineCode); static void ReplaceReturnAddrWithLazyDeoptTrampline(JSThread *thread, uintptr_t *returnAddraddress, FrameType *prevFrameTypeAddress, uintptr_t prevFrameCallSiteSp); static void PrepareForLazyDeopt(JSThread *thread); @@ -217,7 +218,8 @@ private: bool traceDeopt_{false}; size_t inlineDepth_ {0}; uint32_t type_ {static_cast(DeoptType::NONE)}; + bool isRecursiveCall_ {false}; }; } // namespace panda::ecmascript -#endif // ECMASCRIPT_DEOPTIMIZER_DEOPTIMIZER_H \ No newline at end of file +#endif // ECMASCRIPT_DEOPTIMIZER_DEOPTIMIZER_H diff --git a/ecmascript/dependent_infos.cpp b/ecmascript/dependent_infos.cpp index e2528d55f39d8fe509dd40dcb8c12860d7416c02..8e1cf0a77cbb8243560fdebe7ec3c29af5ff86a8 100644 --- a/ecmascript/dependent_infos.cpp +++ b/ecmascript/dependent_infos.cpp @@ -89,7 +89,8 @@ void DependentInfos::TriggerLazyDeoptimization(JSHandle dependen Deoptimizier::ClearCompiledCodeStatusWhenDeopt(thread, func.GetObject(), method.GetObject(), - kungfu::DeoptType::LAZYDEOPT); + kungfu::DeoptType::LAZYDEOPT, + true); TraceLazyDeoptReason(thread, func, (depCollection & collection)); } } diff --git a/ecmascript/stackmap/ark_stackmap_parser.cpp b/ecmascript/stackmap/ark_stackmap_parser.cpp index 7da1e7798b97d5e6fed35a8771a5c6adeac2c61d..23b1732586f914f3166e639092ebe929d74fb470 100644 --- a/ecmascript/stackmap/ark_stackmap_parser.cpp +++ b/ecmascript/stackmap/ark_stackmap_parser.cpp @@ -30,6 +30,9 @@ void ArkStackMapParser::ParseArkDeopt(const CallsiteHeader& callsiteHead, LLVMStackMapType::DwarfRegType reg; LLVMStackMapType::OffsetType offsetType; ASSERT(deoptNum % DEOPT_ENTRY_SIZE == 0); // 2: + if (deoptNum == 0) { + LOG_ECMA(INFO) << "deoptNum is 0"; + } for (uint32_t j = 0; j < deoptNum; j += DEOPT_ENTRY_SIZE) { // DEOPT_ENTRY_SIZE: auto [vregsInfo, vregsInfoSize, InfoIsFull] = panda::leb128::DecodeSigned(ptr + deoptOffset); @@ -94,6 +97,7 @@ void ArkStackMapParser::GetArkDeopt(uintptr_t callSiteAddr, ArkStackMapHeader *head = reinterpret_cast(stackmapAddr); ASSERT(head != nullptr); if (head == nullptr) { + LOG_ECMA(INFO) << "stack map addr is null"; return; } uint32_t callsiteNum = head->callsiteNum; @@ -102,6 +106,7 @@ void ArkStackMapParser::GetArkDeopt(uintptr_t callSiteAddr, int mid = BinaraySearch(callsiteHead, callsiteNum, callSiteAddr); ASSERT(mid != -1); if (mid == -1) { + LOG_ECMA(INFO) << "can't find callSiteAddr"; return; } CallsiteHeader *found = callsiteHead + mid; @@ -430,4 +435,4 @@ void ArkStackMapParser::ParseArkStackMapAndDeopt(uint8_t *ptr, uint32_t length) } } #endif -} // namespace panda::ecmascript::kungfu \ No newline at end of file +} // namespace panda::ecmascript::kungfu