diff --git a/src/coreclr/vm/threadsuspend.cpp b/src/coreclr/vm/threadsuspend.cpp index a060c121cb6874..671572fa1d6884 100644 --- a/src/coreclr/vm/threadsuspend.cpp +++ b/src/coreclr/vm/threadsuspend.cpp @@ -20,6 +20,8 @@ #include "exinfo.h" #endif +bool IsCallDescrWorkerInternalReturnAddress(PCODE pCode); + #define HIJACK_NONINTERRUPTIBLE_THREADS bool ThreadSuspend::s_fSuspendRuntimeInProgress = false; @@ -4597,6 +4599,19 @@ void Thread::HijackThread(ExecutionState *esb X86_ARG(ReturnKind returnKind) X86 // Remember the place that the return would have gone m_pvHJRetAddr = *esb->m_ppvRetAddrPtr; +#ifndef TARGET_X86 + // Except for x86, no registers are scanned as part of the HijackFrame on top of the stack. + // This still allows scanning of the return value because the registers in question are + // scanned as part of the calling method's roots. The problem arises if we are returning to + // CallDescrWorkerInternal, which is hand written assembly with no GC info, so a returned + // objectref would be neither reported nor updated by a GC. + if (IsCallDescrWorkerInternalReturnAddress((PCODE)(TADDR)m_pvHJRetAddr)) + { + STRESS_LOG2(LF_SYNC, LL_INFO100, "Thread::HijackThread(%p): Early out - return address %p is CallDescrWorkerInternal.\n", this, m_pvHJRetAddr); + return; + } +#endif // !TARGET_X86 + IS_VALID_CODE_PTR((FARPROC) (TADDR)m_pvHJRetAddr); // TODO [DAVBR]: For the full fix for VsWhidbey 450273, the below // may be uncommented once isLegalManagedCodeCaller works properly