From 01da3bdd734c887856f89037cd4a3f2b5a072967 Mon Sep 17 00:00:00 2001 From: Koundinya Veluri Date: Wed, 3 Jul 2019 16:22:31 -0700 Subject: Fix GCStress modes that do code instrumentation to work with code versioning (#25261) - SOS changes are in https://github.com/dotnet/diagnostics/pull/369 - Fixes https://github.com/dotnet/coreclr/issues/17646 --- src/vm/codeman.cpp | 15 ++++++++++ src/vm/codeman.h | 4 +++ src/vm/codeversion.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++++-- src/vm/codeversion.h | 33 ++++++++++++++++++++-- src/vm/gccover.cpp | 69 ++++++++++++++++++++++------------------------ src/vm/gccover.h | 3 +- src/vm/jitinterface.cpp | 24 ++++++++++++++++ src/vm/jitinterface.h | 4 +-- src/vm/prestub.cpp | 2 +- src/vm/threads.h | 3 +- 10 files changed, 182 insertions(+), 48 deletions(-) (limited to 'src/vm') diff --git a/src/vm/codeman.cpp b/src/vm/codeman.cpp index 059690631e..a7fa9d9cad 100644 --- a/src/vm/codeman.cpp +++ b/src/vm/codeman.cpp @@ -4206,6 +4206,21 @@ PCODE ExecutionManager::GetCodeStartAddress(PCODE currentPC) return PINSTRToPCODE(codeInfo.GetStartAddress()); } +//************************************************************************** +NativeCodeVersion ExecutionManager::GetNativeCodeVersion(PCODE currentPC) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + FORBID_FAULT; + } + CONTRACTL_END; + + EECodeInfo codeInfo(currentPC); + return codeInfo.IsValid() ? codeInfo.GetNativeCodeVersion() : NativeCodeVersion(); +} + //************************************************************************** MethodDesc * ExecutionManager::GetCodeMethodDesc(PCODE currentPC) { diff --git a/src/vm/codeman.h b/src/vm/codeman.h index 1dc8d8f1ad..a4ad3ffe8b 100644 --- a/src/vm/codeman.h +++ b/src/vm/codeman.h @@ -1251,6 +1251,8 @@ public: // Returns method's start address for a given PC static PCODE GetCodeStartAddress(PCODE currentPC); + static NativeCodeVersion GetNativeCodeVersion(PCODE currentPC); + // Returns methodDesc for given PC static MethodDesc * GetCodeMethodDesc(PCODE currentPC); @@ -1805,6 +1807,8 @@ public: return PCODEToPINSTR(m_codeAddress); } + NativeCodeVersion GetNativeCodeVersion(); + MethodDesc * GetMethodDesc() { LIMITED_METHOD_DAC_CONTRACT; diff --git a/src/vm/codeversion.cpp b/src/vm/codeversion.cpp index c90189be1e..eb5f15f245 100644 --- a/src/vm/codeversion.cpp +++ b/src/vm/codeversion.cpp @@ -25,17 +25,29 @@ // versioning information // +NativeCodeVersion::NativeCodeVersion() : m_pMethodDesc(PTR_NULL) {}; NativeCodeVersion::NativeCodeVersion(const NativeCodeVersion & rhs) : m_pMethodDesc(rhs.m_pMethodDesc) {} NativeCodeVersion::NativeCodeVersion(PTR_MethodDesc pMethod) : m_pMethodDesc(pMethod) {} BOOL NativeCodeVersion::IsNull() const { return m_pMethodDesc == NULL; } PTR_MethodDesc NativeCodeVersion::GetMethodDesc() const { return m_pMethodDesc; } -PCODE NativeCodeVersion::GetNativeCode() const { return m_pMethodDesc->GetNativeCode(); } NativeCodeVersionId NativeCodeVersion::GetVersionId() const { return 0; } -// ReJITID NativeCodeVersion::GetILCodeVersionId() const; { return 0; } -// ILCodeVersion NativeCodeVersion::GetILCodeVersion() const { return ILCodeVersion(m_pMethodDesc); } +BOOL NativeCodeVersion::IsDefaultVersion() const { return TRUE; } +PCODE NativeCodeVersion::GetNativeCode() const { return m_pMethodDesc->GetNativeCode(); } + #ifndef DACCESS_COMPILE BOOL NativeCodeVersion::SetNativeCodeInterlocked(PCODE pCode, PCODE pExpected) { return m_pMethodDesc->SetNativeCodeInterlocked(pCode, pExpected); } #endif + +#ifdef HAVE_GCCOVER +PTR_GCCoverageInfo NativeCodeVersion::GetGCCoverageInfo() const { return GetMethodDesc()->m_GcCover; } +void NativeCodeVersion::SetGCCoverageInfo(PTR_GCCoverageInfo gcCover) +{ + MethodDesc *pMD = GetMethodDesc(); + _ASSERTE(gcCover == NULL || pMD->m_GcCover == NULL); + *EnsureWritablePages(&pMD->m_GcCover) = gcCover; +} +#endif + bool NativeCodeVersion::operator==(const NativeCodeVersion & rhs) const { return m_pMethodDesc == rhs.m_pMethodDesc; } bool NativeCodeVersion::operator!=(const NativeCodeVersion & rhs) const { return !operator==(rhs); } @@ -63,6 +75,9 @@ NativeCodeVersionNode::NativeCodeVersionNode( m_id(id), #ifdef FEATURE_TIERED_COMPILATION m_optTier(optimizationTier), +#endif +#ifdef HAVE_GCCOVER + m_gcCover(PTR_NULL), #endif m_flags(0) {} @@ -166,6 +181,24 @@ void NativeCodeVersionNode::SetOptimizationTier(NativeCodeVersion::OptimizationT #endif // FEATURE_TIERED_COMPILATION +#ifdef HAVE_GCCOVER + +PTR_GCCoverageInfo NativeCodeVersionNode::GetGCCoverageInfo() const +{ + LIMITED_METHOD_CONTRACT; + return m_gcCover; +} + +void NativeCodeVersionNode::SetGCCoverageInfo(PTR_GCCoverageInfo gcCover) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE(gcCover == NULL || m_gcCover == NULL); + + m_gcCover = gcCover; +} + +#endif // HAVE_GCCOVER + NativeCodeVersion::NativeCodeVersion() : m_storageKind(StorageKind::Unknown) {} @@ -371,6 +404,40 @@ void NativeCodeVersion::SetOptimizationTier(OptimizationTier tier) #endif +#ifdef HAVE_GCCOVER + +PTR_GCCoverageInfo NativeCodeVersion::GetGCCoverageInfo() const +{ + WRAPPER_NO_CONTRACT; + + if (m_storageKind == StorageKind::Explicit) + { + return AsNode()->GetGCCoverageInfo(); + } + else + { + return GetMethodDesc()->m_GcCover; + } +} + +void NativeCodeVersion::SetGCCoverageInfo(PTR_GCCoverageInfo gcCover) +{ + WRAPPER_NO_CONTRACT; + + if (m_storageKind == StorageKind::Explicit) + { + AsNode()->SetGCCoverageInfo(gcCover); + } + else + { + MethodDesc *pMD = GetMethodDesc(); + _ASSERTE(gcCover == NULL || pMD->m_GcCover == NULL); + *EnsureWritablePages(&pMD->m_GcCover) = gcCover; + } +} + +#endif // HAVE_GCCOVER + PTR_NativeCodeVersionNode NativeCodeVersion::AsNode() const { LIMITED_METHOD_DAC_CONTRACT; diff --git a/src/vm/codeversion.h b/src/vm/codeversion.h index 23fb908575..898796f183 100644 --- a/src/vm/codeversion.h +++ b/src/vm/codeversion.h @@ -37,8 +37,10 @@ typedef DPTR(class CodeVersionManager) PTR_CodeVersionManager; #endif - - +#ifdef HAVE_GCCOVER +class GCCoverageInfo; +typedef DPTR(class GCCoverageInfo) PTR_GCCoverageInfo; +#endif class NativeCodeVersion { @@ -54,16 +56,22 @@ public: NativeCodeVersion(PTR_NativeCodeVersionNode pVersionNode); #endif explicit NativeCodeVersion(PTR_MethodDesc pMethod); + BOOL IsNull() const; PTR_MethodDesc GetMethodDesc() const; NativeCodeVersionId GetVersionId() const; BOOL IsDefaultVersion() const; PCODE GetNativeCode() const; + +#ifdef FEATURE_CODE_VERSIONING ILCodeVersion GetILCodeVersion() const; ReJITID GetILCodeVersionId() const; +#endif + #ifndef DACCESS_COMPILE BOOL SetNativeCodeInterlocked(PCODE pCode, PCODE pExpected = NULL); #endif + enum OptimizationTier { OptimizationTier0, @@ -76,8 +84,15 @@ public: void SetOptimizationTier(OptimizationTier tier); #endif #endif // FEATURE_TIERED_COMPILATION + +#ifdef HAVE_GCCOVER + PTR_GCCoverageInfo GetGCCoverageInfo() const; + void SetGCCoverageInfo(PTR_GCCoverageInfo gcCover); +#endif + bool operator==(const NativeCodeVersion & rhs) const; bool operator!=(const NativeCodeVersion & rhs) const; + #if defined(DACCESS_COMPILE) && defined(FEATURE_CODE_VERSIONING) // The DAC is privy to the backing node abstraction PTR_NativeCodeVersionNode AsNode() const; @@ -86,7 +101,7 @@ public: private: #ifndef FEATURE_CODE_VERSIONING - MethodDesc* m_pMethodDesc; + PTR_MethodDesc m_pMethodDesc; #else // FEATURE_CODE_VERSIONING #ifndef DACCESS_COMPILE @@ -229,13 +244,16 @@ class NativeCodeVersionNode friend NativeCodeVersionIterator; friend MethodDescVersioningState; friend ILCodeVersionNode; + public: #ifndef DACCESS_COMPILE NativeCodeVersionNode(NativeCodeVersionId id, MethodDesc* pMethod, ReJITID parentId, NativeCodeVersion::OptimizationTier optimizationTier); #endif + #ifdef DEBUG BOOL LockOwnedByCurrentThread() const; #endif + PTR_MethodDesc GetMethodDesc() const; NativeCodeVersionId GetVersionId() const; PCODE GetNativeCode() const; @@ -246,6 +264,7 @@ public: BOOL SetNativeCodeInterlocked(PCODE pCode, PCODE pExpected); void SetActiveChildFlag(BOOL isActive); #endif + #ifdef FEATURE_TIERED_COMPILATION NativeCodeVersion::OptimizationTier GetOptimizationTier() const; #ifndef DACCESS_COMPILE @@ -253,6 +272,11 @@ public: #endif #endif // FEATURE_TIERED_COMPILATION +#ifdef HAVE_GCCOVER + PTR_GCCoverageInfo GetGCCoverageInfo() const; + void SetGCCoverageInfo(PTR_GCCoverageInfo gcCover); +#endif + private: //union - could save a little memory? //{ @@ -266,6 +290,9 @@ private: #ifdef FEATURE_TIERED_COMPILATION NativeCodeVersion::OptimizationTier m_optTier; #endif +#ifdef HAVE_GCCOVER + PTR_GCCoverageInfo m_gcCover; +#endif enum NativeCodeVersionNodeFlags { diff --git a/src/vm/gccover.cpp b/src/vm/gccover.cpp index 7b8c4742f9..2ede08d823 100644 --- a/src/vm/gccover.cpp +++ b/src/vm/gccover.cpp @@ -125,13 +125,16 @@ bool IsOriginalInstruction(PBYTE instrPtr, GCCoverageInfo* gcCover, DWORD offset void SetupAndSprinkleBreakpoints( - MethodDesc * pMD, + NativeCodeVersion nativeCodeVersion, EECodeInfo * pCodeInfo, IJitManager::MethodRegionInfo methodRegionInfo, BOOL fZapped ) { + _ASSERTE(!nativeCodeVersion.IsNull()); + // Allocate room for the GCCoverageInfo and copy of the method instructions + MethodDesc *pMD = nativeCodeVersion.GetMethodDesc(); size_t memSize = sizeof(GCCoverageInfo) + methodRegionInfo.hotSize + methodRegionInfo.coldSize; GCCoverageInfo* gcCover = (GCCoverageInfo*)(void*) pMD->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocAlignedMem(memSize, CODE_SIZE_ALIGN); @@ -143,8 +146,6 @@ void SetupAndSprinkleBreakpoints( gcCover->callerThread = 0; gcCover->doingEpilogChecks = true; - gcCover->lastMD = pMD; /* pass pMD to SprinkleBreakpoints */ - gcCover->SprinkleBreakpoints(gcCover->savedCode, gcCover->methodRegion.hotStartAddress, gcCover->methodRegion.hotSize, @@ -163,16 +164,15 @@ void SetupAndSprinkleBreakpoints( } #endif - gcCover->lastMD = NULL; /* clear lastMD */ - - _ASSERTE(!pMD->m_GcCover); - *EnsureWritablePages(&pMD->m_GcCover) = gcCover; + nativeCodeVersion.SetGCCoverageInfo(gcCover); } -void SetupAndSprinkleBreakpointsForJittedMethod(MethodDesc * pMD, +void SetupAndSprinkleBreakpointsForJittedMethod(NativeCodeVersion nativeCodeVersion, PCODE codeStart ) { + _ASSERTE(!nativeCodeVersion.IsNull()); + EECodeInfo codeInfo(codeStart); _ASSERTE(codeInfo.IsValid()); _ASSERTE(codeInfo.GetRelOffset() == 0); @@ -183,9 +183,9 @@ void SetupAndSprinkleBreakpointsForJittedMethod(MethodDesc * _ASSERTE(PCODEToPINSTR(codeStart) == methodRegionInfo.hotStartAddress); #ifdef _DEBUG - if (!g_pConfig->SkipGCCoverage(pMD->GetModule()->GetSimpleName())) + if (!g_pConfig->SkipGCCoverage(nativeCodeVersion.GetMethodDesc()->GetModule()->GetSimpleName())) #endif - SetupAndSprinkleBreakpoints(pMD, + SetupAndSprinkleBreakpoints(nativeCodeVersion, &codeInfo, methodRegionInfo, FALSE @@ -195,10 +195,12 @@ void SetupAndSprinkleBreakpointsForJittedMethod(MethodDesc * /****************************************************************************/ /* called when a method is first jitted when GCStress level 4 or 8 is on */ -void SetupGcCoverage(MethodDesc* pMD, BYTE* methodStartPtr) { +void SetupGcCoverage(NativeCodeVersion nativeCodeVersion, BYTE* methodStartPtr) +{ + _ASSERTE(!nativeCodeVersion.IsNull()); #ifdef _DEBUG - if (!g_pConfig->ShouldGcCoverageOnMethod(pMD->m_pszDebugMethodName)) { + if (!g_pConfig->ShouldGcCoverageOnMethod(nativeCodeVersion.GetMethodDesc()->m_pszDebugMethodName)) { return; } #endif @@ -221,22 +223,23 @@ void SetupGcCoverage(MethodDesc* pMD, BYTE* methodStartPtr) { // code, and since the rejitted method does not get instrumented // we should be able to tolerate that the gc cover info does not // match. - if (pMD->m_GcCover) + if (nativeCodeVersion.GetGCCoverageInfo() != NULL) { return; } PCODE codeStart = (PCODE) methodStartPtr; - SetupAndSprinkleBreakpointsForJittedMethod(pMD, codeStart); + SetupAndSprinkleBreakpointsForJittedMethod(nativeCodeVersion, codeStart); } #ifdef FEATURE_PREJIT -void SetupGcCoverageForNativeMethod(MethodDesc* pMD, +void SetupGcCoverageForNativeMethod(NativeCodeVersion nativeCodeVersion, PCODE codeStart, IJitManager::MethodRegionInfo& methodRegionInfo ) { + _ASSERTE(!nativeCodeVersion.IsNull()); EECodeInfo codeInfo(codeStart); _ASSERTE(codeInfo.IsValid()); @@ -244,7 +247,7 @@ void SetupGcCoverageForNativeMethod(MethodDesc* pMD, _ASSERTE(PCODEToPINSTR(codeStart) == methodRegionInfo.hotStartAddress); - SetupAndSprinkleBreakpoints(pMD, + SetupAndSprinkleBreakpoints(nativeCodeVersion, &codeInfo, methodRegionInfo, TRUE @@ -296,7 +299,7 @@ void SetupGcCoverageForNativeImage(Module* module) IJitManager::MethodRegionInfo methodRegionInfo; mi.GetMethodRegionInfo(&methodRegionInfo); - SetupGcCoverageForNativeMethod(pMD, pMethodStart, methodRegionInfo); + SetupGcCoverageForNativeMethod(NativeCodeVersion(pMD), pMethodStart, methodRegionInfo); } } #endif @@ -1312,7 +1315,7 @@ bool IsGcCoverageInterrupt(LPVOID ip) return false; } - GCCoverageInfo *gcCover = codeInfo.GetMethodDesc()->m_GcCover; + GCCoverageInfo *gcCover = codeInfo.GetNativeCodeVersion().GetGCCoverageInfo(); if (gcCover == nullptr) { return false; @@ -1374,7 +1377,7 @@ BOOL OnGcCoverageInterrupt(PCONTEXT regs) forceStack[1] = &pMD; // This is so I can see it fastchecked forceStack[2] = &offset; // This is so I can see it fastchecked - GCCoverageInfo* gcCover = pMD->m_GcCover; + GCCoverageInfo* gcCover = codeInfo.GetNativeCodeVersion().GetGCCoverageInfo(); forceStack[3] = &gcCover; // This is so I can see it fastchecked if (gcCover == 0) return(FALSE); // we aren't doing code gcCoverage on this function @@ -1408,7 +1411,7 @@ BOOL OnGcCoverageInterrupt(PCONTEXT regs) #ifdef _DEBUG if (!g_pConfig->SkipGCCoverage(pMD->GetModule()->GetSimpleName())) #endif - DoGcStress(regs, pMD); + DoGcStress(regs, codeInfo.GetNativeCodeVersion()); #endif // !USE_REDIRECT_FOR_GCSTRESS @@ -1426,22 +1429,22 @@ FORCEINLINE void UpdateGCStressInstructionWithoutGC () /****************************************************************************/ -void DoGcStress (PCONTEXT regs, MethodDesc *pMD) +void DoGcStress (PCONTEXT regs, NativeCodeVersion nativeCodeVersion) { PCODE controlPc = GetIP(regs); PBYTE instrPtr = reinterpret_cast(PCODEToPINSTR(controlPc)); - if (!pMD) + if (nativeCodeVersion.IsNull()) { - pMD = ExecutionManager::GetCodeMethodDesc(controlPc); - if (!pMD) + nativeCodeVersion = ExecutionManager::GetNativeCodeVersion(controlPc); + if (nativeCodeVersion.IsNull()) return; } - GCCoverageInfo *gcCover = pMD->m_GcCover; + GCCoverageInfo *gcCover = nativeCodeVersion.GetGCCoverageInfo(); EECodeInfo codeInfo(controlPc); - _ASSERTE(codeInfo.GetMethodDesc() == pMD); + _ASSERTE(codeInfo.GetNativeCodeVersion() == nativeCodeVersion); DWORD offset = codeInfo.GetRelOffset(); Thread *pThread = GetThread(); @@ -1769,17 +1772,9 @@ void DoGcStress (PCONTEXT regs, MethodDesc *pMD) gcFrame.Init(pThread, (OBJECTREF*)retValRegs, numberOfRegs, TRUE); } - if (gcCover->lastMD != pMD) - { - LOG((LF_GCROOTS, LL_INFO100000, "GCCOVER: Doing GC at method %s::%s offset 0x%x\n", - pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, offset)); - gcCover->lastMD =pMD; - } - else - { - LOG((LF_GCROOTS, LL_EVERYTHING, "GCCOVER: Doing GC at method %s::%s offset 0x%x\n", - pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, offset)); - } + MethodDesc *pMD = nativeCodeVersion.GetMethodDesc(); + LOG((LF_GCROOTS, LL_EVERYTHING, "GCCOVER: Doing GC at method %s::%s offset 0x%x\n", + pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, offset)); //------------------------------------------------------------------------- // Do the actual stress work diff --git a/src/vm/gccover.h b/src/vm/gccover.h index e560c0d28d..42b093f4ce 100644 --- a/src/vm/gccover.h +++ b/src/vm/gccover.h @@ -22,7 +22,6 @@ class GCCoverageInfo { public: IJitManager::MethodRegionInfo methodRegion; BYTE* curInstr; // The last instruction that was able to execute - MethodDesc* lastMD; // Used to quickly figure out the culprite // Following 6 variables are for prolog / epilog walking coverage ICodeManager* codeMan; // CodeMan for this method @@ -61,6 +60,8 @@ public: }; +typedef DPTR(GCCoverageInfo) PTR_GCCoverageInfo; // see code:GCCoverageInfo::savedCode + #ifdef _MSC_VER #pragma warning(pop) #endif // _MSC_VER diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index 884257b6a4..e667ddd0a6 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -14263,6 +14263,30 @@ TADDR EECodeInfo::GetStartAddress() return m_pJM->JitTokenToStartAddress(m_methodToken); } +NativeCodeVersion EECodeInfo::GetNativeCodeVersion() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + PTR_MethodDesc pMD = PTR_MethodDesc(GetMethodDesc()); + if (pMD == NULL) + { + return NativeCodeVersion(); + } + +#ifdef FEATURE_CODE_VERSIONING + CodeVersionManager *pCodeVersionManager = pMD->GetCodeVersionManager(); + CodeVersionManager::TableLockHolder lockHolder(pCodeVersionManager); + return pCodeVersionManager->GetNativeCodeVersion(pMD, PINSTRToPCODE(GetStartAddress())); +#else + return NativeCodeVersion(pMD); +#endif +} + #if defined(WIN64EXCEPTIONS) // ---------------------------------------------------------------------------- diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h index c5f7953596..70726b0b27 100644 --- a/src/vm/jitinterface.h +++ b/src/vm/jitinterface.h @@ -1648,10 +1648,10 @@ EXTERN_C void JIT_TailCallHelperStub_ReturnAddress(); void *GenFastGetSharedStaticBase(bool bCheckCCtor); #ifdef HAVE_GCCOVER -void SetupGcCoverage(MethodDesc* pMD, BYTE* nativeCode); +void SetupGcCoverage(NativeCodeVersion nativeCodeVersion, BYTE* nativeCode); void SetupGcCoverageForNativeImage(Module* module); BOOL OnGcCoverageInterrupt(PT_CONTEXT regs); -void DoGcStress (PT_CONTEXT regs, MethodDesc *pMD); +void DoGcStress (PT_CONTEXT regs, NativeCodeVersion nativeCodeVersion); #endif //HAVE_GCCOVER EXTERN_C FCDECL2(LPVOID, ArrayStoreCheck, Object** pElement, PtrArray** pArray); diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp index 0cbd0fc236..b76a018daf 100644 --- a/src/vm/prestub.cpp +++ b/src/vm/prestub.cpp @@ -1015,7 +1015,7 @@ PCODE MethodDesc::JitCompileCodeLocked(PrepareCodeConfig* pConfig, JitListLockEn return pOtherCode; } - SetupGcCoverage(this, (BYTE*)pCode); + SetupGcCoverage(pConfig->GetCodeVersion(), (BYTE*)pCode); // This thread should always win the publishing race // since we're under a lock. diff --git a/src/vm/threads.h b/src/vm/threads.h index c4189126d3..a5666900d8 100644 --- a/src/vm/threads.h +++ b/src/vm/threads.h @@ -168,6 +168,7 @@ class CRWLock; struct LockEntry; class PendingTypeLoadHolder; class PrepareCodeConfig; +class NativeCodeVersion; struct ThreadLocalBlock; typedef DPTR(struct ThreadLocalBlock) PTR_ThreadLocalBlock; @@ -3700,7 +3701,7 @@ private: friend class NDirect; // Quick access to thread stub creation #ifdef HAVE_GCCOVER - friend void DoGcStress (PT_CONTEXT regs, MethodDesc *pMD); // Needs to call UnhijackThread + friend void DoGcStress (PT_CONTEXT regs, NativeCodeVersion nativeCodeVersion); // Needs to call UnhijackThread #endif // HAVE_GCCOVER ULONG m_ExternalRefCount; -- cgit v1.2.3