diff options
Diffstat (limited to 'src/gc/objecthandle.cpp')
-rw-r--r-- | src/gc/objecthandle.cpp | 137 |
1 files changed, 52 insertions, 85 deletions
diff --git a/src/gc/objecthandle.cpp b/src/gc/objecthandle.cpp index 74a8a71c5e..e8eed93006 100644 --- a/src/gc/objecthandle.cpp +++ b/src/gc/objecthandle.cpp @@ -95,7 +95,7 @@ void CALLBACK PromoteRefCounted(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pExtra Object *pOldObj = pObj; #endif - if (!HndIsNullOrDestroyedHandle(pObj) && !GCHeap::GetGCHeap()->IsPromoted(pObj)) + if (!HndIsNullOrDestroyedHandle(pObj) && !g_theGCHeap->IsPromoted(pObj)) { if (GCToEEInterface::RefCountedHandleCallbacks(pObj)) { @@ -110,6 +110,21 @@ void CALLBACK PromoteRefCounted(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pExtra } #endif // FEATURE_COMINTEROP || FEATURE_REDHAWK + +// Only used by profiling/ETW. +//---------------------------------------------------------------------------- + +/* + * struct DIAG_DEPSCANINFO + * + * used when tracing dependent handles for profiling/ETW. + */ +struct DIAG_DEPSCANINFO +{ + HANDLESCANPROC pfnTrace; // tracing function to use + uintptr_t pfnProfilingOrETW; +}; + void CALLBACK TraceDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pExtraInfo, uintptr_t lp1, uintptr_t lp2) { WRAPPER_NO_CONTRACT; @@ -122,14 +137,15 @@ void CALLBACK TraceDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pEx // object should also be non-NULL. _ASSERTE(*pExtraInfo == NULL || *pObjRef != NULL); - // lp2 is a HANDLESCANPROC - HANDLESCANPROC pfnTrace = (HANDLESCANPROC) lp2; + struct DIAG_DEPSCANINFO *pInfo = (struct DIAG_DEPSCANINFO*)lp2; + + HANDLESCANPROC pfnTrace = pInfo->pfnTrace; // is the handle's secondary object non-NULL? if ((*pObjRef != NULL) && (*pExtraInfo != 0)) { // yes - call the tracing function for this handle - pfnTrace(pObjRef, NULL, lp1, *pExtraInfo); + pfnTrace(pObjRef, NULL, lp1, (uintptr_t)(pInfo->pfnProfilingOrETW)); } } @@ -186,9 +202,9 @@ void CALLBACK PromoteDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *p ScanContext *sc = (ScanContext*)lp1; DhContext *pDhContext = Ref_GetDependentHandleContext(sc); - if (*pObjRef && GCHeap::GetGCHeap()->IsPromoted(*pPrimaryRef)) + if (*pObjRef && g_theGCHeap->IsPromoted(*pPrimaryRef)) { - if (!GCHeap::GetGCHeap()->IsPromoted(*pSecondaryRef)) + if (!g_theGCHeap->IsPromoted(*pSecondaryRef)) { LOG((LF_GC|LF_ENC, LL_INFO10000, "\tPromoting secondary " LOG_OBJECT_CLASS(*pSecondaryRef))); _ASSERTE(lp2); @@ -221,7 +237,7 @@ void CALLBACK ClearDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pEx LOG((LF_GC|LF_ENC, LL_INFO1000, LOG_HANDLE_OBJECT_CLASS("\tPrimary:\t", pPrimaryRef, "to ", *pPrimaryRef))); LOG((LF_GC|LF_ENC, LL_INFO1000, LOG_HANDLE_OBJECT_CLASS("\tSecondary\t", pSecondaryRef, "to ", *pSecondaryRef))); - if (!GCHeap::GetGCHeap()->IsPromoted(*pPrimaryRef)) + if (!g_theGCHeap->IsPromoted(*pPrimaryRef)) { LOG((LF_GC|LF_ENC, LL_INFO1000, "\tunreachable ", LOG_OBJECT_CLASS(*pPrimaryRef))); LOG((LF_GC|LF_ENC, LL_INFO1000, "\tunreachable ", LOG_OBJECT_CLASS(*pSecondaryRef))); @@ -230,7 +246,7 @@ void CALLBACK ClearDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pEx } else { - _ASSERTE(GCHeap::GetGCHeap()->IsPromoted(*pSecondaryRef)); + _ASSERTE(g_theGCHeap->IsPromoted(*pSecondaryRef)); LOG((LF_GC|LF_ENC, LL_INFO10000, "\tPrimary is reachable " LOG_OBJECT_CLASS(*pPrimaryRef))); LOG((LF_GC|LF_ENC, LL_INFO10000, "\tSecondary is reachable " LOG_OBJECT_CLASS(*pSecondaryRef))); } @@ -330,7 +346,7 @@ void CALLBACK CheckPromoted(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pExtraInfo LOG((LF_GC, LL_INFO100000, LOG_HANDLE_OBJECT_CLASS("Checking referent of Weak-", pObjRef, "to ", *pObjRef))); Object **ppRef = (Object **)pObjRef; - if (!GCHeap::GetGCHeap()->IsPromoted(*ppRef)) + if (!g_theGCHeap->IsPromoted(*ppRef)) { LOG((LF_GC, LL_INFO100, LOG_HANDLE_OBJECT_CLASS("Severing Weak-", pObjRef, "to unreachable ", *pObjRef))); @@ -355,9 +371,9 @@ void CALLBACK CalculateSizedRefSize(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pE ScanContext* sc = (ScanContext *)lp1; promote_func* callback = (promote_func*) lp2; - size_t sizeBegin = GCHeap::GetGCHeap()->GetPromotedBytes(sc->thread_number); + size_t sizeBegin = g_theGCHeap->GetPromotedBytes(sc->thread_number); callback(ppSizedRef, (ScanContext *)lp1, 0); - size_t sizeEnd = GCHeap::GetGCHeap()->GetPromotedBytes(sc->thread_number); + size_t sizeEnd = g_theGCHeap->GetPromotedBytes(sc->thread_number); *pSize = sizeEnd - sizeBegin; } @@ -414,7 +430,7 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, uintpt CONTRACTL_END; #endif // FEATURE_REDHAWK UNREFERENCED_PARAMETER(pExtraInfo); - UNREFERENCED_PARAMETER(lp2); + handle_scan_fn fn = (handle_scan_fn)lp2; LOG((LF_GC | LF_CORPROF, LL_INFO100000, LOG_HANDLE_OBJECT_CLASS("Notifying profiler of ", pObjRef, "to ", *pObjRef))); @@ -422,7 +438,7 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, uintpt Object **pRef = (Object **)pObjRef; // Get a hold of the heap ID that's tacked onto the end of the scancontext struct. - ProfilingScanContext *pSC = (ProfilingScanContext *)lp1; + ScanContext *pSC = (ScanContext *)lp1; uint32_t rootFlags = 0; BOOL isDependent = FALSE; @@ -487,60 +503,15 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, uintpt _UNCHECKED_OBJECTREF pSec = NULL; -#ifdef GC_PROFILING - // Give the profiler the objectref. - if (pSC->fProfilerPinned) + if (isDependent) { - if (!isDependent) - { - BEGIN_PIN_PROFILER(CORProfilerTrackGC()); - g_profControlBlock.pProfInterface->RootReference2( - (uint8_t *)*pRef, - kEtwGCRootKindHandle, - (EtwGCRootFlags)rootFlags, - pRef, - &pSC->pHeapId); - END_PIN_PROFILER(); - } - else - { - BEGIN_PIN_PROFILER(CORProfilerTrackConditionalWeakTableElements()); - pSec = (_UNCHECKED_OBJECTREF)HndGetHandleExtraInfo(handle); - g_profControlBlock.pProfInterface->ConditionalWeakTableElementReference( - (uint8_t*)*pRef, - (uint8_t*)pSec, - pRef, - &pSC->pHeapId); - END_PIN_PROFILER(); - } + pSec = (_UNCHECKED_OBJECTREF)HndGetHandleExtraInfo(handle); } -#endif // GC_PROFILING - -#if defined(FEATURE_EVENT_TRACE) - // Notify ETW of the handle - if (ETW::GCLog::ShouldWalkHeapRootsForEtw()) - { - if (isDependent && (pSec == NULL)) - { - pSec = (_UNCHECKED_OBJECTREF)HndGetHandleExtraInfo(handle); - } - - ETW::GCLog::RootReference( - handle, - *pRef, // object being rooted - pSec, // pSecondaryNodeForDependentHandle - isDependent, - pSC, - 0, // dwGCFlags, - rootFlags); // ETW handle flags - } -#endif // defined(FEATURE_EVENT_TRACE) + fn(pRef, pSec, rootFlags, pSC, isDependent); } #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - - /* * Scan callback for updating pointers. * @@ -583,10 +554,10 @@ int getNumberOfSlots() { WRAPPER_NO_CONTRACT; - // when Ref_Initialize called, GCHeap::GetNumberOfHeaps() is still 0, so use #procs as a workaround + // when Ref_Initialize called, IGCHeap::GetNumberOfHeaps() is still 0, so use #procs as a workaround // it is legal since even if later #heaps < #procs we create handles by thread home heap // and just have extra unused slots in HandleTableBuckets, which does not take a lot of space - if (!GCHeap::IsServerHeap()) + if (!IsServerHeap()) return 1; #ifdef FEATURE_REDHAWK @@ -874,7 +845,7 @@ int getSlotNumber(ScanContext* sc) { WRAPPER_NO_CONTRACT; - return (GCHeap::IsServerHeap() ? sc->thread_number : 0); + return (IsServerHeap() ? sc->thread_number : 0); } // <TODO> - reexpress as complete only like hndtable does now!!! -fmh</REVISIT_TODO> @@ -1152,7 +1123,7 @@ void Ref_TraceNormalRoots(uint32_t condemned, uint32_t maxgen, ScanContext* sc, // promote objects pointed to by strong handles // during ephemeral GCs we also want to promote the ones pointed to by sizedref handles. uint32_t types[2] = {HNDTYPE_STRONG, HNDTYPE_SIZEDREF}; - uint32_t uTypeCount = (((condemned >= maxgen) && !GCHeap::GetGCHeap()->IsConcurrentGCInProgress()) ? 1 : _countof(types)); + uint32_t uTypeCount = (((condemned >= maxgen) && !g_theGCHeap->IsConcurrentGCInProgress()) ? 1 : _countof(types)); uint32_t flags = (sc->concurrent) ? HNDGCF_ASYNC : HNDGCF_NORMAL; HandleTableMap *walk = &g_HandleTableMap; @@ -1417,13 +1388,15 @@ void Ref_ScanDependentHandlesForRelocation(uint32_t condemned, uint32_t maxgen, /* loop scan version of TraceVariableHandles for single-thread-managed Ref_* functions should be kept in sync with the code above + Only used by profiling/ETW. */ -void TraceDependentHandlesBySingleThread(HANDLESCANPROC pfnTrace, uintptr_t lp1, uint32_t condemned, uint32_t maxgen, uint32_t flags) +void TraceDependentHandlesBySingleThread(HANDLESCANPROC pfnTrace, uintptr_t lp1, uintptr_t lp2, uint32_t condemned, uint32_t maxgen, uint32_t flags) { WRAPPER_NO_CONTRACT; // set up to scan variable handles with the specified mask and trace function uint32_t type = HNDTYPE_DEPENDENT; + struct DIAG_DEPSCANINFO info = { pfnTrace, lp2 }; HandleTableMap *walk = &g_HandleTableMap; while (walk) { @@ -1436,14 +1409,13 @@ void TraceDependentHandlesBySingleThread(HANDLESCANPROC pfnTrace, uintptr_t lp1, HHANDLETABLE hTable = walk->pBuckets[i]->pTable[uCPUindex]; if (hTable) HndScanHandlesForGC(hTable, TraceDependentHandle, - lp1, (uintptr_t)pfnTrace, &type, 1, condemned, maxgen, HNDGCF_EXTRAINFO | flags); + lp1, (uintptr_t)&info, &type, 1, condemned, maxgen, HNDGCF_EXTRAINFO | flags); } } walk = walk->pNext; } } - // We scan handle tables by their buckets (ie, AD index). We could get into the situation where // the AD indices are not very compacted (for example if we have just unloaded ADs and their // indices haven't been reused yet) and we could be scanning them in an unbalanced fashion. @@ -1454,7 +1426,7 @@ void ScanSizedRefByAD(uint32_t maxgen, HANDLESCANPROC scanProc, ScanContext* sc, HandleTableMap *walk = &g_HandleTableMap; uint32_t type = HNDTYPE_SIZEDREF; int uCPUindex = getSlotNumber(sc); - int n_slots = GCHeap::GetGCHeap()->GetNumberOfHeaps(); + int n_slots = g_theGCHeap->GetNumberOfHeaps(); while (walk) { @@ -1574,11 +1546,11 @@ void Ref_UpdatePointers(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Re // @TODO cwb: wait for compelling performance measurements.</REVISIT_TODO> BOOL bDo = TRUE; - if (GCHeap::IsServerHeap()) + if (IsServerHeap()) { bDo = (Interlocked::Increment(&uCount) == 1); - Interlocked::CompareExchange (&uCount, 0, GCHeap::GetGCHeap()->GetNumberOfHeaps()); - _ASSERTE (uCount <= GCHeap::GetGCHeap()->GetNumberOfHeaps()); + Interlocked::CompareExchange (&uCount, 0, g_theGCHeap->GetNumberOfHeaps()); + _ASSERTE (uCount <= g_theGCHeap->GetNumberOfHeaps()); } if (bDo) @@ -1623,7 +1595,7 @@ void Ref_UpdatePointers(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Re #if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) // Please update this if you change the Ref_UpdatePointers function above. -void Ref_ScanPointersForProfilerAndETW(uint32_t maxgen, uintptr_t lp1) +void Ref_ScanHandlesForProfilerAndETW(uint32_t maxgen, uintptr_t lp1, handle_scan_fn fn) { WRAPPER_NO_CONTRACT; @@ -1662,16 +1634,16 @@ void Ref_ScanPointersForProfilerAndETW(uint32_t maxgen, uintptr_t lp1) { HHANDLETABLE hTable = walk->pBuckets[i]->pTable[uCPUindex]; if (hTable) - HndScanHandlesForGC(hTable, &ScanPointerForProfilerAndETW, lp1, 0, types, _countof(types), maxgen, maxgen, flags); + HndScanHandlesForGC(hTable, &ScanPointerForProfilerAndETW, lp1, (uintptr_t)fn, types, _countof(types), maxgen, maxgen, flags); } walk = walk->pNext; } // update pointers in variable handles whose dynamic type is VHT_WEAK_SHORT, VHT_WEAK_LONG or VHT_STRONG - TraceVariableHandlesBySingleThread(&ScanPointerForProfilerAndETW, lp1, 0, VHT_WEAK_SHORT | VHT_WEAK_LONG | VHT_STRONG, maxgen, maxgen, flags); + TraceVariableHandlesBySingleThread(&ScanPointerForProfilerAndETW, lp1, (uintptr_t)fn, VHT_WEAK_SHORT | VHT_WEAK_LONG | VHT_STRONG, maxgen, maxgen, flags); } -void Ref_ScanDependentHandlesForProfilerAndETW(uint32_t maxgen, ProfilingScanContext * SC) +void Ref_ScanDependentHandlesForProfilerAndETW(uint32_t maxgen, ScanContext * SC, handle_scan_fn fn) { WRAPPER_NO_CONTRACT; @@ -1680,12 +1652,7 @@ void Ref_ScanDependentHandlesForProfilerAndETW(uint32_t maxgen, ProfilingScanCon uint32_t flags = HNDGCF_NORMAL; uintptr_t lp1 = (uintptr_t)SC; - // we'll re-use pHeapId (which was either unused (0) or freed by EndRootReferences2 - // (-1)), so reset it to NULL - _ASSERTE((*((size_t *)(&SC->pHeapId)) == (size_t)(-1)) || - (*((size_t *)(&SC->pHeapId)) == (size_t)(0))); - SC->pHeapId = NULL; - TraceDependentHandlesBySingleThread(&ScanPointerForProfilerAndETW, lp1, maxgen, maxgen, flags); + TraceDependentHandlesBySingleThread(&ScanPointerForProfilerAndETW, lp1, (uintptr_t)fn, maxgen, maxgen, flags); } #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) @@ -1906,9 +1873,9 @@ int GetCurrentThreadHomeHeapNumber() { WRAPPER_NO_CONTRACT; - if (!GCHeap::IsGCHeapInitialized()) + if (g_theGCHeap == nullptr) return 0; - return GCHeap::GetGCHeap()->GetHomeHeapNumber(); + return g_theGCHeap->GetHomeHeapNumber(); } bool HandleTableBucket::Contains(OBJECTHANDLE handle) @@ -1921,7 +1888,7 @@ bool HandleTableBucket::Contains(OBJECTHANDLE handle) } HHANDLETABLE hTable = HndGetHandleTable(handle); - for (int uCPUindex=0; uCPUindex < GCHeap::GetGCHeap()->GetNumberOfHeaps(); uCPUindex++) + for (int uCPUindex=0; uCPUindex < g_theGCHeap->GetNumberOfHeaps(); uCPUindex++) { if (hTable == this->pTable[uCPUindex]) { |