diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index 015168aa6494fa..b60766b8fb9ac7 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -6084,8 +6084,18 @@ HRESULT DacDbiInterfaceImpl::GetContext(VMPTR_Thread vmThread, DT_CONTEXT * pCon // that has context available for stackwalking (SP and PC) // For example: RedirectedThreadFrame, InlinedCallFrame, DynamicHelperFrame, CLRToCOMMethodFrame Frame *frame = pThread->GetFrame(); + while (frame != NULL && frame != FRAME_TOP) { +#ifdef FEATURE_INTERPRETER + if (frame->GetFrameIdentifier() == FrameIdentifier::InterpreterFrame) + { + PTR_InterpreterFrame pInterpreterFrame = dac_cast(frame); + pInterpreterFrame->SetContextToInterpMethodContextFrame(&tmpContext); + CopyMemory(pContextBuffer, &tmpContext, sizeof(*pContextBuffer)); + return S_OK; + } +#endif // FEATURE_INTERPRETER frame->UpdateRegDisplay(&tmpRd); if (GetRegdisplaySP(&tmpRd) != 0 && GetControlPC(&tmpRd) != 0) { @@ -6097,7 +6107,7 @@ HRESULT DacDbiInterfaceImpl::GetContext(VMPTR_Thread vmThread, DT_CONTEXT * pCon // DT_CONTEXT_CONTROL already includes the frame register for X86 and ARM64 architectures #endif ; - return hr; + return S_OK; } frame = frame->Next(); } diff --git a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp index 50a8771a21a6f1..82eb4ec9f1db60 100644 --- a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp +++ b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp @@ -301,7 +301,8 @@ HRESULT DacDbiInterfaceImpl::UnwindStackWalkFrame(StackWalkHandle pSFIHandle, OU MethodDesc *pMD = pIter->m_crawl.GetFunction(); // EH.DispatchEx, EH.RhThrowEx, EH.RhThrowHwEx, ExceptionServices.InternalCalls.SfiInit, ExceptionServices.InternalCalls.SfiNext - if (pMD->GetMethodTable() == g_pEHClass || pMD->GetMethodTable() == g_pExceptionServicesInternalCallsClass) + // and System.Runtime.StackFrameIterator.* + if (pMD->GetMethodTable() == g_pEHClass || pMD->GetMethodTable() == g_pExceptionServicesInternalCallsClass || pMD->GetMethodTable() == g_pStackFrameIteratorClass) { continue; } @@ -517,6 +518,16 @@ HRESULT DacDbiInterfaceImpl::GetCountOfInternalFrames(VMPTR_Thread vmThread, OUT continue; } } + +#ifdef FEATURE_INTERPRETER + if (pFrame->GetFrameIdentifier() == FrameIdentifier::InterpreterFrame) + { + // Skip InterpreterFrame + pFrame = pFrame->Next(); + continue; + } +#endif // FEATURE_INTERPRETER + CorDebugInternalFrameType ift = GetInternalFrameType(pFrame); if (ift != STUBFRAME_NONE) { @@ -573,6 +584,16 @@ HRESULT DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread vmThread, FP_I continue; } } + +#ifdef FEATURE_INTERPRETER + if (pFrame->GetFrameIdentifier() == FrameIdentifier::InterpreterFrame) + { + // Skip InterpreterFrame + pFrame = pFrame->Next(); + continue; + } +#endif // FEATURE_INTERPRETER + // check if the internal frame is interesting frameData.stubFrame.frameType = GetInternalFrameType(pFrame); if (frameData.stubFrame.frameType != STUBFRAME_NONE) diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp index 10c649fa958f13..e68f3adc16f11f 100644 --- a/src/coreclr/interpreter/compiler.cpp +++ b/src/coreclr/interpreter/compiler.cpp @@ -319,6 +319,13 @@ InterpInst* InterpCompiler::NewIns(int opcode, int dataLen) InterpInst *ins = (InterpInst*)getAllocator(IMK_Instruction).allocateZeroed(insSize); ins->opcode = opcode; ins->ilOffset = m_currentILOffset; + if (m_isFirstInstForEmptyILStack) + { + // This is the first instruction we are emitting for this IL offset and the stack is empty, which + // implies the IL stack is empty too. + ins->flags |= INTERP_INST_FLAG_EMPTY_IL_STACK; + m_isFirstInstForEmptyILStack = false; + } m_pLastNewIns = ins; return ins; } @@ -1069,7 +1076,7 @@ int32_t* InterpCompiler::EmitCodeIns(int32_t *ip, InterpInst *ins, TArrayflags & INTERP_INST_FLAG_EMPTY_IL_STACK) ? ICorDebugInfo::STACK_EMPTY : ICorDebugInfo::SOURCE_TYPE_INVALID; m_ILToNativeMapSize++; } } @@ -8379,6 +8386,10 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo) if (ILOpcodePeeps.FindAndApplyPeep(this)) continue; + + // Empty stack at the beginning of the IL instruction implies IL stack being empty too + m_isFirstInstForEmptyILStack = (m_pStackPointer - m_pStackBase) == 0; + uint8_t opcode = *m_ip; switch (opcode) { diff --git a/src/coreclr/interpreter/compiler.h b/src/coreclr/interpreter/compiler.h index 6f58d0c065cf40..33ef656ffe5f5a 100644 --- a/src/coreclr/interpreter/compiler.h +++ b/src/coreclr/interpreter/compiler.h @@ -233,7 +233,9 @@ enum InterpInstFlags { INTERP_INST_FLAG_CALL = 0x01, // Flag used internally by the var offset allocator - INTERP_INST_FLAG_ACTIVE_CALL = 0x02 + INTERP_INST_FLAG_ACTIVE_CALL = 0x02, + // The IL stack is empty at this instruction + INTERP_INST_FLAG_EMPTY_IL_STACK = 0x04 }; struct InterpInst @@ -670,6 +672,9 @@ class InterpCompiler int32_t m_currentILOffset; InterpInst* m_pInitLocalsIns; + // Indicates that we are going to generate the first interpreter byte code instruction for an IL opcode with an empty stack. + bool m_isFirstInstForEmptyILStack = true; + // If the method has a hidden argument, GenerateCode allocates a var to store it and // populates the var at method entry int32_t m_hiddenArgumentVar; @@ -819,7 +824,7 @@ class InterpCompiler private: // Instructions InterpBasicBlock *m_pCBB, *m_pEntryBB; - InterpInst* m_pLastNewIns; + InterpInst* m_pLastNewIns = nullptr; int32_t GetInsLength(InterpInst *pIns); bool InsIsNop(InterpInst *pIns); diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index 6b9d52189dac84..fb8a9fef5b0171 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -3188,7 +3188,7 @@ void CallCatchFunclet(OBJECTREF throwable, BYTE* pHandlerIP, REGDISPLAY* pvRegDi pThread->GetExceptionState()->GetDebuggerState()->GetDebuggerInterceptInfo(&pInterceptMD, NULL, (PBYTE*)&(sfInterceptStackFrame.SP), &ulRelOffset, NULL); if (sfInterceptStackFrame.SP == GetSP(pvRegDisplay->pCurrentContext)) { - PCODE pStartAddress = pInterceptMD->GetNativeCode(); + PCODE pStartAddress = pInterceptMD->GetCodeForInterpreterOrJitted(); EECodeInfo codeInfo(pStartAddress); _ASSERTE(codeInfo.IsValid()); @@ -3226,7 +3226,9 @@ void CallCatchFunclet(OBJECTREF throwable, BYTE* pHandlerIP, REGDISPLAY* pvRegDi { if (fIntercepted) { - ClrRestoreNonvolatileContext(pvRegDisplay->pCurrentContext, targetSSP); + EECodeInfo codeInfo(GetIP(pvRegDisplay->pCurrentContext)); + _ASSERTE(codeInfo.IsValid()); + codeInfo.GetCodeManager()->ResumeAfterCatch(pvRegDisplay->pCurrentContext, targetSSP, /* fIntercepted */ true); } #ifdef HOST_UNIX if (propagateExceptionCallback) @@ -3325,7 +3327,7 @@ void ResumeAtInterceptionLocation(REGDISPLAY* pvRegDisplay) ExInfo::PopExInfos(pThread, (void*)targetSp); - PCODE pStartAddress = pInterceptMD->GetNativeCode(); + PCODE pStartAddress = pInterceptMD->GetCodeForInterpreterOrJitted(); EECodeInfo codeInfo(pStartAddress); _ASSERTE(codeInfo.IsValid()); @@ -3338,7 +3340,7 @@ void ResumeAtInterceptionLocation(REGDISPLAY* pvRegDisplay) SetIP(pvRegDisplay->pCurrentContext, uResumePC); STRESS_LOG2(LF_EH, LL_INFO100, "Resuming at interception location at IP=%p, SP=%p\n", uResumePC, GetSP(pvRegDisplay->pCurrentContext)); - ClrRestoreNonvolatileContext(pvRegDisplay->pCurrentContext, targetSSP); + codeInfo.GetCodeManager()->ResumeAfterCatch(pvRegDisplay->pCurrentContext, targetSSP, /* fIntercepted */ true); } void CallFinallyFunclet(BYTE* pHandlerIP, REGDISPLAY* pvRegDisplay, ExInfo* exInfo) diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index 6c60cc14fa94bd..55072025229b0f 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -2560,6 +2560,12 @@ class InterpreterFrame : public FramedMethodFrame m_isFaulting = isFaulting; } + Interception GetInterception_Impl() + { + LIMITED_METHOD_DAC_CONTRACT; + return m_isFaulting ? INTERCEPTION_EXCEPTION : INTERCEPTION_NONE; + } + void GcScanRoots_Impl(promote_func *fn, ScanContext* sc) { fn(dac_cast(dac_cast(&m_continuation)), sc, 0);