diff options
94 files changed, 1257 insertions, 938 deletions
diff --git a/src/classlibnative/bcltype/arraynative.cpp b/src/classlibnative/bcltype/arraynative.cpp index b1aa6f8751..f247fc46c5 100644 --- a/src/classlibnative/bcltype/arraynative.cpp +++ b/src/classlibnative/bcltype/arraynative.cpp @@ -961,7 +961,7 @@ void memmoveGCRefs(void *dest, const void *src, size_t len) } } - GCHeap::GetGCHeap()->SetCardsAfterBulkCopy((Object**)dest, len); + GCHeapUtilities::GetGCHeap()->SetCardsAfterBulkCopy((Object**)dest, len); } void ArrayNative::ArrayCopyNoTypeCheck(BASEARRAYREF pSrc, unsigned int srcIndex, BASEARRAYREF pDest, unsigned int destIndex, unsigned int length) diff --git a/src/classlibnative/bcltype/system.cpp b/src/classlibnative/bcltype/system.cpp index e902734b23..bb3e1792b4 100644 --- a/src/classlibnative/bcltype/system.cpp +++ b/src/classlibnative/bcltype/system.cpp @@ -673,7 +673,7 @@ FCIMPL0(FC_BOOL_RET, SystemNative::IsServerGC) { FCALL_CONTRACT; - FC_RETURN_BOOL(GCHeap::IsServerHeap()); + FC_RETURN_BOOL(GCHeapUtilities::IsServerHeap()); } FCIMPLEND diff --git a/src/debug/daccess/daccess.cpp b/src/debug/daccess/daccess.cpp index ba3995b1f7..aebfa43a91 100644 --- a/src/debug/daccess/daccess.cpp +++ b/src/debug/daccess/daccess.cpp @@ -7974,7 +7974,7 @@ HRESULT DacHandleWalker::Init(ClrDataAccess *dac, UINT types[], UINT typeCount, { SUPPORTS_DAC; - if (gen < 0 || gen > (int)GCHeap::GetMaxGeneration()) + if (gen < 0 || gen > (int)GCHeapUtilities::GetMaxGeneration()) return E_INVALIDARG; mGenerationFilter = gen; @@ -8033,7 +8033,7 @@ bool DacHandleWalker::FetchMoreHandles(HANDLESCANPROC callback) int max_slots = 1; #ifdef FEATURE_SVR_GC - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) max_slots = GCHeapCount(); #endif // FEATURE_SVR_GC @@ -8089,7 +8089,7 @@ bool DacHandleWalker::FetchMoreHandles(HANDLESCANPROC callback) HndScanHandlesForGC(hTable, callback, (LPARAM)¶m, 0, &handleType, 1, - mGenerationFilter, GCHeap::GetMaxGeneration(), 0); + mGenerationFilter, GCHeapUtilities::GetMaxGeneration(), 0); else HndEnumHandles(hTable, &handleType, 1, callback, (LPARAM)¶m, 0, FALSE); } diff --git a/src/debug/daccess/dacdbiimpl.cpp b/src/debug/daccess/dacdbiimpl.cpp index 9b17f4cd46..cb9c0310cc 100644 --- a/src/debug/daccess/dacdbiimpl.cpp +++ b/src/debug/daccess/dacdbiimpl.cpp @@ -6517,7 +6517,7 @@ HRESULT DacHeapWalker::Init(CORDB_ADDRESS start, CORDB_ADDRESS end) if (thread == NULL) continue; - alloc_context *ctx = thread->GetAllocContext(); + gc_alloc_context *ctx = thread->GetAllocContext(); if (ctx == NULL) continue; @@ -6533,7 +6533,7 @@ HRESULT DacHeapWalker::Init(CORDB_ADDRESS start, CORDB_ADDRESS end) } #ifdef FEATURE_SVR_GC - HRESULT hr = GCHeap::IsServerHeap() ? InitHeapDataSvr(mHeaps, mHeapCount) : InitHeapDataWks(mHeaps, mHeapCount); + HRESULT hr = GCHeapUtilities::IsServerHeap() ? InitHeapDataSvr(mHeaps, mHeapCount) : InitHeapDataWks(mHeaps, mHeapCount); #else HRESULT hr = InitHeapDataWks(mHeaps, mHeapCount); #endif @@ -6777,7 +6777,7 @@ HRESULT DacDbiInterfaceImpl::GetHeapSegments(OUT DacDbiArrayList<COR_SEGMENT> *p HeapData *heaps = 0; #ifdef FEATURE_SVR_GC - HRESULT hr = GCHeap::IsServerHeap() ? DacHeapWalker::InitHeapDataSvr(heaps, heapCount) : DacHeapWalker::InitHeapDataWks(heaps, heapCount); + HRESULT hr = GCHeapUtilities::IsServerHeap() ? DacHeapWalker::InitHeapDataSvr(heaps, heapCount) : DacHeapWalker::InitHeapDataWks(heaps, heapCount); #else HRESULT hr = DacHeapWalker::InitHeapDataWks(heaps, heapCount); #endif @@ -7171,7 +7171,7 @@ void DacDbiInterfaceImpl::GetGCHeapInformation(COR_HEAPINFO * pHeapInfo) pHeapInfo->areGCStructuresValid = GCScan::GetGcRuntimeStructuresValid(); #ifdef FEATURE_SVR_GC - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) { pHeapInfo->gcType = CorDebugServerGC; pHeapInfo->numHeaps = DacGetNumHeaps(); diff --git a/src/debug/daccess/enummem.cpp b/src/debug/daccess/enummem.cpp index 068c2f2b13..cc3ae4f606 100644 --- a/src/debug/daccess/enummem.cpp +++ b/src/debug/daccess/enummem.cpp @@ -250,9 +250,9 @@ HRESULT ClrDataAccess::EnumMemCLRStatic(IN CLRDataEnumMemoryFlags flags) ReportMem(m_globalBase + g_dacGlobals.SharedDomain__m_pSharedDomain, sizeof(SharedDomain)); - // We need GCHeap pointer to make EEVersion work + // We need IGCHeap pointer to make EEVersion work ReportMem(m_globalBase + g_dacGlobals.dac__g_pGCHeap, - sizeof(GCHeap *)); + sizeof(IGCHeap *)); // see synblk.cpp, the pointer is pointed to a static byte[] SyncBlockCache::s_pSyncBlockCache.EnumMem(); @@ -316,7 +316,7 @@ HRESULT ClrDataAccess::EnumMemCLRStatic(IN CLRDataEnumMemoryFlags flags) #ifdef FEATURE_SVR_GC CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED ( - GCHeap::gcHeapType.EnumMem(); + IGCHeap::gcHeapType.EnumMem(); ); #endif // FEATURE_SVR_GC diff --git a/src/debug/daccess/request.cpp b/src/debug/daccess/request.cpp index a30ec37eac..9de09e7f85 100644 --- a/src/debug/daccess/request.cpp +++ b/src/debug/daccess/request.cpp @@ -725,7 +725,7 @@ ClrDataAccess::GetHeapAllocData(unsigned int count, struct DacpGenerationAllocDa SOSDacEnter(); #if defined(FEATURE_SVR_GC) - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) { hr = GetServerAllocData(count, data, pNeeded); } @@ -2809,7 +2809,7 @@ ClrDataAccess::GetGCHeapDetails(CLRDATA_ADDRESS heap, struct DacpGcHeapDetails * SOSDacEnter(); // doesn't make sense to call this on WKS mode - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) hr = E_INVALIDARG; else #ifdef FEATURE_SVR_GC @@ -2884,7 +2884,7 @@ ClrDataAccess::GetHeapSegmentData(CLRDATA_ADDRESS seg, struct DacpHeapSegmentDat SOSDacEnter(); - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) { #if !defined(FEATURE_SVR_GC) _ASSERTE(0); @@ -2924,7 +2924,7 @@ ClrDataAccess::GetGCHeapList(unsigned int count, CLRDATA_ADDRESS heaps[], unsign SOSDacEnter(); // make sure we called this in appropriate circumstances (i.e., we have multiple heaps) - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) { #if !defined(FEATURE_SVR_GC) _ASSERTE(0); @@ -2960,45 +2960,53 @@ ClrDataAccess::GetGCHeapData(struct DacpGcHeapData *gcheapData) SOSDacEnter(); - // Now get the heap type. The first data member of the GCHeap class is the GC_HEAP_TYPE, which has - // three possible values: - // GC_HEAP_INVALID = 0, - // GC_HEAP_WKS = 1, - // GC_HEAP_SVR = 2 - - TADDR gcHeapLocation = g_pGCHeap.GetAddrRaw (); // get the starting address of the global GCHeap instance - size_t gcHeapValue = 0; // this will hold the heap type + size_t gcHeapValue = 0; ULONG32 returned = 0; + TADDR gcHeapTypeLocation = m_globalBase + g_dacGlobals.IGCHeap__gcHeapType; // @todo Microsoft: we should probably be capturing the HRESULT from ReadVirtual. We could // provide a more informative error message. E_FAIL is a wretchedly vague thing to return. - hr = m_pTarget->ReadVirtual(gcHeapLocation, (PBYTE)&gcHeapValue, sizeof(gcHeapValue), &returned); + hr = m_pTarget->ReadVirtual(gcHeapTypeLocation, (PBYTE)&gcHeapValue, sizeof(gcHeapValue), &returned); + if (!SUCCEEDED(hr)) + { + goto cleanup; + } + + // GC_HEAP_TYPE has three possible values: + // GC_HEAP_INVALID = 0, + // GC_HEAP_WKS = 1, + // GC_HEAP_SVR = 2 + // If we get something other than that, we probably read the wrong location. + _ASSERTE(gcHeapValue >= 0 && gcHeapValue <= 2); //@todo Microsoft: We have an enumerated type, we probably should use the symbolic name // we have GC_HEAP_INVALID if gcHeapValue == 0, so we're done if (SUCCEEDED(hr) && ((returned != sizeof(gcHeapValue)) || (gcHeapValue == 0))) + { hr = E_FAIL; + goto cleanup; + } - if (SUCCEEDED(hr)) + // Now we can get other important information about the heap + gcheapData->g_max_generation = GCHeapUtilities::GetMaxGeneration(); + gcheapData->bServerMode = GCHeapUtilities::IsServerHeap(); + gcheapData->bGcStructuresValid = GCScan::GetGcRuntimeStructuresValid(); + if (GCHeapUtilities::IsServerHeap()) { - // Now we can get other important information about the heap - gcheapData->g_max_generation = GCHeap::GetMaxGeneration(); - gcheapData->bServerMode = GCHeap::IsServerHeap(); - gcheapData->bGcStructuresValid = GCScan::GetGcRuntimeStructuresValid(); - if (GCHeap::IsServerHeap()) - { #if !defined (FEATURE_SVR_GC) - _ASSERTE(0); - gcheapData->HeapCount = 1; + _ASSERTE(0); + gcheapData->HeapCount = 1; #else // !defined (FEATURE_SVR_GC) - gcheapData->HeapCount = GCHeapCount(); + gcheapData->HeapCount = GCHeapCount(); #endif // !defined (FEATURE_SVR_GC) - } - else - { - gcheapData->HeapCount = 1; - } } + else + { + gcheapData->HeapCount = 1; + } + +cleanup: + ; SOSDacLeave(); return hr; @@ -3014,7 +3022,7 @@ ClrDataAccess::GetOOMStaticData(struct DacpOomData *oomData) memset(oomData, 0, sizeof(DacpOomData)); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) { oom_history* pOOMInfo = &(WKS::gc_heap::oom_info); oomData->reason = pOOMInfo->reason; @@ -3043,7 +3051,7 @@ ClrDataAccess::GetOOMData(CLRDATA_ADDRESS oomAddr, struct DacpOomData *data) SOSDacEnter(); memset(data, 0, sizeof(DacpOomData)); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) hr = E_FAIL; // doesn't make sense to call this on WKS mode #ifdef FEATURE_SVR_GC @@ -3090,7 +3098,7 @@ ClrDataAccess::GetGCInterestingInfoStaticData(struct DacpGCInterestingInfoData * SOSDacEnter(); memset(data, 0, sizeof(DacpGCInterestingInfoData)); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) { for (int i = 0; i < NUM_GC_DATA_POINTS; i++) data->interestingDataPoints[i] = WKS::interesting_data_per_heap[i]; @@ -3123,7 +3131,7 @@ ClrDataAccess::GetGCInterestingInfoData(CLRDATA_ADDRESS interestingInfoAddr, str SOSDacEnter(); memset(data, 0, sizeof(DacpGCInterestingInfoData)); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) hr = E_FAIL; // doesn't make sense to call this on WKS mode #ifdef FEATURE_SVR_GC @@ -3149,7 +3157,7 @@ ClrDataAccess::GetHeapAnalyzeData(CLRDATA_ADDRESS addr, struct DacpGcHeapAnalyz SOSDacEnter(); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) hr = E_FAIL; // doesn't make sense to call this on WKS mode #ifdef FEATURE_SVR_GC @@ -3856,7 +3864,7 @@ ClrDataAccess::EnumWksGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) // enumerating the generations from max (which is normally gen2) to max+1 gives you // the segment list for all the normal segements plus the large heap segment (max+1) // this is the convention in the GC so it is repeated here - for (ULONG i = GCHeap::GetMaxGeneration(); i <= GCHeap::GetMaxGeneration()+1; i++) + for (ULONG i = GCHeapUtilities::GetMaxGeneration(); i <= GCHeapUtilities::GetMaxGeneration()+1; i++) { __DPtr<WKS::heap_segment> seg = dac_cast<TADDR>(WKS::generation_table[i].start_segment); while (seg) diff --git a/src/debug/daccess/request_svr.cpp b/src/debug/daccess/request_svr.cpp index 429f30020f..1fe20e2b60 100644 --- a/src/debug/daccess/request_svr.cpp +++ b/src/debug/daccess/request_svr.cpp @@ -256,7 +256,7 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) // enumerating the generations from max (which is normally gen2) to max+1 gives you // the segment list for all the normal segements plus the large heap segment (max+1) // this is the convention in the GC so it is repeated here - for (ULONG i = GCHeap::GetMaxGeneration(); i <= GCHeap::GetMaxGeneration()+1; i++) + for (ULONG i = GCHeapUtilities::GetMaxGeneration(); i <= GCHeapUtilities::GetMaxGeneration()+1; i++) { __DPtr<SVR::heap_segment> seg = dac_cast<TADDR>(pHeap->generation_table[i].start_segment); while (seg) @@ -271,7 +271,7 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) DWORD DacGetNumHeaps() { - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) return (DWORD)SVR::gc_heap::n_heaps; // workstation gc diff --git a/src/gc/env/gcenv.ee.h b/src/gc/env/gcenv.ee.h index 0c1fd4988a..f71380e1a1 100644 --- a/src/gc/env/gcenv.ee.h +++ b/src/gc/env/gcenv.ee.h @@ -9,10 +9,11 @@ struct ScanContext; class CrawlFrame; +struct gc_alloc_context; typedef void promote_func(PTR_PTR_Object, ScanContext*, uint32_t); -typedef void enum_alloc_context_func(alloc_context*, void*); +typedef void enum_alloc_context_func(gc_alloc_context*, void*); typedef struct { @@ -74,7 +75,7 @@ public: static void EnablePreemptiveGC(Thread * pThread); static void DisablePreemptiveGC(Thread * pThread); - static alloc_context * GetAllocContext(Thread * pThread); + static gc_alloc_context * GetAllocContext(Thread * pThread); static bool CatchAtSafePoint(Thread * pThread); static void GcEnumAllocContexts(enum_alloc_context_func* fn, void* param); diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp index a62b02d33a..eb7e5a3429 100644 --- a/src/gc/gc.cpp +++ b/src/gc/gc.cpp @@ -1544,7 +1544,7 @@ void WaitLongerNoInstru (int i) } else if (g_TrapReturningThreads) { - GCHeap::GetGCHeap()->WaitUntilGCComplete(); + g_theGcHeap->WaitUntilGCComplete(); } } @@ -1573,7 +1573,7 @@ retry: unsigned int i = 0; while (VolatileLoad(lock) >= 0) { - if ((++i & 7) && !GCHeap::IsGCInProgress()) + if ((++i & 7) && !IsGCInProgress()) { if (g_SystemInfo.dwNumberOfProcessors > 1) { @@ -1584,11 +1584,11 @@ retry: #endif //!MULTIPLE_HEAPS for (int j = 0; j < spin_count; j++) { - if (VolatileLoad(lock) < 0 || GCHeap::IsGCInProgress()) + if (VolatileLoad(lock) < 0 || IsGCInProgress()) break; YieldProcessor(); // indicate to the processor that we are spining } - if (VolatileLoad(lock) >= 0 && !GCHeap::IsGCInProgress()) + if (VolatileLoad(lock) >= 0 && !IsGCInProgress()) { safe_switch_to_thread(); } @@ -3743,9 +3743,9 @@ public: BOOL fSmallObjectHeapPtr = FALSE, fLargeObjectHeapPtr = FALSE; if (!noRangeChecks) { - fSmallObjectHeapPtr = GCHeap::GetGCHeap()->IsHeapPointer(this, TRUE); + fSmallObjectHeapPtr = g_theGcHeap->IsHeapPointer(this, TRUE); if (!fSmallObjectHeapPtr) - fLargeObjectHeapPtr = GCHeap::GetGCHeap()->IsHeapPointer(this); + fLargeObjectHeapPtr = g_theGcHeap->IsHeapPointer(this); _ASSERTE(fSmallObjectHeapPtr || fLargeObjectHeapPtr); } @@ -3763,14 +3763,14 @@ public: #ifdef VERIFY_HEAP if (bDeep && (g_pConfig->GetHeapVerifyLevel() & EEConfig::HEAPVERIFY_GC)) - GCHeap::GetGCHeap()->ValidateObjectMember(this); + g_theGcHeap->ValidateObjectMember(this); #endif if (fSmallObjectHeapPtr) { #ifdef FEATURE_BASICFREEZE - _ASSERTE(!GCHeap::GetGCHeap()->IsLargeObject(pMT) || GCHeap::GetGCHeap()->IsInFrozenSegment(this)); + _ASSERTE(!g_theGcHeap->IsLargeObject(pMT) || g_theGcHeap->IsInFrozenSegment(this)); #else - _ASSERTE(!GCHeap::GetGCHeap()->IsLargeObject(pMT)); + _ASSERTE(!g_theGcHeap->IsLargeObject(pMT)); #endif } } @@ -4361,7 +4361,7 @@ static size_t get_valid_segment_size (BOOL large_seg=FALSE) // if seg_size is small but not 0 (0 is default if config not set) // then set the segment to the minimum size - if (!GCHeap::IsValidSegmentSize(seg_size)) + if (!g_theGcHeap->IsValidSegmentSize(seg_size)) { // if requested size is between 1 byte and 4MB, use min if ((seg_size >> 1) && !(seg_size >> 22)) @@ -5775,7 +5775,7 @@ void gc_heap::fix_allocation_context (alloc_context* acontext, BOOL for_gc_p, //used by the heap verification for concurrent gc. //it nulls out the words set by fix_allocation_context for heap_verification -void repair_allocation (alloc_context* acontext, void*) +void repair_allocation (gc_alloc_context* acontext, void*) { uint8_t* point = acontext->alloc_ptr; @@ -5788,7 +5788,7 @@ void repair_allocation (alloc_context* acontext, void*) } } -void void_allocation (alloc_context* acontext, void*) +void void_allocation (gc_alloc_context* acontext, void*) { uint8_t* point = acontext->alloc_ptr; @@ -5818,10 +5818,10 @@ struct fix_alloc_context_args void* heap; }; -void fix_alloc_context(alloc_context* acontext, void* param) +void fix_alloc_context(gc_alloc_context* acontext, void* param) { fix_alloc_context_args* args = (fix_alloc_context_args*)param; - GCHeap::GetGCHeap()->FixAllocContext(acontext, FALSE, (void*)(size_t)(args->for_gc_p), args->heap); + g_theGcHeap->FixAllocContext(acontext, FALSE, (void*)(size_t)(args->for_gc_p), args->heap); } void gc_heap::fix_allocation_contexts(BOOL for_gc_p) @@ -10384,10 +10384,10 @@ gc_heap::init_gc_heap (int h_number) heap_segment_heap (lseg) = this; //initialize the alloc context heap - generation_alloc_context (generation_of (0))->alloc_heap = vm_heap; + generation_alloc_context (generation_of (0))->set_alloc_heap(vm_heap); //initialize the alloc context heap - generation_alloc_context (generation_of (max_generation+1))->alloc_heap = vm_heap; + generation_alloc_context (generation_of (max_generation+1))->set_alloc_heap(vm_heap); #endif //MULTIPLE_HEAPS @@ -13080,10 +13080,10 @@ void gc_heap::balance_heaps (alloc_context* acontext) { if (acontext->alloc_count == 0) { - acontext->home_heap = GCHeap::GetHeap( heap_select::select_heap(acontext, 0) ); - gc_heap* hp = acontext->home_heap->pGenGCHeap; + acontext->set_home_heap(GCHeap::GetHeap( heap_select::select_heap(acontext, 0) )); + gc_heap* hp = acontext->get_home_heap()->pGenGCHeap; dprintf (3, ("First allocation for context %Ix on heap %d\n", (size_t)acontext, (size_t)hp->heap_number)); - acontext->alloc_heap = acontext->home_heap; + acontext->set_alloc_heap(acontext->get_home_heap()); hp->alloc_context_count++; } } @@ -13094,9 +13094,9 @@ void gc_heap::balance_heaps (alloc_context* acontext) if (heap_select::can_find_heap_fast()) { - if (acontext->home_heap != NULL) - hint = acontext->home_heap->pGenGCHeap->heap_number; - if (acontext->home_heap != GCHeap::GetHeap(hint = heap_select::select_heap(acontext, hint)) || ((acontext->alloc_count & 15) == 0)) + if (acontext->get_home_heap() != NULL) + hint = acontext->get_home_heap()->pGenGCHeap->heap_number; + if (acontext->get_home_heap() != GCHeap::GetHeap(hint = heap_select::select_heap(acontext, hint)) || ((acontext->alloc_count & 15) == 0)) { set_home_heap = TRUE; } @@ -13122,7 +13122,7 @@ void gc_heap::balance_heaps (alloc_context* acontext) else */ { - gc_heap* org_hp = acontext->alloc_heap->pGenGCHeap; + gc_heap* org_hp = acontext->get_alloc_heap()->pGenGCHeap; dynamic_data* dd = org_hp->dynamic_data_of (0); ptrdiff_t org_size = dd_new_allocation (dd); @@ -13141,9 +13141,9 @@ try_again: { max_hp = org_hp; max_size = org_size + delta; - acontext->home_heap = GCHeap::GetHeap( heap_select::select_heap(acontext, hint) ); + acontext->set_home_heap(GCHeap::GetHeap( heap_select::select_heap(acontext, hint) )); - if (org_hp == acontext->home_heap->pGenGCHeap) + if (org_hp == acontext->get_home_heap()->pGenGCHeap) max_size = max_size + delta; org_alloc_context_count = org_hp->alloc_context_count; @@ -13156,7 +13156,7 @@ try_again: gc_heap* hp = GCHeap::GetHeap(i%n_heaps)->pGenGCHeap; dd = hp->dynamic_data_of (0); ptrdiff_t size = dd_new_allocation (dd); - if (hp == acontext->home_heap->pGenGCHeap) + if (hp == acontext->get_home_heap()->pGenGCHeap) size = size + delta; int hp_alloc_context_count = hp->alloc_context_count; if (hp_alloc_context_count > 0) @@ -13183,7 +13183,7 @@ try_again: { org_hp->alloc_context_count--; max_hp->alloc_context_count++; - acontext->alloc_heap = GCHeap::GetHeap(max_hp->heap_number); + acontext->set_alloc_heap(GCHeap::GetHeap(max_hp->heap_number)); #if !defined(FEATURE_PAL) if (CPUGroupInfo::CanEnableGCCPUGroups()) { //only set ideal processor when max_hp and org_hp are in the same cpu @@ -13221,7 +13221,7 @@ try_again: #endif // !FEATURE_PAL dprintf (3, ("Switching context %p (home heap %d) ", acontext, - acontext->home_heap->pGenGCHeap->heap_number)); + acontext->get_home_heap()->pGenGCHeap->heap_number)); dprintf (3, (" from heap %d (%Id free bytes, %d contexts) ", org_hp->heap_number, org_size, @@ -13239,7 +13239,7 @@ try_again: gc_heap* gc_heap::balance_heaps_loh (alloc_context* acontext, size_t /*size*/) { - gc_heap* org_hp = acontext->alloc_heap->pGenGCHeap; + gc_heap* org_hp = acontext->get_alloc_heap()->pGenGCHeap; //dprintf (1, ("LA: %Id", size)); //if (size > 128*1024) @@ -13316,7 +13316,7 @@ BOOL gc_heap::allocate_more_space(alloc_context* acontext, size_t size, if (alloc_generation_number == 0) { balance_heaps (acontext); - status = acontext->alloc_heap->pGenGCHeap->try_allocate_more_space (acontext, size, alloc_generation_number); + status = acontext->get_alloc_heap()->pGenGCHeap->try_allocate_more_space (acontext, size, alloc_generation_number); } else { @@ -22250,7 +22250,7 @@ void gc_heap::plan_phase (int condemned_gen_number) #endif //TIME_GC // We may update write barrier code. We assume here EE has been suspended if we are on a GC thread. - assert(GCHeap::IsGCInProgress()); + assert(IsGCInProgress()); BOOL should_expand = FALSE; BOOL should_compact= FALSE; @@ -30469,7 +30469,7 @@ CObjectHeader* gc_heap::allocate_large_object (size_t jsize, int64_t& alloc_byte acontext.alloc_limit = 0; acontext.alloc_bytes = 0; #ifdef MULTIPLE_HEAPS - acontext.alloc_heap = vm_heap; + acontext.set_alloc_heap(vm_heap); #endif //MULTIPLE_HEAPS #ifdef MARK_ARRAY @@ -31946,11 +31946,11 @@ void gc_heap::descr_card_table () #endif //TRACE_GC } -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) void gc_heap::descr_generations_to_profiler (gen_walk_fn fn, void *context) { +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) #ifdef MULTIPLE_HEAPS - int n_heaps = GCHeap::GetGCHeap()->GetNumberOfHeaps (); + int n_heaps = g_theGcHeap->GetNumberOfHeaps (); for (int i = 0; i < n_heaps; i++) { gc_heap* hp = GCHeap::GetHeap(i)->pGenGCHeap; @@ -32026,8 +32026,8 @@ void gc_heap::descr_generations_to_profiler (gen_walk_fn fn, void *context) curr_gen_number0--; } } -} #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +} #ifdef TRACE_GC // Note that when logging is on it can take a long time to go through the free items. @@ -33306,8 +33306,12 @@ gc_heap::verify_heap (BOOL begin_gc_p) #endif //BACKGROUND_GC } +#endif //VERIFY_HEAP + + void GCHeap::ValidateObjectMember (Object* obj) { +#ifdef VERIFY_HEAP size_t s = size (obj); uint8_t* o = (uint8_t*)obj; @@ -33325,9 +33329,8 @@ void GCHeap::ValidateObjectMember (Object* obj) } } } ); - +#endif // VERIFY_HEAP } -#endif //VERIFY_HEAP void DestructObject (CObjectHeader* hdr) { @@ -33640,12 +33643,12 @@ BOOL GCHeap::IsEphemeral (Object* object) return hp->ephemeral_pointer_p (o); } -#ifdef VERIFY_HEAP // Return NULL if can't find next object. When EE is not suspended, // the result is not accurate: if the input arg is in gen0, the function could // return zeroed out memory as next object Object * GCHeap::NextObj (Object * object) { +#ifdef VERIFY_HEAP uint8_t* o = (uint8_t*)object; #ifndef FEATURE_BASICFREEZE @@ -33687,8 +33690,13 @@ Object * GCHeap::NextObj (Object * object) } return (Object *)nextobj; +#else + return nullptr; +#endif // VERIFY_HEAP } +#ifdef VERIFY_HEAP + #ifdef FEATURE_BASICFREEZE BOOL GCHeap::IsInFrozenSegment (Object * object) { @@ -33918,11 +33926,16 @@ int StressRNG(int iMaxValue) int randValue = (((lHoldrand = lHoldrand * 214013L + 2531011L) >> 16) & 0x7fff); return randValue % iMaxValue; } +#endif // STRESS_HEAP +#endif // !FEATURE_REDHAWK // free up object so that things will move and then do a GC //return TRUE if GC actually happens, otherwise FALSE -BOOL GCHeap::StressHeap(alloc_context * acontext) +BOOL GCHeap::StressHeap(gc_alloc_context * context) { +#if defined(STRESS_HEAP) && !defined(FEATURE_REDHAWK) + alloc_context* acontext = static_cast<alloc_context*>(context); + // if GC stress was dynamically disabled during this run we return FALSE if (!GCStressPolicy::IsEnabled()) return FALSE; @@ -34102,11 +34115,11 @@ BOOL GCHeap::StressHeap(alloc_context * acontext) } return TRUE; +#else + return FALSE; +#endif // defined(STRESS_HEAP) && !defined(FEATURE_REDHAWK) } -#endif // STRESS_HEAP -#endif // FEATURE_REDHAWK - #ifdef FEATURE_PREMORTEM_FINALIZATION #define REGISTER_FOR_FINALIZATION(_object, _size) \ @@ -34164,8 +34177,6 @@ GCHeap::Alloc( size_t size, uint32_t flags REQD_ALIGN_DCL) TRIGGERSGC(); - assert (!GCHeap::UseAllocationContexts()); - Object* newAlloc = NULL; #ifdef TRACE_GC @@ -34237,11 +34248,11 @@ GCHeap::Alloc( size_t size, uint32_t flags REQD_ALIGN_DCL) return newAlloc; } -#ifdef FEATURE_64BIT_ALIGNMENT // Allocate small object with an alignment requirement of 8-bytes. Non allocation context version. Object * GCHeap::AllocAlign8( size_t size, uint32_t flags) { +#ifdef FEATURE_64BIT_ALIGNMENT CONTRACTL { #ifdef FEATURE_REDHAWK // Under Redhawk NULL is returned on failure. @@ -34252,8 +34263,6 @@ GCHeap::AllocAlign8( size_t size, uint32_t flags) GC_TRIGGERS; } CONTRACTL_END; - assert (!GCHeap::UseAllocationContexts()); - Object* newAlloc = NULL; { @@ -34270,12 +34279,17 @@ GCHeap::AllocAlign8( size_t size, uint32_t flags) } return newAlloc; +#else + assert(!"should not call GCHeap::AllocAlign8 without FEATURE_64BIT_ALIGNMENT defined!"); + return nullptr; +#endif //FEATURE_64BIT_ALIGNMENT } // Allocate small object with an alignment requirement of 8-bytes. Allocation context version. Object* -GCHeap::AllocAlign8(alloc_context* acontext, size_t size, uint32_t flags ) +GCHeap::AllocAlign8(gc_alloc_context* ctx, size_t size, uint32_t flags ) { +#ifdef FEATURE_64BIT_ALIGNMENT CONTRACTL { #ifdef FEATURE_REDHAWK // Under Redhawk NULL is returned on failure. @@ -34286,25 +34300,32 @@ GCHeap::AllocAlign8(alloc_context* acontext, size_t size, uint32_t flags ) GC_TRIGGERS; } CONTRACTL_END; + alloc_context* acontext = static_cast<alloc_context*>(ctx); + #ifdef MULTIPLE_HEAPS - if (acontext->alloc_heap == 0) + if (acontext->get_alloc_heap() == 0) { AssignHeap (acontext); - assert (acontext->alloc_heap); + assert (acontext->get_alloc_heap()); } - gc_heap* hp = acontext->alloc_heap->pGenGCHeap; + gc_heap* hp = acontext->get_alloc_heap()->pGenGCHeap; #else gc_heap* hp = pGenGCHeap; #endif //MULTIPLE_HEAPS return AllocAlign8Common(hp, acontext, size, flags); +#else + assert(!"should not call GCHeap::AllocAlign8 without FEATURE_64BIT_ALIGNMENT defined!"); + return nullptr; +#endif //FEATURE_64BIT_ALIGNMENT } // Common code used by both variants of AllocAlign8 above. Object* GCHeap::AllocAlign8Common(void* _hp, alloc_context* acontext, size_t size, uint32_t flags) { +#ifdef FEATURE_64BIT_ALIGNMENT CONTRACTL { #ifdef FEATURE_REDHAWK // Under Redhawk NULL is returned on failure. @@ -34424,8 +34445,11 @@ GCHeap::AllocAlign8Common(void* _hp, alloc_context* acontext, size_t size, uint3 AllocCount++; #endif //TRACE_GC return newAlloc; -} +#else + assert(!"Should not call GCHeap::AllocAlign8Common without FEATURE_64BIT_ALIGNMENT defined!"); + return nullptr; #endif // FEATURE_64BIT_ALIGNMENT +} Object * GCHeap::AllocLHeap( size_t size, uint32_t flags REQD_ALIGN_DCL) @@ -34499,7 +34523,7 @@ GCHeap::AllocLHeap( size_t size, uint32_t flags REQD_ALIGN_DCL) } Object* -GCHeap::Alloc(alloc_context* acontext, size_t size, uint32_t flags REQD_ALIGN_DCL) +GCHeap::Alloc(gc_alloc_context* context, size_t size, uint32_t flags REQD_ALIGN_DCL) { CONTRACTL { #ifdef FEATURE_REDHAWK @@ -34522,6 +34546,7 @@ GCHeap::Alloc(alloc_context* acontext, size_t size, uint32_t flags REQD_ALIGN_DC TRIGGERSGC(); Object* newAlloc = NULL; + alloc_context* acontext = static_cast<alloc_context*>(context); #ifdef TRACE_GC #ifdef COUNT_CYCLES @@ -34534,10 +34559,10 @@ GCHeap::Alloc(alloc_context* acontext, size_t size, uint32_t flags REQD_ALIGN_DC #endif //TRACE_GC #ifdef MULTIPLE_HEAPS - if (acontext->alloc_heap == 0) + if (acontext->get_alloc_heap() == 0) { AssignHeap (acontext); - assert (acontext->alloc_heap); + assert (acontext->get_alloc_heap()); } #endif //MULTIPLE_HEAPS @@ -34546,7 +34571,7 @@ GCHeap::Alloc(alloc_context* acontext, size_t size, uint32_t flags REQD_ALIGN_DC #endif // FEATURE_REDHAWK #ifdef MULTIPLE_HEAPS - gc_heap* hp = acontext->alloc_heap->pGenGCHeap; + gc_heap* hp = acontext->get_alloc_heap()->pGenGCHeap; #else gc_heap* hp = pGenGCHeap; #ifdef _PREFAST_ @@ -34591,8 +34616,9 @@ GCHeap::Alloc(alloc_context* acontext, size_t size, uint32_t flags REQD_ALIGN_DC } void -GCHeap::FixAllocContext (alloc_context* acontext, BOOL lockp, void* arg, void *heap) +GCHeap::FixAllocContext (gc_alloc_context* context, BOOL lockp, void* arg, void *heap) { + alloc_context* acontext = static_cast<alloc_context*>(context); #ifdef MULTIPLE_HEAPS if (arg != 0) @@ -35383,8 +35409,8 @@ size_t GCHeap::ApproxTotalBytesInUse(BOOL small_heap_only) void GCHeap::AssignHeap (alloc_context* acontext) { // Assign heap based on processor - acontext->alloc_heap = GetHeap(heap_select::select_heap(acontext, 0)); - acontext->home_heap = acontext->alloc_heap; + acontext->set_alloc_heap(GetHeap(heap_select::select_heap(acontext, 0))); + acontext->set_home_heap(acontext->get_alloc_heap()); } GCHeap* GCHeap::GetHeap (int n) { @@ -35393,11 +35419,12 @@ GCHeap* GCHeap::GetHeap (int n) } #endif //MULTIPLE_HEAPS -bool GCHeap::IsThreadUsingAllocationContextHeap(alloc_context* acontext, int thread_number) +bool GCHeap::IsThreadUsingAllocationContextHeap(gc_alloc_context* context, int thread_number) { + alloc_context* acontext = static_cast<alloc_context*>(context); #ifdef MULTIPLE_HEAPS - return ((acontext->home_heap == GetHeap(thread_number)) || - ((acontext->home_heap == 0) && (thread_number == 0))); + return ((acontext->get_home_heap() == GetHeap(thread_number)) || + ((acontext->get_home_heap() == 0) && (thread_number == 0))); #else UNREFERENCED_PARAMETER(acontext); UNREFERENCED_PARAMETER(thread_number); @@ -35427,7 +35454,8 @@ int GCHeap::GetHomeHeapNumber () { if (pThread) { - GCHeap *hp = GCToEEInterface::GetAllocContext(pThread)->home_heap; + gc_alloc_context* ctx = GCToEEInterface::GetAllocContext(pThread); + GCHeap *hp = static_cast<alloc_context*>(ctx)->get_home_heap(); if (hp == gc_heap::g_heaps[i]->vm_heap) return i; } } @@ -35639,7 +35667,7 @@ size_t GCHeap::GetValidGen0MaxSize(size_t seg_size) { size_t gen0size = g_pConfig->GetGCgen0size(); - if ((gen0size == 0) || !GCHeap::IsValidGen0MaxSize(gen0size)) + if ((gen0size == 0) || !g_theGcHeap->IsValidGen0MaxSize(gen0size)) { #ifdef SERVER_GC // performance data seems to indicate halving the size results @@ -35869,7 +35897,7 @@ GCHeap::SetCardsAfterBulkCopy( Object **StartPoint, size_t len ) #ifdef BACKGROUND_GC (!gc_heap::settings.concurrent) && #endif //BACKGROUND_GC - (GCHeap::GetGCHeap()->WhichGeneration( (Object*) StartPoint ) == 0)) + (g_theGcHeap->WhichGeneration( (Object*) StartPoint ) == 0)) return; rover = StartPoint; @@ -36374,7 +36402,7 @@ CFinalize::ScanForFinalization (promote_func* pfn, int gen, BOOL mark_only_p, { CObjectHeader* obj = (CObjectHeader*)*i; dprintf (3, ("scanning: %Ix", (size_t)obj)); - if (!GCHeap::GetGCHeap()->IsPromoted (obj)) + if (!g_theGcHeap->IsPromoted (obj)) { dprintf (3, ("freacheable: %Ix", (size_t)obj)); @@ -36507,7 +36535,7 @@ CFinalize::UpdatePromotedGenerations (int gen, BOOL gen_0_empty_p) for (Object** po = startIndex; po < SegQueueLimit (gen_segment(i)); po++) { - int new_gen = GCHeap::GetGCHeap()->WhichGeneration (*po); + int new_gen = g_theGcHeap->WhichGeneration (*po); if (new_gen != i) { if (new_gen > i) @@ -36567,7 +36595,7 @@ void CFinalize::CheckFinalizerObjects() for (Object **po = startIndex; po < stopIndex; po++) { - if ((int)GCHeap::GetGCHeap()->WhichGeneration (*po) < i) + if ((int)g_theGcHeap->WhichGeneration (*po) < i) FATAL_GC_ERROR (); ((CObjectHeader*)*po)->Validate(); } @@ -36640,9 +36668,9 @@ void gc_heap::walk_heap (walk_fn fn, void* context, int gen_number, BOOL walk_la } } -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) void GCHeap::WalkObject (Object* obj, walk_fn fn, void* context) { +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) uint8_t* o = (uint8_t*)obj; if (o) { @@ -36657,8 +36685,8 @@ void GCHeap::WalkObject (Object* obj, walk_fn fn, void* context) } ); } -} #endif //defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +} // Go through and touch (read) each page straddled by a memory block. void TouchPages(void * pStart, size_t cb) diff --git a/src/gc/gc.h b/src/gc/gc.h index 14c6baee83..7f6e956515 100644 --- a/src/gc/gc.h +++ b/src/gc/gc.h @@ -14,9 +14,8 @@ Module Name: #ifndef __GC_H #define __GC_H -#ifdef PROFILING_SUPPORTED -#define GC_PROFILING //Turn on profiling -#endif // PROFILING_SUPPORTED +#include "gcinterface.h" + /* * Promotion Function Prototypes @@ -80,6 +79,24 @@ enum oom_reason oom_unproductive_full_gc = 6 }; +// TODO : it would be easier to make this an ORed value +enum gc_reason +{ + reason_alloc_soh = 0, + reason_induced = 1, + reason_lowmemory = 2, + reason_empty = 3, + reason_alloc_loh = 4, + reason_oos_soh = 5, + reason_oos_loh = 6, + reason_induced_noforce = 7, // it's an induced GC and doesn't have to be blocking. + reason_gcstress = 8, // this turns into reason_induced & gc_mechanisms.stress_induced = true + reason_lowmemory_blocking = 9, + reason_induced_compacting = 10, + reason_lowmemory_host = 11, + reason_max +}; + struct oom_history { oom_reason reason; @@ -97,28 +114,16 @@ struct oom_history class CObjectHeader; class Object; -class GCHeap; +class IGCHeapInternal; /* misc defines */ #define LARGE_OBJECT_SIZE ((size_t)(85000)) -GPTR_DECL(GCHeap, g_pGCHeap); - #ifdef GC_CONFIG_DRIVEN #define MAX_GLOBAL_GC_MECHANISMS_COUNT 6 GARY_DECL(size_t, gc_global_mechanisms, MAX_GLOBAL_GC_MECHANISMS_COUNT); #endif //GC_CONFIG_DRIVEN -#ifndef DACCESS_COMPILE -extern "C" { -#endif -GPTR_DECL(uint8_t,g_lowest_address); -GPTR_DECL(uint8_t,g_highest_address); -GPTR_DECL(uint32_t,g_card_table); -#ifndef DACCESS_COMPILE -} -#endif - #ifdef DACCESS_COMPILE class DacHeapWalker; #endif @@ -127,137 +132,22 @@ class DacHeapWalker; #define _LOGALLOC #endif -#ifdef WRITE_BARRIER_CHECK -//always defined, but should be 0 in Server GC -extern uint8_t* g_GCShadow; -extern uint8_t* g_GCShadowEnd; -// saves the g_lowest_address in between GCs to verify the consistency of the shadow segment -extern uint8_t* g_shadow_lowest_address; -#endif - #define MP_LOCKS -extern "C" uint8_t* g_ephemeral_low; -extern "C" uint8_t* g_ephemeral_high; - namespace WKS { - ::GCHeap* CreateGCHeap(); + ::IGCHeapInternal* CreateGCHeap(); class GCHeap; class gc_heap; } #if defined(FEATURE_SVR_GC) namespace SVR { - ::GCHeap* CreateGCHeap(); + ::IGCHeapInternal* CreateGCHeap(); class GCHeap; class gc_heap; } #endif // defined(FEATURE_SVR_GC) -/* - * Ephemeral Garbage Collected Heap Interface - */ - - -struct alloc_context -{ - friend class WKS::gc_heap; -#if defined(FEATURE_SVR_GC) - friend class SVR::gc_heap; - friend class SVR::GCHeap; -#endif // defined(FEATURE_SVR_GC) - friend struct ClassDumpInfo; - - uint8_t* alloc_ptr; - uint8_t* alloc_limit; - int64_t alloc_bytes; //Number of bytes allocated on SOH by this context - int64_t alloc_bytes_loh; //Number of bytes allocated on LOH by this context -#if defined(FEATURE_SVR_GC) - SVR::GCHeap* alloc_heap; - SVR::GCHeap* home_heap; -#endif // defined(FEATURE_SVR_GC) - int alloc_count; -public: - - void init() - { - LIMITED_METHOD_CONTRACT; - - alloc_ptr = 0; - alloc_limit = 0; - alloc_bytes = 0; - alloc_bytes_loh = 0; -#if defined(FEATURE_SVR_GC) - alloc_heap = 0; - home_heap = 0; -#endif // defined(FEATURE_SVR_GC) - alloc_count = 0; - } -}; - -struct ScanContext -{ - Thread* thread_under_crawl; - int thread_number; - uintptr_t stack_limit; // Lowest point on the thread stack that the scanning logic is permitted to read - BOOL promotion; //TRUE: Promotion, FALSE: Relocation. - BOOL concurrent; //TRUE: concurrent scanning -#if CHECK_APP_DOMAIN_LEAKS || defined (FEATURE_APPDOMAIN_RESOURCE_MONITORING) || defined (DACCESS_COMPILE) - AppDomain *pCurrentDomain; -#endif //CHECK_APP_DOMAIN_LEAKS || FEATURE_APPDOMAIN_RESOURCE_MONITORING || DACCESS_COMPILE - -#ifndef FEATURE_REDHAWK -#if defined(GC_PROFILING) || defined (DACCESS_COMPILE) - MethodDesc *pMD; -#endif //GC_PROFILING || DACCESS_COMPILE -#endif // FEATURE_REDHAWK -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - EtwGCRootKind dwEtwRootKind; -#endif // GC_PROFILING || FEATURE_EVENT_TRACE - - ScanContext() - { - LIMITED_METHOD_CONTRACT; - - thread_under_crawl = 0; - thread_number = -1; - stack_limit = 0; - promotion = FALSE; - concurrent = FALSE; -#ifdef GC_PROFILING - pMD = NULL; -#endif //GC_PROFILING -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - dwEtwRootKind = kEtwGCRootKindOther; -#endif // GC_PROFILING || FEATURE_EVENT_TRACE - } -}; - -typedef BOOL (* walk_fn)(Object*, void*); -typedef void (* gen_walk_fn)(void *context, int generation, uint8_t *range_start, uint8_t * range_end, uint8_t *range_reserved); - -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) -struct ProfilingScanContext : ScanContext -{ - BOOL fProfilerPinned; - void * pvEtwContext; - void *pHeapId; - - ProfilingScanContext(BOOL fProfilerPinnedParam) : ScanContext() - { - LIMITED_METHOD_CONTRACT; - - pHeapId = NULL; - fProfilerPinned = fProfilerPinnedParam; - pvEtwContext = NULL; -#ifdef FEATURE_CONSERVATIVE_GC - // To not confuse GCScan::GcScanRoots - promotion = g_pConfig->GetGCConservative(); -#endif - } -}; -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - #ifdef STRESS_HEAP #define IN_STRESS_HEAP(x) x #define STRESS_HEAP_ARG(x) ,x @@ -266,7 +156,6 @@ struct ProfilingScanContext : ScanContext #define STRESS_HEAP_ARG(x) #endif // STRESS_HEAP - //dynamic data interface struct gc_counters { @@ -275,51 +164,6 @@ struct gc_counters size_t collection_count; }; -// !!!!!!!!!!!!!!!!!!!!!!! -// make sure you change the def in bcl\system\gc.cs -// if you change this! -enum collection_mode -{ - collection_non_blocking = 0x00000001, - collection_blocking = 0x00000002, - collection_optimized = 0x00000004, - collection_compacting = 0x00000008 -#ifdef STRESS_HEAP - , collection_gcstress = 0x80000000 -#endif // STRESS_HEAP -}; - -// !!!!!!!!!!!!!!!!!!!!!!! -// make sure you change the def in bcl\system\gc.cs -// if you change this! -enum wait_full_gc_status -{ - wait_full_gc_success = 0, - wait_full_gc_failed = 1, - wait_full_gc_cancelled = 2, - wait_full_gc_timeout = 3, - wait_full_gc_na = 4 -}; - -// !!!!!!!!!!!!!!!!!!!!!!! -// make sure you change the def in bcl\system\gc.cs -// if you change this! -enum start_no_gc_region_status -{ - start_no_gc_success = 0, - start_no_gc_no_memory = 1, - start_no_gc_too_large = 2, - start_no_gc_in_progress = 3 -}; - -enum end_no_gc_region_status -{ - end_no_gc_success = 0, - end_no_gc_not_in_progress = 1, - end_no_gc_induced = 2, - end_no_gc_alloc_exceeded = 3 -}; - enum bgc_state { bgc_not_in_process = 0, @@ -352,276 +196,72 @@ void record_changed_seg (uint8_t* start, uint8_t* end, void record_global_mechanism (int mech_index); #endif //GC_CONFIG_DRIVEN -//constants for the flags parameter to the gc call back - -#define GC_CALL_INTERIOR 0x1 -#define GC_CALL_PINNED 0x2 -#define GC_CALL_CHECK_APP_DOMAIN 0x4 - -//flags for GCHeap::Alloc(...) -#define GC_ALLOC_FINALIZE 0x1 -#define GC_ALLOC_CONTAINS_REF 0x2 -#define GC_ALLOC_ALIGN8_BIAS 0x4 -#define GC_ALLOC_ALIGN8 0x8 - -class GCHeap { - friend struct ::_DacGlobals; -#ifdef DACCESS_COMPILE - friend class ClrDataAccess; -#endif - -public: - - virtual ~GCHeap() {} - - static GCHeap *GetGCHeap() +struct alloc_context : gc_alloc_context +{ +#ifdef FEATURE_SVR_GC + inline SVR::GCHeap* get_alloc_heap() { - LIMITED_METHOD_CONTRACT; - - _ASSERTE(g_pGCHeap != NULL); - return g_pGCHeap; + return static_cast<SVR::GCHeap*>(gc_reserved_1); } -#ifndef DACCESS_COMPILE - static BOOL IsGCInProgress(BOOL bConsiderGCStart = FALSE) - { - WRAPPER_NO_CONTRACT; - - return (IsGCHeapInitialized() ? GetGCHeap()->IsGCInProgressHelper(bConsiderGCStart) : false); - } -#endif - - static BOOL IsGCHeapInitialized() + inline void set_alloc_heap(SVR::GCHeap* heap) { - LIMITED_METHOD_CONTRACT; - - return (g_pGCHeap != NULL); + gc_reserved_1 = heap; } - static void WaitForGCCompletion(BOOL bConsiderGCStart = FALSE) - { - WRAPPER_NO_CONTRACT; - - if (IsGCHeapInitialized()) - GetGCHeap()->WaitUntilGCComplete(bConsiderGCStart); - } - - // The runtime needs to know whether we're using workstation or server GC - // long before the GCHeap is created. So IsServerHeap cannot be a virtual - // method on GCHeap. Instead we make it a static method and initialize - // gcHeapType before any of the calls to IsServerHeap. Note that this also - // has the advantage of getting the answer without an indirection - // (virtual call), which is important for perf critical codepaths. - - #ifndef DACCESS_COMPILE - static void InitializeHeapType(bool bServerHeap) - { - LIMITED_METHOD_CONTRACT; -#ifdef FEATURE_SVR_GC - gcHeapType = bServerHeap ? GC_HEAP_SVR : GC_HEAP_WKS; -#ifdef WRITE_BARRIER_CHECK - if (gcHeapType == GC_HEAP_SVR) - { - g_GCShadow = 0; - g_GCShadowEnd = 0; - } -#endif -#else // FEATURE_SVR_GC - UNREFERENCED_PARAMETER(bServerHeap); - CONSISTENCY_CHECK(bServerHeap == false); -#endif // FEATURE_SVR_GC - } - #endif - - static BOOL IsValidSegmentSize(size_t cbSize) + inline SVR::GCHeap* get_home_heap() { - //Must be aligned on a Mb and greater than 4Mb - return (((cbSize & (1024*1024-1)) ==0) && (cbSize >> 22)); + return static_cast<SVR::GCHeap*>(gc_reserved_2); } - static BOOL IsValidGen0MaxSize(size_t cbSize) + inline void set_home_heap(SVR::GCHeap* heap) { - return (cbSize >= 64*1024); + gc_reserved_2 = heap; } - - inline static bool IsServerHeap() - { - LIMITED_METHOD_CONTRACT; -#ifdef FEATURE_SVR_GC - _ASSERTE(gcHeapType != GC_HEAP_INVALID); - return (gcHeapType == GC_HEAP_SVR); -#else // FEATURE_SVR_GC - return false; #endif // FEATURE_SVR_GC - } +}; - inline static bool UseAllocationContexts() - { - WRAPPER_NO_CONTRACT; -#ifdef FEATURE_REDHAWK - // SIMPLIFY: only use allocation contexts - return true; -#else -#if defined(_TARGET_ARM_) || defined(FEATURE_PAL) - return true; -#else - return ((IsServerHeap() ? true : (g_SystemInfo.dwNumberOfProcessors >= 2))); +class IGCHeapInternal : public IGCHeap { + friend struct ::_DacGlobals; +#ifdef DACCESS_COMPILE + friend class ClrDataAccess; #endif -#endif - } - - inline static bool MarkShouldCompeteForStatics() - { - WRAPPER_NO_CONTRACT; - - return IsServerHeap() && g_SystemInfo.dwNumberOfProcessors >= 2; - } -#ifndef DACCESS_COMPILE - static GCHeap * CreateGCHeap() - { - WRAPPER_NO_CONTRACT; - - GCHeap * pGCHeap; - -#if defined(FEATURE_SVR_GC) - pGCHeap = (IsServerHeap() ? SVR::CreateGCHeap() : WKS::CreateGCHeap()); -#else - pGCHeap = WKS::CreateGCHeap(); -#endif // defined(FEATURE_SVR_GC) +public: - g_pGCHeap = pGCHeap; - return pGCHeap; - } -#endif // DACCESS_COMPILE + virtual ~IGCHeapInternal() {} private: - typedef enum - { - GC_HEAP_INVALID = 0, - GC_HEAP_WKS = 1, - GC_HEAP_SVR = 2 - } GC_HEAP_TYPE; - -#ifdef FEATURE_SVR_GC - SVAL_DECL(uint32_t,gcHeapType); -#endif // FEATURE_SVR_GC - + virtual Object* AllocAlign8Common (void* hp, alloc_context* acontext, size_t size, uint32_t flags) = 0; public: - // TODO Synchronization, should be moved out - virtual BOOL IsGCInProgressHelper (BOOL bConsiderGCStart = FALSE) = 0; - virtual uint32_t WaitUntilGCComplete (BOOL bConsiderGCStart = FALSE) = 0; - virtual void SetGCInProgress(BOOL fInProgress) = 0; - virtual CLREventStatic * GetWaitForGCEvent() = 0; - - virtual void SetFinalizationRun (Object* obj) = 0; - virtual Object* GetNextFinalizable() = 0; - virtual size_t GetNumberOfFinalizable() = 0; - - virtual void SetFinalizeQueueForShutdown(BOOL fHasLock) = 0; - virtual BOOL FinalizeAppDomain(AppDomain *pDomain, BOOL fRunFinalizers) = 0; - virtual BOOL ShouldRestartFinalizerWatchDog() = 0; - - //wait for concurrent GC to finish - virtual void WaitUntilConcurrentGCComplete () = 0; // Use in managed threads -#ifndef DACCESS_COMPILE - virtual HRESULT WaitUntilConcurrentGCCompleteAsync(int millisecondsTimeout) = 0; // Use in native threads. TRUE if succeed. FALSE if failed or timeout -#endif - virtual BOOL IsConcurrentGCInProgress() = 0; - - // Enable/disable concurrent GC - virtual void TemporaryEnableConcurrentGC() = 0; - virtual void TemporaryDisableConcurrentGC() = 0; - virtual BOOL IsConcurrentGCEnabled() = 0; - - virtual void FixAllocContext (alloc_context* acontext, BOOL lockp, void* arg, void *heap) = 0; - virtual Object* Alloc (alloc_context* acontext, size_t size, uint32_t flags) = 0; - - // This is safe to call only when EE is suspended. - virtual Object* GetContainingObject(void *pInteriorPtr) = 0; - - // TODO Should be folded into constructor - virtual HRESULT Initialize () = 0; - - virtual HRESULT GarbageCollect (int generation = -1, BOOL low_memory_p=FALSE, int mode = collection_blocking) = 0; - virtual Object* Alloc (size_t size, uint32_t flags) = 0; -#ifdef FEATURE_64BIT_ALIGNMENT - virtual Object* AllocAlign8 (size_t size, uint32_t flags) = 0; - virtual Object* AllocAlign8 (alloc_context* acontext, size_t size, uint32_t flags) = 0; -private: - virtual Object* AllocAlign8Common (void* hp, alloc_context* acontext, size_t size, uint32_t flags) = 0; -public: -#endif // FEATURE_64BIT_ALIGNMENT - virtual Object* AllocLHeap (size_t size, uint32_t flags) = 0; - virtual void SetReservedVMLimit (size_t vmlimit) = 0; - virtual void SetCardsAfterBulkCopy( Object**, size_t ) = 0; -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - virtual void WalkObject (Object* obj, walk_fn fn, void* context) = 0; -#endif //defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - - virtual bool IsThreadUsingAllocationContextHeap(alloc_context* acontext, int thread_number) = 0; + virtual void SetReservedVMLimit (size_t vmlimit) = 0; virtual int GetNumberOfHeaps () = 0; virtual int GetHomeHeapNumber () = 0; - - virtual int CollectionCount (int generation, int get_bgc_fgc_count = 0) = 0; - - // Finalizer queue stuff (should stay) - virtual bool RegisterForFinalization (int gen, Object* obj) = 0; - - // General queries to the GC - virtual BOOL IsPromoted (Object *object) = 0; - virtual unsigned WhichGeneration (Object* object) = 0; - virtual BOOL IsEphemeral (Object* object) = 0; - virtual BOOL IsHeapPointer (void* object, BOOL small_heap_only = FALSE) = 0; - - virtual unsigned GetCondemnedGeneration() = 0; - virtual int GetGcLatencyMode() = 0; - virtual int SetGcLatencyMode(int newLatencyMode) = 0; - - virtual int GetLOHCompactionMode() = 0; - virtual void SetLOHCompactionMode(int newLOHCompactionyMode) = 0; - - virtual BOOL RegisterForFullGCNotification(uint32_t gen2Percentage, - uint32_t lohPercentage) = 0; - virtual BOOL CancelFullGCNotification() = 0; - virtual int WaitForFullGCApproach(int millisecondsTimeout) = 0; - virtual int WaitForFullGCComplete(int millisecondsTimeout) = 0; - - virtual int StartNoGCRegion(uint64_t totalSize, BOOL lohSizeKnown, uint64_t lohSize, BOOL disallowFullBlockingGC) = 0; - virtual int EndNoGCRegion() = 0; + virtual size_t GetPromotedBytes(int heap_index) = 0; - virtual BOOL IsObjectInFixedHeap(Object *pObj) = 0; - virtual size_t GetTotalBytesInUse () = 0; - virtual size_t GetCurrentObjSize() = 0; - virtual size_t GetLastGCStartTime(int generation) = 0; - virtual size_t GetLastGCDuration(int generation) = 0; - virtual size_t GetNow() = 0; - virtual unsigned GetGcCount() = 0; - virtual void TraceGCSegments() = 0; + unsigned GetMaxGeneration() + { + return IGCHeap::maxGeneration; + } - virtual void PublishObject(uint8_t* obj) = 0; + BOOL IsValidSegmentSize(size_t cbSize) + { + //Must be aligned on a Mb and greater than 4Mb + return (((cbSize & (1024*1024-1)) ==0) && (cbSize >> 22)); + } - // static if since restricting for all heaps is fine - virtual size_t GetValidSegmentSize(BOOL large_seg = FALSE) = 0; + BOOL IsValidGen0MaxSize(size_t cbSize) + { + return (cbSize >= 64*1024); + } - static BOOL IsLargeObject(MethodTable *mt) { + BOOL IsLargeObject(MethodTable *mt) + { WRAPPER_NO_CONTRACT; return mt->GetBaseSize() >= LARGE_OBJECT_SIZE; } - static unsigned GetMaxGeneration() { - LIMITED_METHOD_DAC_CONTRACT; - return max_generation; - } - - virtual size_t GetPromotedBytes(int heap_index) = 0; - -private: - enum { - max_generation = 2, - }; - public: #ifdef FEATURE_BASICFREEZE @@ -630,43 +270,17 @@ public: virtual void UnregisterFrozenSegment(segment_handle seg) = 0; #endif //FEATURE_BASICFREEZE - // debug support -#ifndef FEATURE_REDHAWK // Redhawk forces relocation a different way -#ifdef STRESS_HEAP - //return TRUE if GC actually happens, otherwise FALSE - virtual BOOL StressHeap(alloc_context * acontext = 0) = 0; -#endif -#endif // FEATURE_REDHAWK -#ifdef VERIFY_HEAP - virtual void ValidateObjectMember (Object *obj) = 0; -#endif - -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - virtual void DescrGenerationsToProfiler (gen_walk_fn fn, void *context) = 0; -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - protected: -#ifdef VERIFY_HEAP public: - // Return NULL if can't find next object. When EE is not suspended, - // the result is not accurate: if the input arg is in gen0, the function could - // return zeroed out memory as next object - virtual Object * NextObj (Object * object) = 0; -#ifdef FEATURE_BASICFREEZE +#if defined(FEATURE_BASICFREEZE) && defined(VERIFY_HEAP) // Return TRUE if object lives in frozen segment virtual BOOL IsInFrozenSegment (Object * object) = 0; -#endif //FEATURE_BASICFREEZE -#endif //VERIFY_HEAP +#endif // defined(FEATURE_BASICFREEZE) && defined(VERIFY_HEAP) }; -extern VOLATILE(int32_t) m_GCLock; - // Go through and touch (read) each page straddled by a memory block. void TouchPages(void * pStart, size_t cb); -// For low memory notification from host -extern int32_t g_bLowMemoryFromHost; - #ifdef WRITE_BARRIER_CHECK void updateGCShadow(Object** ptr, Object* val); #endif @@ -677,4 +291,27 @@ extern MethodTable *pWeakReferenceMT; extern MethodTable *pWeakReferenceOfTCanonMT; extern void FinalizeWeakReference(Object * obj); +// The single GC heap instance, shared with the VM. +extern IGCHeapInternal* g_theGcHeap; + +#ifndef DACCESS_COMPILE +inline BOOL IsGCInProgress(bool bConsiderGCStart = FALSE) +{ + WRAPPER_NO_CONTRACT; + + return g_theGcHeap != nullptr ? g_theGcHeap->IsGCInProgressHelper(bConsiderGCStart) : false; +} +#endif // DACCESS_COMPILE + +inline BOOL IsServerHeap() +{ + LIMITED_METHOD_CONTRACT; +#ifdef FEATURE_SVR_GC + _ASSERTE(IGCHeap::gcHeapType != IGCHeap::GC_HEAP_INVALID); + return (IGCHeap::gcHeapType == IGCHeap::GC_HEAP_SVR); +#else // FEATURE_SVR_GC + return false; +#endif // FEATURE_SVR_GC +} + #endif // __GC_H diff --git a/src/gc/gccommon.cpp b/src/gc/gccommon.cpp index 779aac7296..6bcdf3957b 100644 --- a/src/gc/gccommon.cpp +++ b/src/gc/gccommon.cpp @@ -15,10 +15,12 @@ #include "gc.h" #ifdef FEATURE_SVR_GC -SVAL_IMPL_INIT(uint32_t,GCHeap,gcHeapType,GCHeap::GC_HEAP_INVALID); +SVAL_IMPL_INIT(uint32_t,IGCHeap,gcHeapType,IGCHeap::GC_HEAP_INVALID); #endif // FEATURE_SVR_GC -GPTR_IMPL(GCHeap,g_pGCHeap); +SVAL_IMPL_INIT(uint32_t,IGCHeap,maxGeneration,2); + +IGCHeapInternal* g_theGcHeap; /* global versions of the card table and brick table */ GPTR_IMPL(uint32_t,g_card_table); @@ -112,4 +114,41 @@ void record_changed_seg (uint8_t* start, uint8_t* end, } } +// The runtime needs to know whether we're using workstation or server GC +// long before the GCHeap is created. +void InitializeHeapType(bool bServerHeap) +{ + LIMITED_METHOD_CONTRACT; +#ifdef FEATURE_SVR_GC + IGCHeap::gcHeapType = bServerHeap ? IGCHeap::GC_HEAP_SVR : IGCHeap::GC_HEAP_WKS; +#ifdef WRITE_BARRIER_CHECK + if (IGCHeap::gcHeapType == IGCHeap::GC_HEAP_SVR) + { + g_GCShadow = 0; + g_GCShadowEnd = 0; + } +#endif // WRITE_BARRIER_CHECK +#else // FEATURE_SVR_GC + UNREFERENCED_PARAMETER(bServerHeap); + CONSISTENCY_CHECK(bServerHeap == false); +#endif // FEATURE_SVR_GC +} + +IGCHeap* InitializeGarbageCollector(IGCToCLR* clrToGC) +{ + LIMITED_METHOD_CONTRACT; + UNREFERENCED_PARAMETER(clrToGC); + + IGCHeapInternal* heap; +#ifdef FEATURE_SVR_GC + assert(IGCHeap::gcHeapType != IGCHeap::GC_HEAP_INVALID); + heap = IGCHeap::gcHeapType == IGCHeap::GC_HEAP_SVR ? SVR::CreateGCHeap() : WKS::CreateGCHeap(); +#else + heap = WKS::CreateGCHeap(); +#endif + + g_theGcHeap = heap; + return heap; +} + #endif // !DACCESS_COMPILE diff --git a/src/gc/gcee.cpp b/src/gc/gcee.cpp index d37eaf4de9..e2015eef0c 100644 --- a/src/gc/gcee.cpp +++ b/src/gc/gcee.cpp @@ -148,7 +148,7 @@ void GCHeap::UpdatePostGCCounters() // if a max gen garbage collection was performed, resync the GC Handle counter; // if threads are currently suspended, we do not need to obtain a lock on each handle table if (condemned_gen == max_generation) - total_num_gc_handles = HndCountAllHandles(!GCHeap::IsGCInProgress()); + total_num_gc_handles = HndCountAllHandles(!IsGCInProgress()); #endif //FEATURE_REDHAWK // per generation calculation. @@ -782,7 +782,7 @@ void gc_heap::background_gc_wait_lh (alloc_wait_reason awr) /******************************************************************************/ -::GCHeap* CreateGCHeap() { +IGCHeapInternal* CreateGCHeap() { return new(nothrow) GCHeap(); // we return wks or svr } @@ -823,12 +823,12 @@ void GCHeap::TraceGCSegments() #endif // FEATURE_EVENT_TRACE } -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) void GCHeap::DescrGenerationsToProfiler (gen_walk_fn fn, void *context) { +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) pGenGCHeap->descr_generations_to_profiler(fn, context); -} #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +} #ifdef FEATURE_BASICFREEZE segment_handle GCHeap::RegisterFrozenSegment(segment_info *pseginfo) diff --git a/src/gc/gcimpl.h b/src/gc/gcimpl.h index 6a4ee86cd8..38392b8229 100644 --- a/src/gc/gcimpl.h +++ b/src/gc/gcimpl.h @@ -36,29 +36,10 @@ inline void checkGCWriteBarrier() {} void GCProfileWalkHeap(); -class GCHeap; class gc_heap; class CFinalize; -// TODO : it would be easier to make this an ORed value -enum gc_reason -{ - reason_alloc_soh = 0, - reason_induced = 1, - reason_lowmemory = 2, - reason_empty = 3, - reason_alloc_loh = 4, - reason_oos_soh = 5, - reason_oos_loh = 6, - reason_induced_noforce = 7, // it's an induced GC and doesn't have to be blocking. - reason_gcstress = 8, // this turns into reason_induced & gc_mechanisms.stress_induced = true - reason_lowmemory_blocking = 9, - reason_induced_compacting = 10, - reason_lowmemory_host = 11, - reason_max -}; - -class GCHeap : public ::GCHeap +class GCHeap : public IGCHeapInternal { protected: @@ -111,17 +92,15 @@ public: //flags can be GC_ALLOC_CONTAINS_REF GC_ALLOC_FINALIZE Object* Alloc (size_t size, uint32_t flags); -#ifdef FEATURE_64BIT_ALIGNMENT Object* AllocAlign8 (size_t size, uint32_t flags); - Object* AllocAlign8 (alloc_context* acontext, size_t size, uint32_t flags); + Object* AllocAlign8 (gc_alloc_context* acontext, size_t size, uint32_t flags); private: Object* AllocAlign8Common (void* hp, alloc_context* acontext, size_t size, uint32_t flags); public: -#endif // FEATURE_64BIT_ALIGNMENT Object* AllocLHeap (size_t size, uint32_t flags); - Object* Alloc (alloc_context* acontext, size_t size, uint32_t flags); + Object* Alloc (gc_alloc_context* acontext, size_t size, uint32_t flags); - void FixAllocContext (alloc_context* acontext, + void FixAllocContext (gc_alloc_context* acontext, BOOL lockp, void* arg, void *heap); Object* GetContainingObject(void *pInteriorPtr); @@ -132,7 +111,7 @@ public: #endif //MULTIPLE_HEAPS int GetHomeHeapNumber (); - bool IsThreadUsingAllocationContextHeap(alloc_context* acontext, int thread_number); + bool IsThreadUsingAllocationContextHeap(gc_alloc_context* acontext, int thread_number); int GetNumberOfHeaps (); void HideAllocContext(alloc_context*); void RevealAllocContext(alloc_context*); @@ -176,9 +155,7 @@ public: BOOL IsEphemeral (Object* object); BOOL IsHeapPointer (void* object, BOOL small_heap_only = FALSE); -#ifdef VERIFY_HEAP void ValidateObjectMember (Object *obj); -#endif //_DEBUG PER_HEAP size_t ApproxTotalBytesInUse(BOOL small_heap_only = FALSE); PER_HEAP size_t ApproxFreeBytes(); @@ -199,8 +176,6 @@ public: int StartNoGCRegion(uint64_t totalSize, BOOL lohSizeKnown, uint64_t lohSize, BOOL disallowFullBlockingGC); int EndNoGCRegion(); - - PER_HEAP_ISOLATED unsigned GetMaxGeneration(); unsigned GetGcCount(); @@ -224,9 +199,7 @@ public: BOOL ShouldRestartFinalizerWatchDog(); void SetCardsAfterBulkCopy( Object**, size_t); -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) void WalkObject (Object* obj, walk_fn fn, void* context); -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) public: // FIX @@ -281,11 +254,12 @@ private: // the condition here may have to change as well. return g_TrapReturningThreads == 0; } -#ifndef FEATURE_REDHAWK // Redhawk forces relocation a different way -#ifdef STRESS_HEAP public: //return TRUE if GC actually happens, otherwise FALSE - BOOL StressHeap(alloc_context * acontext = 0); + BOOL StressHeap(gc_alloc_context * acontext = 0); + +#ifndef FEATURE_REDHAWK // Redhawk forces relocation a different way +#ifdef STRESS_HEAP protected: // only used in BACKGROUND_GC, but the symbol is not defined yet... @@ -300,17 +274,13 @@ protected: #endif // STRESS_HEAP #endif // FEATURE_REDHAWK -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) virtual void DescrGenerationsToProfiler (gen_walk_fn fn, void *context); -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) -#ifdef VERIFY_HEAP public: Object * NextObj (Object * object); -#ifdef FEATURE_BASICFREEZE +#if defined (FEATURE_BASICFREEZE) && defined (VERIFY_HEAP) BOOL IsInFrozenSegment (Object * object); -#endif //FEATURE_BASICFREEZE -#endif //VERIFY_HEAP +#endif // defined (FEATURE_BASICFREEZE) && defined (VERIFY_HEAP) }; #endif // GCIMPL_H_ diff --git a/src/gc/gcinterface.h b/src/gc/gcinterface.h new file mode 100644 index 0000000000..a12031bc61 --- /dev/null +++ b/src/gc/gcinterface.h @@ -0,0 +1,509 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _GC_INTERFACE_H_ +#define _GC_INTERFACE_H_ + +// The allocation context must be known to the VM for use in the allocation +// fast path and known to the GC for performing the allocation. Every Thread +// has its own allocation context that it hands to the GC when allocating. +struct gc_alloc_context +{ + uint8_t* alloc_ptr; + uint8_t* alloc_limit; + int64_t alloc_bytes; //Number of bytes allocated on SOH by this context + int64_t alloc_bytes_loh; //Number of bytes allocated on LOH by this context + // These two fields are deliberately not exposed past the EE-GC interface. + void* gc_reserved_1; + void* gc_reserved_2; + int alloc_count; +public: + + void init() + { + LIMITED_METHOD_CONTRACT; + + alloc_ptr = 0; + alloc_limit = 0; + alloc_bytes = 0; + alloc_bytes_loh = 0; + gc_reserved_1 = 0; + gc_reserved_2 = 0; + alloc_count = 0; + } +}; + +#ifdef PROFILING_SUPPORTED +#define GC_PROFILING //Turn on profiling +#endif // PROFILING_SUPPORTED + +#define LARGE_OBJECT_SIZE ((size_t)(85000)) + +class Object; +class IGCHeap; +class IGCToCLR; + +// Initializes the garbage collector. Should only be called +// once, during EE startup. +IGCHeap* InitializeGarbageCollector(IGCToCLR* clrToGC); + +// The runtime needs to know whether we're using workstation or server GC +// long before the GCHeap is created. This function sets the type of +// heap that will be created, before InitializeGarbageCollector is called +// and the heap is actually recated. +void InitializeHeapType(bool bServerHeap); + +#ifndef DACCESS_COMPILE +extern "C" { +#endif // !DACCESS_COMPILE +GPTR_DECL(uint8_t,g_lowest_address); +GPTR_DECL(uint8_t,g_highest_address); +GPTR_DECL(uint32_t,g_card_table); +#ifndef DACCESS_COMPILE +} +#endif // !DACCESS_COMPILE + +extern "C" uint8_t* g_ephemeral_low; +extern "C" uint8_t* g_ephemeral_high; + +#ifdef WRITE_BARRIER_CHECK +//always defined, but should be 0 in Server GC +extern uint8_t* g_GCShadow; +extern uint8_t* g_GCShadowEnd; +// saves the g_lowest_address in between GCs to verify the consistency of the shadow segment +extern uint8_t* g_shadow_lowest_address; +#endif + +// For low memory notification from host +extern int32_t g_bLowMemoryFromHost; + +extern VOLATILE(int32_t) m_GCLock; + +// !!!!!!!!!!!!!!!!!!!!!!! +// make sure you change the def in bcl\system\gc.cs +// if you change this! +enum collection_mode +{ + collection_non_blocking = 0x00000001, + collection_blocking = 0x00000002, + collection_optimized = 0x00000004, + collection_compacting = 0x00000008 +#ifdef STRESS_HEAP + , collection_gcstress = 0x80000000 +#endif // STRESS_HEAP +}; + +// !!!!!!!!!!!!!!!!!!!!!!! +// make sure you change the def in bcl\system\gc.cs +// if you change this! +enum wait_full_gc_status +{ + wait_full_gc_success = 0, + wait_full_gc_failed = 1, + wait_full_gc_cancelled = 2, + wait_full_gc_timeout = 3, + wait_full_gc_na = 4 +}; + +// !!!!!!!!!!!!!!!!!!!!!!! +// make sure you change the def in bcl\system\gc.cs +// if you change this! +enum start_no_gc_region_status +{ + start_no_gc_success = 0, + start_no_gc_no_memory = 1, + start_no_gc_too_large = 2, + start_no_gc_in_progress = 3 +}; + +enum end_no_gc_region_status +{ + end_no_gc_success = 0, + end_no_gc_not_in_progress = 1, + end_no_gc_induced = 2, + end_no_gc_alloc_exceeded = 3 +}; + +typedef BOOL (* walk_fn)(Object*, void*); +typedef void (* gen_walk_fn)(void* context, int generation, uint8_t* range_start, uint8_t* range_end, uint8_t* range_reserved); + +// IGCHeap is the interface that the VM will use when interacting with the GC. +class IGCHeap { +public: + /* + =========================================================================== + Hosting APIs. These are used by GC hosting. The code that + calls these methods may possibly be moved behind the interface - + today, the VM handles the setting of segment size and max gen 0 size. + (See src/vm/corehost.cpp) + =========================================================================== + */ + + // Returns whether or not the given size is a valid segment size. + virtual BOOL IsValidSegmentSize(size_t size) = 0; + + // Returns whether or not the given size is a valid gen 0 max size. + virtual BOOL IsValidGen0MaxSize(size_t size) = 0; + + // Gets a valid segment size. + virtual size_t GetValidSegmentSize(BOOL large_seg = FALSE) = 0; + + /* + =========================================================================== + Concurrent GC routines. These are used in various places in the VM + to synchronize with the GC, when the VM wants to update something that + the GC is potentially using, if it's doing a background GC. + + Concrete examples of this are moving async pinned handles across appdomains + and profiling/ETW scenarios. + =========================================================================== + */ + + // Blocks until any running concurrent GCs complete. + virtual void WaitUntilConcurrentGCComplete() = 0; + + // Returns true if a concurrent GC is in progress, false otherwise. + virtual BOOL IsConcurrentGCInProgress() = 0; + + // Temporarily enables concurrent GC, used during profiling. + virtual void TemporaryEnableConcurrentGC() = 0; + + // Temporarily disables concurrent GC, used during profiling. + virtual void TemporaryDisableConcurrentGC() = 0; + + // Returns whether or not Concurrent GC is enabled. + virtual BOOL IsConcurrentGCEnabled() = 0; + + // Wait for a concurrent GC to complete if one is in progress, with the given timeout. + virtual HRESULT WaitUntilConcurrentGCCompleteAsync(int millisecondsTimeout) = 0; // Use in native threads. TRUE if succeed. FALSE if failed or timeout + + + /* + =========================================================================== + Finalization routines. These are used by the finalizer thread to communicate + with the GC. + =========================================================================== + */ + + // Finalizes an app domain by finalizing objects within that app domain. + virtual BOOL FinalizeAppDomain(AppDomain* pDomain, BOOL fRunFinalizers) = 0; + + // Finalizes all registered objects for shutdown, even if they are still reachable. + virtual void SetFinalizeQueueForShutdown(BOOL fHasLock) = 0; + + // Gets the number of finalizable objects. + virtual size_t GetNumberOfFinalizable() = 0; + + // Traditionally used by the finalizer thread on shutdown to determine + // whether or not to time out. Returns true if the GC lock has not been taken. + virtual BOOL ShouldRestartFinalizerWatchDog() = 0; + + // Gets the next finalizable object. + virtual Object* GetNextFinalizable() = 0; + + /* + =========================================================================== + BCL routines. These are routines that are directly exposed by mscorlib + as a part of the `System.GC` class. These routines behave in the same + manner as the functions on `System.GC`. + =========================================================================== + */ + + // Gets the current GC latency mode. + virtual int GetGcLatencyMode() = 0; + + // Sets the current GC latency mode. newLatencyMode has already been + // verified by mscorlib to be valid. + virtual int SetGcLatencyMode(int newLatencyMode) = 0; + + // Gets the current LOH compaction mode. + virtual int GetLOHCompactionMode() = 0; + + // Sets the current LOH compaction mode. newLOHCompactionMode has + // already been verified by mscorlib to be valid. + virtual void SetLOHCompactionMode(int newLOHCompactionMode) = 0; + + // Registers for a full GC notification, raising a notification if the gen 2 or + // LOH object heap thresholds are exceeded. + virtual BOOL RegisterForFullGCNotification(uint32_t gen2Percentage, uint32_t lohPercentage) = 0; + + // Cancels a full GC notification that was requested by `RegisterForFullGCNotification`. + virtual BOOL CancelFullGCNotification() = 0; + + // Returns the status of a registered notification for determining whether a blocking + // Gen 2 collection is about to be initiated, with the given timeout. + virtual int WaitForFullGCApproach(int millisecondsTimeout) = 0; + + // Returns the status of a registered notification for determining whether a blocking + // Gen 2 collection has completed, with the given timeout. + virtual int WaitForFullGCComplete(int millisecondsTimeout) = 0; + + // Returns the generation in which obj is found. Also used by the VM + // in some places, in particular syncblk code. + virtual unsigned WhichGeneration(Object* obj) = 0; + + // Returns the number of GCs that have transpired in the given generation + // since the beginning of the life of the process. Also used by the VM + // for debug code and app domains. + virtual int CollectionCount(int generation, int get_bgc_fgc_coutn = 0) = 0; + + // Begins a no-GC region, returning a code indicating whether entering the no-GC + // region was successful. + virtual int StartNoGCRegion(uint64_t totalSize, BOOL lohSizeKnown, uint64_t lohSize, BOOL disallowFullBlockingGC) = 0; + + // Exits a no-GC region. + virtual int EndNoGCRegion() = 0; + + // Gets the total number of bytes in use. + virtual size_t GetTotalBytesInUse() = 0; + + // Forces a garbage collection of the given generation. Also used extensively + // throughout the VM. + virtual HRESULT GarbageCollect(int generation = -1, BOOL low_memory_p = FALSE, int mode = collection_blocking) = 0; + + // Gets the largest GC generation. Also used extensively throughout the VM. + virtual unsigned GetMaxGeneration() = 0; + + // Indicates that an object's finalizer should not be run upon the object's collection. + virtual void SetFinalizationRun(Object* obj) = 0; + + // Indicates that an object's finalizer should be run upon the object's collection. + virtual bool RegisterForFinalization(int gen, Object* obj) = 0; + + /* + =========================================================================== + Miscellaneous routines used by the VM. + =========================================================================== + */ + + // Initializes the GC heap, returning whether or not the initialization + // was successful. + virtual HRESULT Initialize() = 0; + + // Returns whether nor this GC was promoted by the last GC. + virtual BOOL IsPromoted(Object* object) = 0; + + // Returns true if this pointer points into a GC heap, false otherwise. + virtual BOOL IsHeapPointer(void* object, BOOL small_heap_only = FALSE) = 0; + + // Return the generation that has been condemned by the current GC. + virtual unsigned GetCondemnedGeneration() = 0; + + // Returns whether or not a GC is in progress. + virtual BOOL IsGCInProgressHelper(BOOL bConsiderGCStart = FALSE) = 0; + + // Returns the number of GCs that have occured. Mainly used for + // sanity checks asserting that a GC has not occured. + virtual unsigned GetGcCount() = 0; + + // Sets cards after an object has been memmoved. + virtual void SetCardsAfterBulkCopy(Object** obj, size_t length) = 0; + + // Gets whether or not the home heap of this alloc context matches the heap + // associated with this thread. + virtual bool IsThreadUsingAllocationContextHeap(gc_alloc_context* acontext, int thread_number) = 0; + + // Returns whether or not this object resides in an ephemeral generation. + virtual BOOL IsEphemeral(Object* object) = 0; + + // Blocks until a GC is complete, returning a code indicating the wait was successful. + virtual uint32_t WaitUntilGCComplete(BOOL bConsiderGCStart = FALSE) = 0; + + // "Fixes" an allocation context by binding its allocation pointer to a + // location on the heap. + virtual void FixAllocContext(gc_alloc_context* acontext, BOOL lockp, void* arg, void* heap) = 0; + + // Gets the total survived size plus the total allocated bytes on the heap. + virtual size_t GetCurrentObjSize() = 0; + + // Sets whether or not a GC is in progress. + virtual void SetGCInProgress(BOOL fInProgress) = 0; + + /* + Add/RemoveMemoryPressure support routines. These are on the interface + for now, but we should move Add/RemoveMemoryPressure from the VM to the GC. + When that occurs, these three routines can be removed from the interface. + */ + + // Get the timestamp corresponding to the last GC that occured for the + // given generation. + virtual size_t GetLastGCStartTime(int generation) = 0; + + // Gets the duration of the last GC that occured for the given generation. + virtual size_t GetLastGCDuration(int generation) = 0; + + // Gets a timestamp for the current moment in time. + virtual size_t GetNow() = 0; + + /* + =========================================================================== + Allocation routines. These all call into the GC's allocator and may trigger a garbage + collection. + =========================================================================== + */ + + // Allocates an object on the given allocation context with the given size and flags. + virtual Object* Alloc(gc_alloc_context* acontext, size_t size, uint32_t flags) = 0; + + // Allocates an object on the default allocation context with the given size and flags. + virtual Object* Alloc(size_t size, uint32_t flags) = 0; + + // Allocates an object on the large object heap with the given size and flags. + virtual Object* AllocLHeap(size_t size, uint32_t flags) = 0; + + // Allocates an object on the default allocation context, aligned to 64 bits, + // with the given size and flags. + virtual Object* AllocAlign8 (size_t size, uint32_t flags) = 0; + + // Allocates an object on the given allocation context, aligned to 64 bits, + // with the given size and flags. + virtual Object* AllocAlign8 (gc_alloc_context* acontext, size_t size, uint32_t flags) = 0; + + // If allocating on the LOH, blocks if a BGC is in a position (concurrent mark) + // where the LOH allocator can't allocate. + virtual void PublishObject(uint8_t* obj) = 0; + + // Gets the event that suspended threads will use to wait for the + // end of a GC. + virtual CLREventStatic* GetWaitForGCEvent() = 0; + + /* + =========================================================================== + Heap verification routines. These are used during heap verification only. + =========================================================================== + */ + // Returns whether or not this object is in the fixed heap. + virtual BOOL IsObjectInFixedHeap(Object* pObj) = 0; + + // Walks an object and validates its members. + virtual void ValidateObjectMember(Object* obj) = 0; + + // Retrieves the next object after the given object. When the EE + // is not suspended, the result is not accurate - if the input argument + // is in Gen0, the function could return zeroed out memory as the next object. + virtual Object* NextObj(Object* object) = 0; + + // Given an interior pointer, return a pointer to the object + // containing that pointer. This is safe to call only when the EE is suspended. + virtual Object* GetContainingObject(void* pInteriorPtr) = 0; + + /* + =========================================================================== + Profiling routines. Used for event tracing and profiling to broadcast + information regarding the heap. + =========================================================================== + */ + + // Walks an object, invoking a callback on each member. + virtual void WalkObject(Object* obj, walk_fn fn, void* context) = 0; + + // Describes all generations to the profiler, invoking a callback on each generation. + virtual void DescrGenerationsToProfiler(gen_walk_fn fn, void* context) = 0; + + // Traces all GC segments and fires ETW events with information on them. + virtual void TraceGCSegments() = 0; + + /* + =========================================================================== + GC Stress routines. Used only when running under GC Stress. + =========================================================================== + */ + + // Returns TRUE if GC actually happens, otherwise FALSE + virtual BOOL StressHeap(gc_alloc_context* acontext = 0) = 0; + + IGCHeap() {} + virtual ~IGCHeap() {} + + typedef enum + { + GC_HEAP_INVALID = 0, + GC_HEAP_WKS = 1, + GC_HEAP_SVR = 2 + } GC_HEAP_TYPE; + +#ifdef FEATURE_SVR_GC + SVAL_DECL(uint32_t, gcHeapType); +#endif + + SVAL_DECL(uint32_t, maxGeneration); +}; + +#ifdef WRITE_BARRIER_CHECK +void updateGCShadow(Object** ptr, Object* val); +#endif + +//constants for the flags parameter to the gc call back + +#define GC_CALL_INTERIOR 0x1 +#define GC_CALL_PINNED 0x2 +#define GC_CALL_CHECK_APP_DOMAIN 0x4 + +//flags for IGCHeapAlloc(...) +#define GC_ALLOC_FINALIZE 0x1 +#define GC_ALLOC_CONTAINS_REF 0x2 +#define GC_ALLOC_ALIGN8_BIAS 0x4 +#define GC_ALLOC_ALIGN8 0x8 + +struct ScanContext +{ + Thread* thread_under_crawl; + int thread_number; + uintptr_t stack_limit; // Lowest point on the thread stack that the scanning logic is permitted to read + BOOL promotion; //TRUE: Promotion, FALSE: Relocation. + BOOL concurrent; //TRUE: concurrent scanning +#if CHECK_APP_DOMAIN_LEAKS || defined (FEATURE_APPDOMAIN_RESOURCE_MONITORING) || defined (DACCESS_COMPILE) + AppDomain *pCurrentDomain; +#endif //CHECK_APP_DOMAIN_LEAKS || FEATURE_APPDOMAIN_RESOURCE_MONITORING || DACCESS_COMPILE + +#ifndef FEATURE_REDHAWK +#if defined(GC_PROFILING) || defined (DACCESS_COMPILE) + MethodDesc *pMD; +#endif //GC_PROFILING || DACCESS_COMPILE +#endif // FEATURE_REDHAWK +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + EtwGCRootKind dwEtwRootKind; +#endif // GC_PROFILING || FEATURE_EVENT_TRACE + + ScanContext() + { + LIMITED_METHOD_CONTRACT; + + thread_under_crawl = 0; + thread_number = -1; + stack_limit = 0; + promotion = FALSE; + concurrent = FALSE; +#ifdef GC_PROFILING + pMD = NULL; +#endif //GC_PROFILING +#ifdef FEATURE_EVENT_TRACE + dwEtwRootKind = kEtwGCRootKindOther; +#endif // FEATURE_EVENT_TRACE + } +}; + +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +struct ProfilingScanContext : ScanContext +{ + BOOL fProfilerPinned; + void * pvEtwContext; + void *pHeapId; + + ProfilingScanContext(BOOL fProfilerPinnedParam) : ScanContext() + { + LIMITED_METHOD_CONTRACT; + + pHeapId = NULL; + fProfilerPinned = fProfilerPinnedParam; + pvEtwContext = NULL; +#ifdef FEATURE_CONSERVATIVE_GC + // To not confuse GCScan::GcScanRoots + promotion = g_pConfig->GetGCConservative(); +#endif + } +}; +#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + +#endif // _GC_INTERFACE_H_ diff --git a/src/gc/gcpriv.h b/src/gc/gcpriv.h index 03a23454a0..9fbb289db8 100644 --- a/src/gc/gcpriv.h +++ b/src/gc/gcpriv.h @@ -2547,9 +2547,9 @@ protected: PER_HEAP void descr_generations (BOOL begin_gc_p); -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) PER_HEAP_ISOLATED void descr_generations_to_profiler (gen_walk_fn fn, void *context); +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) PER_HEAP void record_survived_for_profiler(int condemned_gen_number, uint8_t * first_condemned_address); PER_HEAP @@ -2978,7 +2978,7 @@ protected: PER_HEAP VOLATILE(int) alloc_context_count; #else //MULTIPLE_HEAPS -#define vm_heap ((GCHeap*) g_pGCHeap) +#define vm_heap ((GCHeap*) g_theGcHeap) #define heap_number (0) #endif //MULTIPLE_HEAPS diff --git a/src/gc/gcscan.cpp b/src/gc/gcscan.cpp index 42989e0414..f22840a262 100644 --- a/src/gc/gcscan.cpp +++ b/src/gc/gcscan.cpp @@ -129,7 +129,7 @@ static void CALLBACK CheckPromoted(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t * /* LOG((LF_GC, LL_INFO100000, LOG_HANDLE_OBJECT_CLASS("Checking referent of Weak-", pObjRef, "to ", *pObjRef))); Object **pRef = (Object **)pObjRef; - if (!GCHeap::GetGCHeap()->IsPromoted(*pRef)) + if (!g_theGcHeap->IsPromoted(*pRef)) { LOG((LF_GC, LL_INFO100, LOG_HANDLE_OBJECT_CLASS("Severing Weak-", pObjRef, "to unreachable ", *pObjRef))); @@ -240,14 +240,14 @@ void GCScan::GcRuntimeStructuresValid (BOOL bValid) void GCScan::GcDemote (int condemned, int max_gen, ScanContext* sc) { Ref_RejuvenateHandles (condemned, max_gen, (uintptr_t)sc); - if (!GCHeap::IsServerHeap() || sc->thread_number == 0) + if (!IsServerHeap() || sc->thread_number == 0) GCToEEInterface::SyncBlockCacheDemote(max_gen); } void GCScan::GcPromotionsGranted (int condemned, int max_gen, ScanContext* sc) { Ref_AgeHandles(condemned, max_gen, (uintptr_t)sc); - if (!GCHeap::IsServerHeap() || sc->thread_number == 0) + if (!IsServerHeap() || sc->thread_number == 0) GCToEEInterface::SyncBlockCachePromotionsGranted(max_gen); } diff --git a/src/gc/handletable.cpp b/src/gc/handletable.cpp index 43b43ffcea..fe184bf2ff 100644 --- a/src/gc/handletable.cpp +++ b/src/gc/handletable.cpp @@ -755,7 +755,7 @@ void HndLogSetEvent(OBJECTHANDLE handle, _UNCHECKED_OBJECTREF value) uint32_t hndType = HandleFetchType(handle); ADIndex appDomainIndex = HndGetHandleADIndex(handle); AppDomain* pAppDomain = SystemDomain::GetAppDomainAtIndex(appDomainIndex); - uint32_t generation = value != 0 ? GCHeap::GetGCHeap()->WhichGeneration(value) : 0; + uint32_t generation = value != 0 ? g_theGcHeap->WhichGeneration(value) : 0; FireEtwSetGCHandle((void*) handle, value, hndType, generation, (int64_t) pAppDomain, GetClrInstanceId()); FireEtwPrvSetGCHandle((void*) handle, value, hndType, generation, (int64_t) pAppDomain, GetClrInstanceId()); @@ -774,14 +774,14 @@ void HndLogSetEvent(OBJECTHANDLE handle, _UNCHECKED_OBJECTREF value) for (size_t i = 0; i < num; i ++) { value = ppObj[i]; - uint32_t generation = value != 0 ? GCHeap::GetGCHeap()->WhichGeneration(value) : 0; + uint32_t generation = value != 0 ? g_theGcHeap->WhichGeneration(value) : 0; FireEtwSetGCHandle(overlapped, value, HNDTYPE_PINNED, generation, (int64_t) pAppDomain, GetClrInstanceId()); } } else { value = OBJECTREF_TO_UNCHECKED_OBJECTREF(overlapped->m_userObject); - uint32_t generation = value != 0 ? GCHeap::GetGCHeap()->WhichGeneration(value) : 0; + uint32_t generation = value != 0 ? g_theGcHeap->WhichGeneration(value) : 0; FireEtwSetGCHandle(overlapped, value, HNDTYPE_PINNED, generation, (int64_t) pAppDomain, GetClrInstanceId()); } } @@ -838,7 +838,7 @@ void HndWriteBarrier(OBJECTHANDLE handle, OBJECTREF objref) if (*pClumpAge != 0) // Perf optimization: if clumpAge is 0, nothing more to do { // find out generation - int generation = GCHeap::GetGCHeap()->WhichGeneration(value); + int generation = g_theGcHeap->WhichGeneration(value); uint32_t uType = HandleFetchType(handle); #ifndef FEATURE_REDHAWK diff --git a/src/gc/handletablecore.cpp b/src/gc/handletablecore.cpp index 5e077de8a2..c6f569d5fa 100644 --- a/src/gc/handletablecore.cpp +++ b/src/gc/handletablecore.cpp @@ -14,6 +14,7 @@ #include "common.h" #include "gcenv.h" +#include "gc.h" #ifndef FEATURE_REDHAWK #include "nativeoverlapped.h" @@ -1111,13 +1112,13 @@ SLOW_PATH: // we have the lock held but the part we care about (the async table scan) takes the table lock during // a preparation step so we'll be able to complete our segment moves before the async scan has a // chance to interfere with us (or vice versa). - if (GCHeap::GetGCHeap()->IsConcurrentGCInProgress()) + if (g_theGcHeap->IsConcurrentGCInProgress()) { // A concurrent GC is in progress so someone might be scanning our segments asynchronously. // Release the lock, wait for the GC to complete and try again. The order is important; if we wait // before releasing the table lock we can deadlock with an async table scan. ch.Release(); - GCHeap::GetGCHeap()->WaitUntilConcurrentGCComplete(); + g_theGcHeap->WaitUntilConcurrentGCComplete(); continue; } diff --git a/src/gc/handletablescan.cpp b/src/gc/handletablescan.cpp index 863b5a52b0..1f58336573 100644 --- a/src/gc/handletablescan.cpp +++ b/src/gc/handletablescan.cpp @@ -818,7 +818,7 @@ void BlockResetAgeMapForBlocksWorker(uint32_t *pdwGen, uint32_t dwClumpMask, Sca { if (!HndIsNullOrDestroyedHandle(*pValue)) { - int thisAge = GCHeap::GetGCHeap()->WhichGeneration(*pValue); + int thisAge = g_theGcHeap->WhichGeneration(*pValue); if (minAge > thisAge) minAge = thisAge; @@ -830,7 +830,7 @@ void BlockResetAgeMapForBlocksWorker(uint32_t *pdwGen, uint32_t dwClumpMask, Sca if (pOverlapped->m_userObject != NULL) { Object * pUserObject = OBJECTREFToObject(pOverlapped->m_userObject); - thisAge = GCHeap::GetGCHeap()->WhichGeneration(pUserObject); + thisAge = g_theGcHeap->WhichGeneration(pUserObject); if (minAge > thisAge) minAge = thisAge; if (pOverlapped->m_isArray) @@ -840,7 +840,7 @@ void BlockResetAgeMapForBlocksWorker(uint32_t *pdwGen, uint32_t dwClumpMask, Sca size_t num = pUserArrayObject->GetNumComponents(); for (size_t i = 0; i < num; i ++) { - thisAge = GCHeap::GetGCHeap()->WhichGeneration(pObj[i]); + thisAge = g_theGcHeap->WhichGeneration(pObj[i]); if (minAge > thisAge) minAge = thisAge; } @@ -925,10 +925,10 @@ static void VerifyObjectAndAge(_UNCHECKED_OBJECTREF *pValue, _UNCHECKED_OBJECTRE UNREFERENCED_PARAMETER(pValue); VerifyObject(from, obj); - int thisAge = GCHeap::GetGCHeap()->WhichGeneration(obj); + int thisAge = g_theGcHeap->WhichGeneration(obj); //debugging code - //if (minAge > thisAge && thisAge < GCHeap::GetGCHeap()->GetMaxGeneration()) + //if (minAge > thisAge && thisAge < g_theGcHeap->GetMaxGeneration()) //{ // if ((*pValue) == obj) // printf("Handle (age %u) %p -> %p (age %u)", minAge, pValue, obj, thisAge); @@ -946,7 +946,7 @@ static void VerifyObjectAndAge(_UNCHECKED_OBJECTREF *pValue, _UNCHECKED_OBJECTRE // } //} - if (minAge >= GEN_MAX_AGE || (minAge > thisAge && thisAge < static_cast<int>(GCHeap::GetGCHeap()->GetMaxGeneration()))) + if (minAge >= GEN_MAX_AGE || (minAge > thisAge && thisAge < static_cast<int>(g_theGcHeap->GetMaxGeneration()))) { _ASSERTE(!"Fatal Error in HandleTable."); EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); diff --git a/src/gc/objecthandle.cpp b/src/gc/objecthandle.cpp index 74a8a71c5e..231332a395 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)) { @@ -186,9 +186,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 +221,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 +230,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 +330,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 +355,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; } @@ -583,10 +583,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 +874,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 +1152,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; @@ -1454,7 +1454,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 +1574,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) @@ -1906,9 +1906,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 +1921,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]) { diff --git a/src/gc/sample/GCSample.cpp b/src/gc/sample/GCSample.cpp index 7e07834ced..c242f08cac 100644 --- a/src/gc/sample/GCSample.cpp +++ b/src/gc/sample/GCSample.cpp @@ -68,7 +68,7 @@ Object * AllocateObject(MethodTable * pMT) } else { - pObject = GCHeap::GetGCHeap()->Alloc(acontext, size, 0); + pObject = g_theGcHeap->Alloc(acontext, size, 0); if (pObject == NULL) return NULL; } @@ -137,7 +137,7 @@ int __cdecl main(int argc, char* argv[]) // // Initialize GC heap // - GCHeap *pGCHeap = GCHeap::CreateGCHeap(); + IGCHeap *pGCHeap = InitializeGarbageCollector(nullptr); if (!pGCHeap) return -1; diff --git a/src/gc/sample/gcenv.ee.cpp b/src/gc/sample/gcenv.ee.cpp index 330564a380..05359d954c 100644 --- a/src/gc/sample/gcenv.ee.cpp +++ b/src/gc/sample/gcenv.ee.cpp @@ -131,7 +131,7 @@ void ThreadStore::AttachCurrentThread() void GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_REASON reason) { - GCHeap::GetGCHeap()->SetGCInProgress(TRUE); + g_theGcHeap->SetGCInProgress(TRUE); // TODO: Implement } @@ -140,7 +140,7 @@ void GCToEEInterface::RestartEE(bool bFinishedGC) { // TODO: Implement - GCHeap::GetGCHeap()->SetGCInProgress(FALSE); + g_theGcHeap->SetGCInProgress(FALSE); } void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc) @@ -184,7 +184,7 @@ void GCToEEInterface::DisablePreemptiveGC(Thread * pThread) pThread->DisablePreemptiveGC(); } -alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread) +gc_alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread) { return pThread->GetAllocContext(); } diff --git a/src/gc/sample/gcenv.h b/src/gc/sample/gcenv.h index d560789751..3f43a3ffeb 100644 --- a/src/gc/sample/gcenv.h +++ b/src/gc/sample/gcenv.h @@ -64,6 +64,9 @@ #define LOG(x) +#define SVAL_IMPL_INIT(type, cls, var, init) \ + type cls::var = init + // // Thread // diff --git a/src/inc/dacvars.h b/src/inc/dacvars.h index fb052b3f5d..c8a12931bf 100644 --- a/src/inc/dacvars.h +++ b/src/inc/dacvars.h @@ -125,9 +125,10 @@ DEFINE_DACVAR(ULONG, PTR_Thread, dac__g_pFinalizerThread, ::g_pFinalizerThread) DEFINE_DACVAR(ULONG, PTR_Thread, dac__g_pSuspensionThread, ::g_pSuspensionThread) #ifdef FEATURE_SVR_GC -DEFINE_DACVAR(ULONG, DWORD, GCHeap__gcHeapType, GCHeap::gcHeapType) +DEFINE_DACVAR(ULONG, DWORD, IGCHeap__gcHeapType, IGCHeap::gcHeapType) #endif // FEATURE_SVR_GC +DEFINE_DACVAR(ULONG, DWORD, IGCHeap__maxGeneration, IGCHeap::maxGeneration) DEFINE_DACVAR(ULONG, PTR_BYTE, WKS__gc_heap__alloc_allocated, WKS::gc_heap::alloc_allocated) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE /*PTR_heap_segment*/, WKS__gc_heap__ephemeral_heap_segment, WKS::gc_heap::ephemeral_heap_segment) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE /*PTR_CFinalize*/, WKS__gc_heap__finalize_queue, WKS::gc_heap::finalize_queue) @@ -198,7 +199,7 @@ DEFINE_DACVAR(ULONG, PTR_DWORD, dac__g_card_table, ::g_card_table) DEFINE_DACVAR(ULONG, PTR_BYTE, dac__g_lowest_address, ::g_lowest_address) DEFINE_DACVAR(ULONG, PTR_BYTE, dac__g_highest_address, ::g_highest_address) -DEFINE_DACVAR(ULONG, GCHeap, dac__g_pGCHeap, ::g_pGCHeap) +DEFINE_DACVAR(ULONG, IGCHeap, dac__g_pGCHeap, ::g_pGCHeap) #ifdef GC_CONFIG_DRIVEN DEFINE_DACVAR_NO_DUMP(ULONG, SIZE_T, dac__interesting_data_per_heap, WKS::interesting_data_per_heap) diff --git a/src/inc/stresslog.h b/src/inc/stresslog.h index 86dee130c4..55fb27a56d 100644 --- a/src/inc/stresslog.h +++ b/src/inc/stresslog.h @@ -683,7 +683,7 @@ public: static const char* gcRootPromoteMsg() { STATIC_CONTRACT_LEAF; - return " GCHeap::Promote: Promote GC Root *%p = %p MT = %pT\n"; + return " IGCHeap::Promote: Promote GC Root *%p = %p MT = %pT\n"; } static const char* gcPlugMoveMsg() diff --git a/src/strongname/api/common.h b/src/strongname/api/common.h index c83685cc0c..0518c00433 100644 --- a/src/strongname/api/common.h +++ b/src/strongname/api/common.h @@ -156,7 +156,7 @@ typedef DPTR(class TypeHandle) PTR_TypeHandle; typedef VPTR(class VirtualCallStubManager) PTR_VirtualCallStubManager; typedef VPTR(class VirtualCallStubManagerManager) PTR_VirtualCallStubManagerManager; #endif -typedef VPTR(class GCHeap) PTR_GCHeap; +typedef VPTR(class IGCHeap) PTR_IGCHeap; // // _UNCHECKED_OBJECTREF is for code that can't deal with DEBUG OBJECTREFs diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt index 6f17a90c1f..e15d08d2d3 100644 --- a/src/vm/CMakeLists.txt +++ b/src/vm/CMakeLists.txt @@ -70,6 +70,7 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON formattype.cpp fptrstubs.cpp frames.cpp + gcheaputilities.cpp genericdict.cpp generics.cpp hash.cpp diff --git a/src/vm/amd64/asmconstants.h b/src/vm/amd64/asmconstants.h index 32b23c83c3..ad90dd17ad 100644 --- a/src/vm/amd64/asmconstants.h +++ b/src/vm/amd64/asmconstants.h @@ -164,10 +164,10 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_ThreadId == offsetof(Thread, m_ThreadId)); #define OFFSET__Thread__m_alloc_context__alloc_ptr 0x60 -ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_ptr == offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_ptr)); +ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_ptr == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr)); #define OFFSET__Thread__m_alloc_context__alloc_limit 0x68 -ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_limit == offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_limit)); +ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_limit == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_limit)); #define OFFSETOF__ThreadExceptionState__m_pCurrentTracker 0x000 ASMCONSTANTS_C_ASSERT(OFFSETOF__ThreadExceptionState__m_pCurrentTracker diff --git a/src/vm/amd64/excepamd64.cpp b/src/vm/amd64/excepamd64.cpp index 2fc553a987..d4248e7b07 100644 --- a/src/vm/amd64/excepamd64.cpp +++ b/src/vm/amd64/excepamd64.cpp @@ -21,7 +21,7 @@ #include "comutilnative.h" #include "sigformat.h" #include "siginfo.hpp" -#include "gc.h" +#include "gcheaputilities.h" #include "eedbginterfaceimpl.h" //so we can clearexception in COMPlusThrow #include "perfcounters.h" #include "asmconstants.h" diff --git a/src/vm/amd64/jitinterfaceamd64.cpp b/src/vm/amd64/jitinterfaceamd64.cpp index 39c2e05c2f..d5dec8e6e8 100644 --- a/src/vm/amd64/jitinterfaceamd64.cpp +++ b/src/vm/amd64/jitinterfaceamd64.cpp @@ -390,7 +390,7 @@ bool WriteBarrierManager::NeedDifferentWriteBarrier(bool bReqUpperBoundsCheck, W } #endif - writeBarrierType = GCHeap::IsServerHeap() ? WRITE_BARRIER_SVR64 : WRITE_BARRIER_PREGROW64; + writeBarrierType = GCHeapUtilities::IsServerHeap() ? WRITE_BARRIER_SVR64 : WRITE_BARRIER_PREGROW64; continue; case WRITE_BARRIER_PREGROW64: diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp index 0ec2c5f2fc..f2d7955a43 100644 --- a/src/vm/appdomain.cpp +++ b/src/vm/appdomain.cpp @@ -12,7 +12,7 @@ #include "strongnameinternal.h" #include "excep.h" #include "eeconfig.h" -#include "gc.h" +#include "gcheaputilities.h" #include "eventtrace.h" #ifdef FEATURE_FUSION #include "assemblysink.h" @@ -2652,8 +2652,8 @@ void AppDomain::CreateADUnloadStartEvent() // If the thread is in cooperative mode, it must have been suspended for the GC so a delete // can't happen. - _ASSERTE(GCHeap::IsGCInProgress() && - GCHeap::IsServerHeap() && + _ASSERTE(GCHeapUtilities::IsGCInProgress() && + GCHeapUtilities::IsServerHeap() && IsGCSpecialThread()); SystemDomain* sysDomain = SystemDomain::System(); @@ -2691,7 +2691,7 @@ void SystemDomain::ResetADSurvivedBytes() } CONTRACT_END; - _ASSERTE(GCHeap::IsGCInProgress()); + _ASSERTE(GCHeapUtilities::IsGCInProgress()); SystemDomain* sysDomain = SystemDomain::System(); if (sysDomain) @@ -3824,7 +3824,7 @@ HRESULT SystemDomain::RunDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReser return S_OK; // ExitProcess is called while a thread is doing GC. - if (dwReason == DLL_PROCESS_DETACH && GCHeap::IsGCInProgress()) + if (dwReason == DLL_PROCESS_DETACH && GCHeapUtilities::IsGCInProgress()) return S_OK; // ExitProcess is called on a thread that we don't know about @@ -5107,7 +5107,7 @@ void AppDomain::Init() // Ref_CreateHandleTableBucket, this is because AD::Init() can race with GC // and once we add ourselves to the handle table map the GC can start walking // our handles and calling AD::RecordSurvivedBytes() which touches ARM data. - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) m_dwNumHeaps = CPUGroupInfo::CanEnableGCCPUGroups() ? CPUGroupInfo::GetNumActiveProcessors() : GetCurrentProcessCpuCount(); @@ -11110,7 +11110,7 @@ void AppDomain::Unload(BOOL fForceUnload) } if(bForceGC) { - GCHeap::GetGCHeap()->GarbageCollect(); + GCHeapUtilities::GetGCHeap()->GarbageCollect(); FinalizerThread::FinalizerThreadWait(); SetStage(STAGE_COLLECTED); Close(); //NOTHROW! @@ -11146,7 +11146,7 @@ void AppDomain::Unload(BOOL fForceUnload) { // do extra finalizer wait to remove any leftover sb entries FinalizerThread::FinalizerThreadWait(); - GCHeap::GetGCHeap()->GarbageCollect(); + GCHeapUtilities::GetGCHeap()->GarbageCollect(); FinalizerThread::FinalizerThreadWait(); LogSpewAlways("Done unload %3.3d\n", unloadCount); DumpSyncBlockCache(); @@ -11548,7 +11548,7 @@ void AppDomain::ClearGCHandles() SetStage(STAGE_HANDLETABLE_NOACCESS); - GCHeap::GetGCHeap()->WaitUntilConcurrentGCComplete(); + GCHeapUtilities::GetGCHeap()->WaitUntilConcurrentGCComplete(); // Keep async pin handles alive by moving them to default domain HandleAsyncPinHandles(); @@ -13516,8 +13516,8 @@ void SystemDomain::ProcessDelayedUnloadDomains() } CONTRACTL_END; - int iGCRefPoint=GCHeap::GetGCHeap()->CollectionCount(GCHeap::GetGCHeap()->GetMaxGeneration()); - if (GCHeap::GetGCHeap()->IsConcurrentGCInProgress()) + int iGCRefPoint=GCHeapUtilities::GetGCHeap()->CollectionCount(GCHeapUtilities::GetGCHeap()->GetMaxGeneration()); + if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCInProgress()) iGCRefPoint--; BOOL bAppDomainToCleanup = FALSE; @@ -13735,8 +13735,8 @@ void AppDomain::EnumStaticGCRefs(promote_func* fn, ScanContext* sc) } CONTRACT_END; - _ASSERTE(GCHeap::IsGCInProgress() && - GCHeap::IsServerHeap() && + _ASSERTE(GCHeapUtilities::IsGCInProgress() && + GCHeapUtilities::IsServerHeap() && IsGCSpecialThread()); AppDomain::AssemblyIterator asmIterator = IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution)); diff --git a/src/vm/appdomain.hpp b/src/vm/appdomain.hpp index 97e8438329..d766b3da43 100644 --- a/src/vm/appdomain.hpp +++ b/src/vm/appdomain.hpp @@ -30,6 +30,7 @@ #include "fptrstubs.h" #include "ilstubcache.h" #include "testhookmgr.h" +#include "gcheaputilities.h" #ifdef FEATURE_VERSIONING #include "../binder/inc/applicationcontext.hpp" #endif // FEATURE_VERSIONING @@ -1295,7 +1296,7 @@ public: { WRAPPER_NO_CONTRACT; OBJECTHANDLE h = ::CreateSizedRefHandle( - m_hHandleTableBucket->pTable[GCHeap::IsServerHeap() ? (m_dwSizedRefHandles % m_iNumberOfProcessors) : GetCurrentThreadHomeHeapNumber()], + m_hHandleTableBucket->pTable[GCHeapUtilities::IsServerHeap() ? (m_dwSizedRefHandles % m_iNumberOfProcessors) : GetCurrentThreadHomeHeapNumber()], object); InterlockedIncrement((LONG*)&m_dwSizedRefHandles); return h; @@ -4533,8 +4534,8 @@ public: if (m_UnloadIsAsync) { pDomain->AddRef(); - int iGCRefPoint=GCHeap::GetGCHeap()->CollectionCount(GCHeap::GetGCHeap()->GetMaxGeneration()); - if (GCHeap::GetGCHeap()->IsGCInProgress()) + int iGCRefPoint=GCHeapUtilities::GetGCHeap()->CollectionCount(GCHeapUtilities::GetGCHeap()->GetMaxGeneration()); + if (GCHeapUtilities::IsGCInProgress()) iGCRefPoint++; pDomain->SetGCRefPoint(iGCRefPoint); } @@ -4554,8 +4555,8 @@ public: pAllocator->m_pLoaderAllocatorDestroyNext=m_pDelayedUnloadListOfLoaderAllocators; m_pDelayedUnloadListOfLoaderAllocators=pAllocator; - int iGCRefPoint=GCHeap::GetGCHeap()->CollectionCount(GCHeap::GetGCHeap()->GetMaxGeneration()); - if (GCHeap::GetGCHeap()->IsGCInProgress()) + int iGCRefPoint=GCHeapUtilities::GetGCHeap()->CollectionCount(GCHeapUtilities::GetGCHeap()->GetMaxGeneration()); + if (GCHeapUtilities::IsGCInProgress()) iGCRefPoint++; pAllocator->SetGCRefPoint(iGCRefPoint); } diff --git a/src/vm/arm/asmconstants.h b/src/vm/arm/asmconstants.h index 47ebb2d24d..93af04734e 100644 --- a/src/vm/arm/asmconstants.h +++ b/src/vm/arm/asmconstants.h @@ -225,10 +225,10 @@ ASMCONSTANTS_C_ASSERT(UnmanagedToManagedFrame__m_pvDatum == offsetof(UnmanagedTo #ifndef CROSSGEN_COMPILE #define Thread__m_alloc_context__alloc_limit 0x44 -ASMCONSTANTS_C_ASSERT(Thread__m_alloc_context__alloc_limit == offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_limit)); +ASMCONSTANTS_C_ASSERT(Thread__m_alloc_context__alloc_limit == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_limit)); #define Thread__m_alloc_context__alloc_ptr 0x40 -ASMCONSTANTS_C_ASSERT(Thread__m_alloc_context__alloc_ptr == offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_ptr)); +ASMCONSTANTS_C_ASSERT(Thread__m_alloc_context__alloc_ptr == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr)); #endif // CROSSGEN_COMPILE #define Thread__m_fPreemptiveGCDisabled 0x08 diff --git a/src/vm/arm/stubs.cpp b/src/vm/arm/stubs.cpp index 0b069da47e..1309695f73 100644 --- a/src/vm/arm/stubs.cpp +++ b/src/vm/arm/stubs.cpp @@ -2650,7 +2650,7 @@ void InitJITHelpers1() )) { - _ASSERTE(GCHeap::UseAllocationContexts()); + _ASSERTE(GCHeapUtilities::UseAllocationContexts()); // If the TLS for Thread is low enough use the super-fast helpers if (gThreadTLSIndex < TLS_MINIMUM_AVAILABLE) { diff --git a/src/vm/ceeload.cpp b/src/vm/ceeload.cpp index 6dab63eefd..5699a29342 100644 --- a/src/vm/ceeload.cpp +++ b/src/vm/ceeload.cpp @@ -3427,8 +3427,8 @@ void Module::EnumRegularStaticGCRefs(AppDomain* pAppDomain, promote_func* fn, Sc } CONTRACT_END; - _ASSERTE(GCHeap::IsGCInProgress() && - GCHeap::IsServerHeap() && + _ASSERTE(GCHeapUtilities::IsGCInProgress() && + GCHeapUtilities::IsServerHeap() && IsGCSpecialThread()); @@ -6264,7 +6264,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile, BOOL onlyLoadedInAppDomain, BOOL #ifndef DACCESS_COMPILE #if defined(FEATURE_MULTIMODULE_ASSEMBLIES) // check if actually loaded, unless happens during GC (GC works only with loaded assemblies) - if (!GCHeap::IsGCInProgress() && onlyLoadedInAppDomain && pModule && !pModule->IsManifest()) + if (!GCHeapUtilities::IsGCInProgress() && onlyLoadedInAppDomain && pModule && !pModule->IsManifest()) { DomainModule *pDomainModule = pModule->FindDomainModule(GetAppDomain()); if (pDomainModule == NULL || !pDomainModule->IsLoaded()) diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp index 07781261f7..1a19e630e4 100644 --- a/src/vm/ceemain.cpp +++ b/src/vm/ceemain.cpp @@ -150,7 +150,7 @@ #include "frames.h" #include "threads.h" #include "stackwalk.h" -#include "gc.h" +#include "gcheaputilities.h" #include "interoputil.h" #include "security.h" #include "fieldmarshaler.h" @@ -640,7 +640,7 @@ void InitializeStartupFlags() g_fEnableARM = TRUE; #endif // !FEATURE_CORECLR - GCHeap::InitializeHeapType((flags & STARTUP_SERVER_GC) != 0); + InitializeHeapType((flags & STARTUP_SERVER_GC) != 0); #ifdef FEATURE_LOADER_OPTIMIZATION g_dwGlobalSharePolicy = (flags&STARTUP_LOADER_OPTIMIZATION_MASK)>>1; @@ -3719,7 +3719,8 @@ void InitializeGarbageCollector() g_pFreeObjectMethodTable->SetBaseSize(ObjSizeOf (ArrayBase)); g_pFreeObjectMethodTable->SetComponentSize(1); - GCHeap *pGCHeap = GCHeap::CreateGCHeap(); + IGCHeap *pGCHeap = InitializeGarbageCollector(nullptr); + g_pGCHeap = pGCHeap; if (!pGCHeap) ThrowOutOfMemory(); @@ -3833,7 +3834,7 @@ BOOL STDMETHODCALLTYPE EEDllMain( // TRUE on success, FALSE on error. { // GetThread() may be set to NULL for Win9x during shutdown. Thread *pThread = GetThread(); - if (GCHeap::IsGCInProgress() && + if (GCHeapUtilities::IsGCInProgress() && ( (pThread && (pThread != ThreadSuspend::GetSuspensionThread() )) || !g_fSuspendOnShutdown)) { diff --git a/src/vm/classcompat.cpp b/src/vm/classcompat.cpp index ac819941f9..50c56506a9 100644 --- a/src/vm/classcompat.cpp +++ b/src/vm/classcompat.cpp @@ -31,7 +31,7 @@ #include "log.h" #include "fieldmarshaler.h" #include "cgensys.h" -#include "gc.h" +#include "gcheaputilities.h" #include "security.h" #include "dbginterface.h" #include "comdelegate.h" diff --git a/src/vm/codeman.cpp b/src/vm/codeman.cpp index 89084dbe85..88bfd58e93 100644 --- a/src/vm/codeman.cpp +++ b/src/vm/codeman.cpp @@ -3397,7 +3397,7 @@ void ExecutionManager::CleanupCodeHeaps() } CONTRACTL_END; - _ASSERTE (g_fProcessDetach || (GCHeap::IsGCInProgress() && ::IsGCThread())); + _ASSERTE (g_fProcessDetach || (GCHeapUtilities::IsGCInProgress() && ::IsGCThread())); GetEEJitManager()->CleanupCodeHeaps(); } @@ -3411,7 +3411,7 @@ void EEJitManager::CleanupCodeHeaps() } CONTRACTL_END; - _ASSERTE (g_fProcessDetach || (GCHeap::IsGCInProgress() && ::IsGCThread())); + _ASSERTE (g_fProcessDetach || (GCHeapUtilities::IsGCInProgress() && ::IsGCThread())); CrstHolder ch(&m_CodeHeapCritSec); @@ -4451,7 +4451,7 @@ RangeSection* ExecutionManager::GetRangeSection(TADDR addr) // Unless we are on an MP system with many cpus // where this sort of caching actually diminishes scaling during server GC // due to many processors writing to a common location - if (g_SystemInfo.dwNumberOfProcessors < 4 || !GCHeap::IsServerHeap() || !GCHeap::IsGCInProgress()) + if (g_SystemInfo.dwNumberOfProcessors < 4 || !GCHeapUtilities::IsServerHeap() || !GCHeapUtilities::IsGCInProgress()) pHead->pLastUsed = pLast; #endif diff --git a/src/vm/commemoryfailpoint.cpp b/src/vm/commemoryfailpoint.cpp index 276a9f305a..4d1ed6ef64 100644 --- a/src/vm/commemoryfailpoint.cpp +++ b/src/vm/commemoryfailpoint.cpp @@ -26,7 +26,7 @@ FCIMPL2(void, COMMemoryFailPoint::GetMemorySettings, UINT64* pMaxGCSegmentSize, { FCALL_CONTRACT; - GCHeap * pGC = GCHeap::GetGCHeap(); + IGCHeap * pGC = GCHeapUtilities::GetGCHeap(); size_t segment_size = pGC->GetValidSegmentSize(FALSE); size_t large_segment_size = pGC->GetValidSegmentSize(TRUE); _ASSERTE(segment_size < SIZE_T_MAX && large_segment_size < SIZE_T_MAX); diff --git a/src/vm/common.h b/src/vm/common.h index 123350334b..9de9f35141 100644 --- a/src/vm/common.h +++ b/src/vm/common.h @@ -177,7 +177,7 @@ typedef DPTR(class StringBufferObject) PTR_StringBufferObject; typedef DPTR(class TypeHandle) PTR_TypeHandle; typedef VPTR(class VirtualCallStubManager) PTR_VirtualCallStubManager; typedef VPTR(class VirtualCallStubManagerManager) PTR_VirtualCallStubManagerManager; -typedef VPTR(class GCHeap) PTR_GCHeap; +typedef VPTR(class IGCHeap) PTR_IGCHeap; // // _UNCHECKED_OBJECTREF is for code that can't deal with DEBUG OBJECTREFs diff --git a/src/vm/comutilnative.cpp b/src/vm/comutilnative.cpp index b55c63549d..0f27542e1d 100644 --- a/src/vm/comutilnative.cpp +++ b/src/vm/comutilnative.cpp @@ -27,7 +27,7 @@ #include "frames.h" #include "field.h" #include "winwrap.h" -#include "gc.h" +#include "gcheaputilities.h" #include "fcall.h" #include "invokeutil.h" #include "eeconfig.h" @@ -1638,7 +1638,7 @@ FCIMPL0(int, GCInterface::GetGcLatencyMode) FC_GC_POLL_NOT_NEEDED(); - int result = (INT32)GCHeap::GetGCHeap()->GetGcLatencyMode(); + int result = (INT32)GCHeapUtilities::GetGCHeap()->GetGcLatencyMode(); return result; } FCIMPLEND @@ -1649,7 +1649,7 @@ FCIMPL1(int, GCInterface::SetGcLatencyMode, int newLatencyMode) FC_GC_POLL_NOT_NEEDED(); - return GCHeap::GetGCHeap()->SetGcLatencyMode(newLatencyMode); + return GCHeapUtilities::GetGCHeap()->SetGcLatencyMode(newLatencyMode); } FCIMPLEND @@ -1659,7 +1659,7 @@ FCIMPL0(int, GCInterface::GetLOHCompactionMode) FC_GC_POLL_NOT_NEEDED(); - int result = (INT32)GCHeap::GetGCHeap()->GetLOHCompactionMode(); + int result = (INT32)GCHeapUtilities::GetGCHeap()->GetLOHCompactionMode(); return result; } FCIMPLEND @@ -1670,7 +1670,7 @@ FCIMPL1(void, GCInterface::SetLOHCompactionMode, int newLOHCompactionyMode) FC_GC_POLL_NOT_NEEDED(); - GCHeap::GetGCHeap()->SetLOHCompactionMode(newLOHCompactionyMode); + GCHeapUtilities::GetGCHeap()->SetLOHCompactionMode(newLOHCompactionyMode); } FCIMPLEND @@ -1681,7 +1681,7 @@ FCIMPL2(FC_BOOL_RET, GCInterface::RegisterForFullGCNotification, UINT32 gen2Perc FC_GC_POLL_NOT_NEEDED(); - FC_RETURN_BOOL(GCHeap::GetGCHeap()->RegisterForFullGCNotification(gen2Percentage, lohPercentage)); + FC_RETURN_BOOL(GCHeapUtilities::GetGCHeap()->RegisterForFullGCNotification(gen2Percentage, lohPercentage)); } FCIMPLEND @@ -1690,7 +1690,7 @@ FCIMPL0(FC_BOOL_RET, GCInterface::CancelFullGCNotification) FCALL_CONTRACT; FC_GC_POLL_NOT_NEEDED(); - FC_RETURN_BOOL(GCHeap::GetGCHeap()->CancelFullGCNotification()); + FC_RETURN_BOOL(GCHeapUtilities::GetGCHeap()->CancelFullGCNotification()); } FCIMPLEND @@ -1711,7 +1711,7 @@ FCIMPL1(int, GCInterface::WaitForFullGCApproach, int millisecondsTimeout) HELPER_METHOD_FRAME_BEGIN_RET_0(); DWORD dwMilliseconds = ((millisecondsTimeout == -1) ? INFINITE : millisecondsTimeout); - result = GCHeap::GetGCHeap()->WaitForFullGCApproach(dwMilliseconds); + result = GCHeapUtilities::GetGCHeap()->WaitForFullGCApproach(dwMilliseconds); HELPER_METHOD_FRAME_END(); @@ -1736,7 +1736,7 @@ FCIMPL1(int, GCInterface::WaitForFullGCComplete, int millisecondsTimeout) HELPER_METHOD_FRAME_BEGIN_RET_0(); DWORD dwMilliseconds = ((millisecondsTimeout == -1) ? INFINITE : millisecondsTimeout); - result = GCHeap::GetGCHeap()->WaitForFullGCComplete(dwMilliseconds); + result = GCHeapUtilities::GetGCHeap()->WaitForFullGCComplete(dwMilliseconds); HELPER_METHOD_FRAME_END(); @@ -1757,7 +1757,7 @@ FCIMPL1(int, GCInterface::GetGeneration, Object* objUNSAFE) if (objUNSAFE == NULL) FCThrowArgumentNull(W("obj")); - int result = (INT32)GCHeap::GetGCHeap()->WhichGeneration(objUNSAFE); + int result = (INT32)GCHeapUtilities::GetGCHeap()->WhichGeneration(objUNSAFE); FC_GC_POLL_RET(); return result; } @@ -1777,7 +1777,7 @@ FCIMPL2(int, GCInterface::CollectionCount, INT32 generation, INT32 getSpecialGCC _ASSERTE(generation >= 0); //We don't need to check the top end because the GC will take care of that. - int result = (INT32)GCHeap::GetGCHeap()->CollectionCount(generation, getSpecialGCCount); + int result = (INT32)GCHeapUtilities::GetGCHeap()->CollectionCount(generation, getSpecialGCCount); FC_GC_POLL_RET(); return result; } @@ -1793,7 +1793,7 @@ int QCALLTYPE GCInterface::StartNoGCRegion(INT64 totalSize, BOOL lohSizeKnown, I GCX_COOP(); - retVal = GCHeap::GetGCHeap()->StartNoGCRegion((ULONGLONG)totalSize, + retVal = GCHeapUtilities::GetGCHeap()->StartNoGCRegion((ULONGLONG)totalSize, lohSizeKnown, (ULONGLONG)lohSize, disallowFullBlockingGC); @@ -1811,7 +1811,7 @@ int QCALLTYPE GCInterface::EndNoGCRegion() BEGIN_QCALL; - retVal = GCHeap::GetGCHeap()->EndNoGCRegion(); + retVal = GCHeapUtilities::GetGCHeap()->EndNoGCRegion(); END_QCALL; @@ -1837,7 +1837,7 @@ FCIMPL1(int, GCInterface::GetGenerationWR, LPVOID handle) if (temp == NULL) COMPlusThrowArgumentNull(W("weak handle")); - iRetVal = (INT32)GCHeap::GetGCHeap()->WhichGeneration(OBJECTREFToObject(temp)); + iRetVal = (INT32)GCHeapUtilities::GetGCHeap()->WhichGeneration(OBJECTREFToObject(temp)); HELPER_METHOD_FRAME_END(); @@ -1860,7 +1860,7 @@ INT64 QCALLTYPE GCInterface::GetTotalMemory() BEGIN_QCALL; GCX_COOP(); - iRetVal = (INT64) GCHeap::GetGCHeap()->GetTotalBytesInUse(); + iRetVal = (INT64) GCHeapUtilities::GetGCHeap()->GetTotalBytesInUse(); END_QCALL; @@ -1885,7 +1885,7 @@ void QCALLTYPE GCInterface::Collect(INT32 generation, INT32 mode) //We don't need to check the top end because the GC will take care of that. GCX_COOP(); - GCHeap::GetGCHeap()->GarbageCollect(generation, FALSE, mode); + GCHeapUtilities::GetGCHeap()->GarbageCollect(generation, FALSE, mode); END_QCALL; } @@ -1918,7 +1918,7 @@ FCIMPL0(int, GCInterface::GetMaxGeneration) { FCALL_CONTRACT; - return(INT32)GCHeap::GetGCHeap()->GetMaxGeneration(); + return(INT32)GCHeapUtilities::GetGCHeap()->GetMaxGeneration(); } FCIMPLEND @@ -1934,7 +1934,7 @@ FCIMPL0(INT64, GCInterface::GetAllocatedBytesForCurrentThread) INT64 currentAllocated = 0; Thread *pThread = GetThread(); - alloc_context* ac = pThread->GetAllocContext(); + gc_alloc_context* ac = pThread->GetAllocContext(); currentAllocated = ac->alloc_bytes + ac->alloc_bytes_loh - (ac->alloc_limit - ac->alloc_ptr); return currentAllocated; @@ -1956,7 +1956,7 @@ FCIMPL1(void, GCInterface::SuppressFinalize, Object *obj) if (!obj->GetMethodTable ()->HasFinalizer()) return; - GCHeap::GetGCHeap()->SetFinalizationRun(obj); + GCHeapUtilities::GetGCHeap()->SetFinalizationRun(obj); FC_GC_POLL(); } FCIMPLEND @@ -1977,7 +1977,7 @@ FCIMPL1(void, GCInterface::ReRegisterForFinalize, Object *obj) if (obj->GetMethodTable()->HasFinalizer()) { HELPER_METHOD_FRAME_BEGIN_1(obj); - GCHeap::GetGCHeap()->RegisterForFinalization(-1, obj); + GCHeapUtilities::GetGCHeap()->RegisterForFinalization(-1, obj); HELPER_METHOD_FRAME_END(); } } @@ -2079,7 +2079,7 @@ void GCInterface::AddMemoryPressure(UINT64 bytesAllocated) m_ulThreshold = (addMethod > multMethod) ? addMethod : multMethod; for (int i = 0; i <= 1; i++) { - if ((GCHeap::GetGCHeap()->CollectionCount(i) / RELATIVE_GC_RATIO) > GCHeap::GetGCHeap()->CollectionCount(i + 1)) + if ((GCHeapUtilities::GetGCHeap()->CollectionCount(i) / RELATIVE_GC_RATIO) > GCHeapUtilities::GetGCHeap()->CollectionCount(i + 1)) { gen_collect = i + 1; break; @@ -2089,14 +2089,14 @@ void GCInterface::AddMemoryPressure(UINT64 bytesAllocated) PREFIX_ASSUME(gen_collect <= 2); - if ((gen_collect == 0) || (m_gc_counts[gen_collect] == GCHeap::GetGCHeap()->CollectionCount(gen_collect))) + if ((gen_collect == 0) || (m_gc_counts[gen_collect] == GCHeapUtilities::GetGCHeap()->CollectionCount(gen_collect))) { GarbageCollectModeAny(gen_collect); } for (int i = 0; i < 3; i++) { - m_gc_counts [i] = GCHeap::GetGCHeap()->CollectionCount(i); + m_gc_counts [i] = GCHeapUtilities::GetGCHeap()->CollectionCount(i); } } } @@ -2115,7 +2115,7 @@ void GCInterface::CheckCollectionCount() { LIMITED_METHOD_CONTRACT; - GCHeap * pHeap = GCHeap::GetGCHeap(); + IGCHeap * pHeap = GCHeapUtilities::GetGCHeap(); if (m_gc_counts[2] != pHeap->CollectionCount(2)) { @@ -2200,7 +2200,7 @@ void GCInterface::NewAddMemoryPressure(UINT64 bytesAllocated) // If still over budget, check current managed heap size if (newMemValue >= budget) { - GCHeap *pGCHeap = GCHeap::GetGCHeap(); + IGCHeap *pGCHeap = GCHeapUtilities::GetGCHeap(); UINT64 heapOver3 = pGCHeap->GetCurrentObjSize() / 3; if (budget < heapOver3) // Max @@ -2274,7 +2274,7 @@ void GCInterface::RemoveMemoryPressure(UINT64 bytesAllocated) for (int i = 0; i < 3; i++) { - m_gc_counts [i] = GCHeap::GetGCHeap()->CollectionCount(i); + m_gc_counts [i] = GCHeapUtilities::GetGCHeap()->CollectionCount(i); } } } @@ -2348,7 +2348,7 @@ NOINLINE void GCInterface::GarbageCollectModeAny(int generation) CONTRACTL_END; GCX_COOP(); - GCHeap::GetGCHeap()->GarbageCollect(generation, FALSE, collection_non_blocking); + GCHeapUtilities::GetGCHeap()->GarbageCollect(generation, FALSE, collection_non_blocking); } // diff --git a/src/vm/corhost.cpp b/src/vm/corhost.cpp index c229a0ee07..6091bad9e2 100644 --- a/src/vm/corhost.cpp +++ b/src/vm/corhost.cpp @@ -5170,7 +5170,7 @@ public: HRESULT hr = S_OK; - if (Generation > (int) GCHeap::GetGCHeap()->GetMaxGeneration()) + if (Generation > (int) GCHeapUtilities::GetGCHeap()->GetMaxGeneration()) hr = E_INVALIDARG; if (SUCCEEDED(hr)) @@ -5188,7 +5188,7 @@ public: EX_TRY { STRESS_LOG0(LF_GC, LL_INFO100, "Host triggers GC\n"); - hr = GCHeap::GetGCHeap()->GarbageCollect(Generation); + hr = GCHeapUtilities::GetGCHeap()->GarbageCollect(Generation); } EX_CATCH { @@ -5354,7 +5354,7 @@ HRESULT CCLRGCManager::_SetGCSegmentSize(SIZE_T SegmentSize) HRESULT hr = S_OK; // Sanity check the value, it must be a power of two and big enough. - if (!GCHeap::IsValidSegmentSize(SegmentSize)) + if (!GCHeapUtilities::GetGCHeap()->IsValidSegmentSize(SegmentSize)) { hr = E_INVALIDARG; } @@ -5380,7 +5380,7 @@ HRESULT CCLRGCManager::_SetGCMaxGen0Size(SIZE_T MaxGen0Size) HRESULT hr = S_OK; // Sanity check the value is at least large enough. - if (!GCHeap::IsValidGen0MaxSize(MaxGen0Size)) + if (!GCHeapUtilities::GetGCHeap()->IsValidGen0MaxSize(MaxGen0Size)) { hr = E_INVALIDARG; } @@ -6408,7 +6408,7 @@ HRESULT CCLRDebugManager::SetConnectionTasks( } // Check for Finalizer thread - if (GCHeap::IsGCHeapInitialized() && (pThread == FinalizerThread::GetFinalizerThread())) + if (GCHeapUtilities::IsGCHeapInitialized() && (pThread == FinalizerThread::GetFinalizerThread())) { // _ASSERTE(!"Host should not try to schedule user code on our Finalizer Thread"); IfFailGo(E_INVALIDARG); diff --git a/src/vm/crossgencompile.cpp b/src/vm/crossgencompile.cpp index 85859c2d82..ffb025adb0 100644 --- a/src/vm/crossgencompile.cpp +++ b/src/vm/crossgencompile.cpp @@ -130,7 +130,7 @@ BOOL __SwitchToThread(DWORD, DWORD) // Globals and misc other // -GPTR_IMPL(GCHeap,g_pGCHeap); +GPTR_IMPL(IGCHeap,g_pGCHeap); BOOL g_fEEOtherStartup=FALSE; BOOL g_fEEComActivatedStartup=FALSE; @@ -138,7 +138,7 @@ BOOL g_fEEComActivatedStartup=FALSE; GVAL_IMPL_INIT(DWORD, g_fHostConfig, 0); #ifdef FEATURE_SVR_GC -SVAL_IMPL_INIT(uint32_t,GCHeap,gcHeapType,GCHeap::GC_HEAP_WKS); +SVAL_IMPL_INIT(uint32_t,IGCHeap,gcHeapType,IGCHeap::GC_HEAP_WKS); #endif void UpdateGCSettingFromHost() diff --git a/src/vm/crst.cpp b/src/vm/crst.cpp index a72ec9d3c0..7bf9bd65da 100644 --- a/src/vm/crst.cpp +++ b/src/vm/crst.cpp @@ -627,7 +627,7 @@ void CrstBase::PreEnter() || (pThread != NULL && pThread->PreemptiveGCDisabled()) // If GC heap has not been initialized yet, there is no need to synchronize with GC. // This check is mainly for code called from EEStartup. - || (pThread == NULL && !GCHeap::IsGCHeapInitialized()) ); + || (pThread == NULL && !GCHeapUtilities::IsGCHeapInitialized()) ); } if ((pThread != NULL) && @@ -910,7 +910,7 @@ BOOL CrstBase::IsSafeToTake() _ASSERTE(pThread == NULL || (pThread->PreemptiveGCDisabled() == ((m_dwFlags & CRST_UNSAFE_COOPGC) != 0)) || ((m_dwFlags & (CRST_UNSAFE_ANYMODE | CRST_GC_NOTRIGGER_WHEN_TAKEN)) != 0) || - (GCHeap::IsGCInProgress() && pThread == ThreadSuspend::GetSuspensionThread())); + (GCHeapUtilities::IsGCInProgress() && pThread == ThreadSuspend::GetSuspensionThread())); END_GETTHREAD_ALLOWED; if (m_holderthreadid.IsCurrentThread()) diff --git a/src/vm/debugdebugger.cpp b/src/vm/debugdebugger.cpp index 9ea5427dfe..64870fa419 100644 --- a/src/vm/debugdebugger.cpp +++ b/src/vm/debugdebugger.cpp @@ -22,7 +22,7 @@ #include "frames.h" #include "vars.hpp" #include "field.h" -#include "gc.h" +#include "gcheaputilities.h" #include "jitinterface.h" #include "debugdebugger.h" #include "dbginterface.h" diff --git a/src/vm/domainfile.cpp b/src/vm/domainfile.cpp index 2353712c9e..bfb69cdd48 100644 --- a/src/vm/domainfile.cpp +++ b/src/vm/domainfile.cpp @@ -4140,8 +4140,8 @@ void DomainAssembly::EnumStaticGCRefs(promote_func* fn, ScanContext* sc) } CONTRACT_END; - _ASSERTE(GCHeap::IsGCInProgress() && - GCHeap::IsServerHeap() && + _ASSERTE(GCHeapUtilities::IsGCInProgress() && + GCHeapUtilities::IsServerHeap() && IsGCSpecialThread()); DomainModuleIterator i = IterateModules(kModIterIncludeLoaded); diff --git a/src/vm/dwreport.cpp b/src/vm/dwreport.cpp index 77669b2f14..5ae4f84de2 100644 --- a/src/vm/dwreport.cpp +++ b/src/vm/dwreport.cpp @@ -3212,7 +3212,7 @@ FaultReportResult DoFaultReport( // Was Watson attempted, successful? // thread under Coop mode, this will let the new generated DoFaultReportCallBack // thread trigger a deadlock. So in this case, we should directly abort the fault // report to avoid the deadlock. - ((IsGCThread() || pThread->PreemptiveGCDisabled()) && GCHeap::IsGCInProgress()) || + ((IsGCThread() || pThread->PreemptiveGCDisabled()) && GCHeapUtilities::IsGCInProgress()) || FAILED(g_pDebugInterface->RequestFavor(DoFaultReportFavorWorker, pData))) { // If we can't initialize the debugger helper thread or we are running on the debugger helper diff --git a/src/vm/eetoprofinterfaceimpl.cpp b/src/vm/eetoprofinterfaceimpl.cpp index 2ec3812159..fdc725b1d8 100644 --- a/src/vm/eetoprofinterfaceimpl.cpp +++ b/src/vm/eetoprofinterfaceimpl.cpp @@ -2294,7 +2294,7 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask // in this function if (g_profControlBlock.curProfStatus.Get() == kProfStatusInitializingForAttachLoad) { - if (GCHeap::GetGCHeap()->IsConcurrentGCEnabled()) + if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()) { // We only allow turning off concurrent GC in the profiler attach thread inside // InitializeForAttach, otherwise we would be vulnerable to weird races such as @@ -2316,7 +2316,7 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask // Fail if concurrent GC is enabled // This should only happen for attach profilers if user didn't turn on COR_PRF_MONITOR_GC // at attach time - if (GCHeap::GetGCHeap()->IsConcurrentGCEnabled()) + if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()) { return CORPROF_E_CONCURRENT_GC_NOT_PROFILABLE; } @@ -2384,7 +2384,7 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask if (fNeedToTurnOffConcurrentGC) { // Turn off concurrent GC if it is on so that user can walk the heap safely in GC callbacks - GCHeap * pGCHeap = GCHeap::GetGCHeap(); + IGCHeap * pGCHeap = GCHeapUtilities::GetGCHeap(); LOG((LF_CORPROF, LL_INFO10, "**PROF: Turning off concurrent GC at attach.\n")); @@ -5609,7 +5609,7 @@ HRESULT EEToProfInterfaceImpl::MovedReferences(GCReferencesData *pData) LL_INFO10000, "**PROF: MovedReferences.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); if (pData->curIdx == 0) { @@ -5805,7 +5805,7 @@ HRESULT EEToProfInterfaceImpl::ObjectReference(ObjectID objId, LL_INFO100000, "**PROF: ObjectReferences.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); { // All callbacks are really NOTHROW, but that's enforced partially by the profiler, @@ -5844,7 +5844,7 @@ HRESULT EEToProfInterfaceImpl::FinalizeableObjectQueued(BOOL isCritical, ObjectI LL_INFO100, "**PROF: Notifying profiler of finalizeable object.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); { // All callbacks are really NOTHROW, but that's enforced partially by the profiler, @@ -5883,7 +5883,7 @@ HRESULT EEToProfInterfaceImpl::RootReferences2(GCReferencesData *pData) LL_INFO10000, "**PROF: RootReferences2.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); HRESULT hr = S_OK; @@ -5948,7 +5948,7 @@ HRESULT EEToProfInterfaceImpl::ConditionalWeakTableElementReferences(GCReference LL_INFO10000, "**PROF: ConditionalWeakTableElementReferences.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); HRESULT hr = S_OK; @@ -6082,7 +6082,7 @@ HRESULT EEToProfInterfaceImpl::GarbageCollectionStarted(int cGenerations, BOOL g LL_INFO10000, "**PROF: GarbageCollectionStarted.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); { // All callbacks are really NOTHROW, but that's enforced partially by the profiler, @@ -6120,7 +6120,7 @@ HRESULT EEToProfInterfaceImpl::GarbageCollectionFinished() LL_INFO10000, "**PROF: GarbageCollectionFinished.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); { // All callbacks are really NOTHROW, but that's enforced partially by the profiler, diff --git a/src/vm/eventtrace.cpp b/src/vm/eventtrace.cpp index d8702a53e1..b126fb07a4 100644 --- a/src/vm/eventtrace.cpp +++ b/src/vm/eventtrace.cpp @@ -431,19 +431,19 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::SaveCurrentStack(int skip VOID ETW::GCLog::GCSettingsEvent() { - if (GCHeap::IsGCHeapInitialized()) + if (GCHeapUtilities::IsGCHeapInitialized()) { if (ETW_TRACING_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, GCSettings)) { ETW::GCLog::ETW_GC_INFO Info; - Info.GCSettings.ServerGC = GCHeap::IsServerHeap (); - Info.GCSettings.SegmentSize = GCHeap::GetGCHeap()->GetValidSegmentSize (FALSE); - Info.GCSettings.LargeObjectSegmentSize = GCHeap::GetGCHeap()->GetValidSegmentSize (TRUE); + Info.GCSettings.ServerGC = GCHeapUtilities::IsServerHeap (); + Info.GCSettings.SegmentSize = GCHeapUtilities::GetGCHeap()->GetValidSegmentSize (FALSE); + Info.GCSettings.LargeObjectSegmentSize = GCHeapUtilities::GetGCHeap()->GetValidSegmentSize (TRUE); FireEtwGCSettings_V1(Info.GCSettings.SegmentSize, Info.GCSettings.LargeObjectSegmentSize, Info.GCSettings.ServerGC, GetClrInstanceId()); } - GCHeap::GetGCHeap()->TraceGCSegments(); + GCHeapUtilities::GetGCHeap()->TraceGCSegments(); } }; @@ -892,7 +892,7 @@ VOID ETW::GCLog::FireGcStartAndGenerationRanges(ETW_GC_INFO * pGcInfo) // GCStart, then retrieve it LONGLONG l64ClientSequenceNumberToLog = 0; if ((s_l64LastClientSequenceNumber != 0) && - (pGcInfo->GCStart.Depth == GCHeap::GetMaxGeneration()) && + (pGcInfo->GCStart.Depth == GCHeapUtilities::GetGCHeap()->GetMaxGeneration()) && (pGcInfo->GCStart.Reason == ETW_GC_INFO::GC_INDUCED)) { l64ClientSequenceNumberToLog = InterlockedExchange64(&s_l64LastClientSequenceNumber, 0); @@ -901,7 +901,7 @@ VOID ETW::GCLog::FireGcStartAndGenerationRanges(ETW_GC_INFO * pGcInfo) FireEtwGCStart_V2(pGcInfo->GCStart.Count, pGcInfo->GCStart.Depth, pGcInfo->GCStart.Reason, pGcInfo->GCStart.Type, GetClrInstanceId(), l64ClientSequenceNumberToLog); // Fire an event per range per generation - GCHeap *hp = GCHeap::GetGCHeap(); + IGCHeap *hp = GCHeapUtilities::GetGCHeap(); hp->DescrGenerationsToProfiler(FireSingleGenerationRangeEvent, NULL /* context */); } } @@ -928,7 +928,7 @@ VOID ETW::GCLog::FireGcEndAndGenerationRanges(ULONG Count, ULONG Depth) CLR_GC_KEYWORD)) { // Fire an event per range per generation - GCHeap *hp = GCHeap::GetGCHeap(); + IGCHeap *hp = GCHeapUtilities::GetGCHeap(); hp->DescrGenerationsToProfiler(FireSingleGenerationRangeEvent, NULL /* context */); // GCEnd @@ -938,7 +938,7 @@ VOID ETW::GCLog::FireGcEndAndGenerationRanges(ULONG Count, ULONG Depth) //--------------------------------------------------------------------------------------- // -// Callback made by GC when we call GCHeap::DescrGenerationsToProfiler(). This is +// Callback made by GC when we call GCHeapUtilities::DescrGenerationsToProfiler(). This is // called once per range per generation, and results in a single ETW event per range per // generation. // @@ -1033,7 +1033,7 @@ HRESULT ETW::GCLog::ForceGCForDiagnostics() ForcedGCHolder forcedGCHolder; - hr = GCHeap::GetGCHeap()->GarbageCollect( + hr = GCHeapUtilities::GetGCHeap()->GarbageCollect( -1, // all generations should be collected FALSE, // low_memory_p collection_blocking); diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp index 672f315fcd..d26f2d62d8 100644 --- a/src/vm/excep.cpp +++ b/src/vm/excep.cpp @@ -20,7 +20,7 @@ #include "cgensys.h" #include "comutilnative.h" #include "siginfo.hpp" -#include "gc.h" +#include "gcheaputilities.h" #include "eedbginterfaceimpl.h" //so we can clearexception in RealCOMPlusThrow #include "perfcounters.h" #include "dllimportcallback.h" diff --git a/src/vm/finalizerthread.cpp b/src/vm/finalizerthread.cpp index 5d51d33cfb..2f72b07957 100644 --- a/src/vm/finalizerthread.cpp +++ b/src/vm/finalizerthread.cpp @@ -295,7 +295,7 @@ Object * FinalizerThread::FinalizeAllObjects(Object* fobj, int bitToCheck) { return NULL; } - fobj = GCHeap::GetGCHeap()->GetNextFinalizable(); + fobj = GCHeapUtilities::GetGCHeap()->GetNextFinalizable(); } Thread *pThread = GetThread(); @@ -320,7 +320,7 @@ Object * FinalizerThread::FinalizeAllObjects(Object* fobj, int bitToCheck) { return NULL; } - fobj = GCHeap::GetGCHeap()->GetNextFinalizable(); + fobj = GCHeapUtilities::GetGCHeap()->GetNextFinalizable(); } else { @@ -337,7 +337,7 @@ Object * FinalizerThread::FinalizeAllObjects(Object* fobj, int bitToCheck) { return NULL; } - fobj = GCHeap::GetGCHeap()->GetNextFinalizable(); + fobj = GCHeapUtilities::GetGCHeap()->GetNextFinalizable(); } } } @@ -533,7 +533,7 @@ void FinalizerThread::WaitForFinalizerEvent (CLREvent *event) case (WAIT_OBJECT_0 + kLowMemoryNotification): //short on memory GC immediately GetFinalizerThread()->DisablePreemptiveGC(); - GCHeap::GetGCHeap()->GarbageCollect(0, TRUE); + GCHeapUtilities::GetGCHeap()->GarbageCollect(0, TRUE); GetFinalizerThread()->EnablePreemptiveGC(); //wait only on the event for 2s switch (event->Wait(2000, FALSE)) @@ -584,7 +584,7 @@ void FinalizerThread::WaitForFinalizerEvent (CLREvent *event) if (WaitForSingleObject(MHandles[kLowMemoryNotification], 0) == WAIT_OBJECT_0) { //short on memory GC immediately GetFinalizerThread()->DisablePreemptiveGC(); - GCHeap::GetGCHeap()->GarbageCollect(0, TRUE); + GCHeapUtilities::GetGCHeap()->GarbageCollect(0, TRUE); GetFinalizerThread()->EnablePreemptiveGC(); } //wait only on the event for 2s @@ -604,7 +604,7 @@ void FinalizerThread::WaitForFinalizerEvent (CLREvent *event) if (sLastLowMemoryFromHost != 0) { GetFinalizerThread()->DisablePreemptiveGC(); - GCHeap::GetGCHeap()->GarbageCollect(0, TRUE); + GCHeapUtilities::GetGCHeap()->GarbageCollect(0, TRUE); GetFinalizerThread()->EnablePreemptiveGC(); } } @@ -677,7 +677,7 @@ VOID FinalizerThread::FinalizerThreadWorker(void *args) { s_forcedGCInProgress = true; GetFinalizerThread()->DisablePreemptiveGC(); - GCHeap::GetGCHeap()->GarbageCollect(2, FALSE, collection_blocking); + GCHeapUtilities::GetGCHeap()->GarbageCollect(2, FALSE, collection_blocking); GetFinalizerThread()->EnablePreemptiveGC(); s_forcedGCInProgress = false; @@ -710,14 +710,14 @@ VOID FinalizerThread::FinalizerThreadWorker(void *args) do { - last_gc_count = GCHeap::GetGCHeap()->CollectionCount(0); + last_gc_count = GCHeapUtilities::GetGCHeap()->CollectionCount(0); GetFinalizerThread()->m_GCOnTransitionsOK = FALSE; GetFinalizerThread()->EnablePreemptiveGC(); __SwitchToThread (0, ++dwSwitchCount); GetFinalizerThread()->DisablePreemptiveGC(); // If no GCs happended, then we assume we are quiescent GetFinalizerThread()->m_GCOnTransitionsOK = TRUE; - } while (GCHeap::GetGCHeap()->CollectionCount(0) - last_gc_count > 0); + } while (GCHeapUtilities::GetGCHeap()->CollectionCount(0) - last_gc_count > 0); } #endif //_DEBUG @@ -747,7 +747,7 @@ VOID FinalizerThread::FinalizerThreadWorker(void *args) } else if (UnloadingAppDomain == NULL) break; - else if (!GCHeap::GetGCHeap()->FinalizeAppDomain(UnloadingAppDomain, fRunFinalizersOnUnload)) + else if (!GCHeapUtilities::GetGCHeap()->FinalizeAppDomain(UnloadingAppDomain, fRunFinalizersOnUnload)) { break; } @@ -916,7 +916,7 @@ DWORD __stdcall FinalizerThread::FinalizerThreadStart(void *args) if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_FinalizeOnShutdown) != 0) { // Finalize all registered objects during shutdown, even they are still reachable. - GCHeap::GetGCHeap()->SetFinalizeQueueForShutdown(FALSE); + GCHeapUtilities::GetGCHeap()->SetFinalizeQueueForShutdown(FALSE); // This will apply any policy for swallowing exceptions during normal // processing, without allowing the finalizer thread to disappear on us. @@ -1380,7 +1380,7 @@ BOOL FinalizerThread::FinalizerThreadWatchDogHelper() } else { - prevCount = GCHeap::GetGCHeap()->GetNumberOfFinalizable(); + prevCount = GCHeapUtilities::GetGCHeap()->GetNumberOfFinalizable(); } DWORD maxTry = (DWORD)(totalWaitTimeout*1.0/FINALIZER_WAIT_TIMEOUT + 0.5); @@ -1447,11 +1447,11 @@ BOOL FinalizerThread::FinalizerThreadWatchDogHelper() } else { - curCount = GCHeap::GetGCHeap()->GetNumberOfFinalizable(); + curCount = GCHeapUtilities::GetGCHeap()->GetNumberOfFinalizable(); } if ((prevCount <= curCount) - && !GCHeap::GetGCHeap()->ShouldRestartFinalizerWatchDog() + && !GCHeapUtilities::GetGCHeap()->ShouldRestartFinalizerWatchDog() && (pThread == NULL || !(pThread->m_State & (Thread::TS_UserSuspendPending | Thread::TS_DebugSuspendPending)))){ if (nTry == maxTry) { if (!s_fRaiseExitProcessEvent) { diff --git a/src/vm/frames.cpp b/src/vm/frames.cpp index ec7e7be63c..04a1815cf3 100644 --- a/src/vm/frames.cpp +++ b/src/vm/frames.cpp @@ -18,7 +18,7 @@ #include "fieldmarshaler.h" #include "objecthandle.h" #include "siginfo.hpp" -#include "gc.h" +#include "gcheaputilities.h" #include "dllimportcallback.h" #include "stackwalk.h" #include "dbginterface.h" diff --git a/src/vm/gccover.cpp b/src/vm/gccover.cpp index 41dc094e94..89f271cdd0 100644 --- a/src/vm/gccover.cpp +++ b/src/vm/gccover.cpp @@ -1234,8 +1234,8 @@ void checkAndUpdateReg(DWORD& origVal, DWORD curVal, bool gcHappened) { // the validation infrastructure has got a bug. _ASSERTE(gcHappened); // If the register values are different, a GC must have happened - _ASSERTE(GCHeap::GetGCHeap()->IsHeapPointer((BYTE*) size_t(origVal))); // And the pointers involved are on the GCHeap - _ASSERTE(GCHeap::GetGCHeap()->IsHeapPointer((BYTE*) size_t(curVal))); + _ASSERTE(GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE*) size_t(origVal))); // And the pointers involved are on the GCHeap + _ASSERTE(GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE*) size_t(curVal))); origVal = curVal; // this is now the best estimate of what should be returned. } @@ -1478,7 +1478,7 @@ void DoGcStress (PCONTEXT regs, MethodDesc *pMD) if (gcCover->callerThread == 0) { if (FastInterlockCompareExchangePointer(&gcCover->callerThread, pThread, 0) == 0) { gcCover->callerRegs = *regs; - gcCover->gcCount = GCHeap::GetGCHeap()->GetGcCount(); + gcCover->gcCount = GCHeapUtilities::GetGCHeap()->GetGcCount(); bShouldUpdateProlog = false; } } @@ -1564,13 +1564,13 @@ void DoGcStress (PCONTEXT regs, MethodDesc *pMD) // instruction in the epilog (TODO: fix it for the first instr Case) _ASSERTE(pThread->PreemptiveGCDisabled()); // Epilogs should be in cooperative mode, no GC can happen right now. - bool gcHappened = gcCover->gcCount != GCHeap::GetGCHeap()->GetGcCount(); + bool gcHappened = gcCover->gcCount != GCHeapUtilities::GetGCHeap()->GetGcCount(); checkAndUpdateReg(gcCover->callerRegs.Edi, *regDisp.pEdi, gcHappened); checkAndUpdateReg(gcCover->callerRegs.Esi, *regDisp.pEsi, gcHappened); checkAndUpdateReg(gcCover->callerRegs.Ebx, *regDisp.pEbx, gcHappened); checkAndUpdateReg(gcCover->callerRegs.Ebp, *regDisp.pEbp, gcHappened); - gcCover->gcCount = GCHeap::GetGCHeap()->GetGcCount(); + gcCover->gcCount = GCHeapUtilities::GetGCHeap()->GetGcCount(); } return; @@ -1777,7 +1777,7 @@ void DoGcStress (PCONTEXT regs, MethodDesc *pMD) // Do the actual stress work // - if (!GCHeap::GetGCHeap()->StressHeap()) + if (!GCHeapUtilities::GetGCHeap()->StressHeap()) UpdateGCStressInstructionWithoutGC (); // Must flush instruction cache before returning as instruction has been modified. diff --git a/src/vm/gcenv.ee.cpp b/src/vm/gcenv.ee.cpp index 2f1e4e8200..8dc1692643 100644 --- a/src/vm/gcenv.ee.cpp +++ b/src/vm/gcenv.ee.cpp @@ -550,7 +550,7 @@ void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen, STRESS_LOG1(LF_GCROOTS, LL_INFO10, "GCScan: Promotion Phase = %d\n", sc->promotion); // In server GC, we should be competing for marking the statics - if (GCHeap::MarkShouldCompeteForStatics()) + if (GCHeapUtilities::MarkShouldCompeteForStatics()) { if (condemned == max_gen && sc->promotion) { @@ -563,7 +563,7 @@ void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen, { STRESS_LOG2(LF_GC | LF_GCROOTS, LL_INFO100, "{ Starting scan of Thread %p ID = %x\n", pThread, pThread->GetThreadId()); - if (GCHeap::GetGCHeap()->IsThreadUsingAllocationContextHeap( + if (GCHeapUtilities::GetGCHeap()->IsThreadUsingAllocationContextHeap( GCToEEInterface::GetAllocContext(pThread), sc->thread_number)) { sc->thread_under_crawl = pThread; @@ -693,7 +693,7 @@ void GCToEEInterface::SyncBlockCachePromotionsGranted(int max_gen) SyncBlockCache::GetSyncBlockCache()->GCDone(FALSE, max_gen); } -alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread) +gc_alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread) { WRAPPER_NO_CONTRACT; return pThread->GetAllocContext(); diff --git a/src/vm/gcheaputilities.cpp b/src/vm/gcheaputilities.cpp new file mode 100644 index 0000000000..ceadb9ea42 --- /dev/null +++ b/src/vm/gcheaputilities.cpp @@ -0,0 +1,9 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "common.h" +#include "gcheaputilities.h" + +// This is the global GC heap, maintained by the VM. +GPTR_IMPL(IGCHeap, g_pGCHeap);
\ No newline at end of file diff --git a/src/vm/gcheaputilities.h b/src/vm/gcheaputilities.h new file mode 100644 index 0000000000..6e08472a2f --- /dev/null +++ b/src/vm/gcheaputilities.h @@ -0,0 +1,110 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _GCHEAPUTILITIES_H_ +#define _GCHEAPUTILITIES_H_ + +#include "gcinterface.h" + +// The singular heap instance. +GPTR_DECL(IGCHeap, g_pGCHeap); + +// GCHeapUtilities provides a number of static methods +// that operate on the global heap instance. It can't be +// instantiated. +class GCHeapUtilities { +public: + // Retrieves the GC heap. + inline static IGCHeap* GetGCHeap() + { + assert(g_pGCHeap != nullptr); + return g_pGCHeap; + } + + // Returns true if the heap has been initialized, false otherwise. + inline static bool IsGCHeapInitialized() + { + return g_pGCHeap != nullptr; + } + + // Returns true if a the heap is initialized and a garbage collection + // is in progress, false otherwise. + inline static BOOL IsGCInProgress(BOOL bConsiderGCStart = FALSE) + { + WRAPPER_NO_CONTRACT; + + return (IsGCHeapInitialized() ? GetGCHeap()->IsGCInProgressHelper(bConsiderGCStart) : false); + } + + // Returns true if we should be competing marking for statics. This + // influences the behavior of `GCToEEInterface::GcScanRoots`. + inline static BOOL MarkShouldCompeteForStatics() + { + WRAPPER_NO_CONTRACT; + + return IsServerHeap() && g_SystemInfo.dwNumberOfProcessors >= 2; + } + + // Waits until a GC is complete, if the heap has been initialized. + inline static void WaitForGCCompletion(BOOL bConsiderGCStart = FALSE) + { + WRAPPER_NO_CONTRACT; + + if (IsGCHeapInitialized()) + GetGCHeap()->WaitUntilGCComplete(bConsiderGCStart); + } + + // Returns true if we should be using allocation contexts, false otherwise. + inline static bool UseAllocationContexts() + { + WRAPPER_NO_CONTRACT; +#ifdef FEATURE_REDHAWK + // SIMPLIFY: only use allocation contexts + return true; +#else +#if defined(_TARGET_ARM_) || defined(FEATURE_PAL) + return true; +#else + return ((IsServerHeap() ? true : (g_SystemInfo.dwNumberOfProcessors >= 2))); +#endif +#endif + } + + // Returns true if the held GC heap is a Server GC heap, false otherwise. + inline static bool IsServerHeap() + { + LIMITED_METHOD_CONTRACT; +#ifdef FEATURE_SVR_GC + _ASSERTE(IGCHeap::gcHeapType != IGCHeap::GC_HEAP_INVALID); + return (IGCHeap::gcHeapType == IGCHeap::GC_HEAP_SVR); +#else // FEATURE_SVR_GC + return false; +#endif // FEATURE_SVR_GC + } + + // Gets the maximum generation number by reading the static field + // on IGCHeap. This should only be done by the DAC code paths - all other code + // should go through IGCHeap::GetMaxGeneration. + // + // The reason for this is that, while we are in the early stages of + // decoupling the GC, the GC and the DAC still remain tightly coupled + // and, in particular, the DAC needs to know how many generations the GC + // has. However, it is not permitted to invoke virtual methods on g_pGCHeap + // while on a DAC code path. Therefore, we need to determine the max generation + // non-virtually, while still in a manner consistent with the interface - + // therefore, a static field is used. + // + // This is not without precedent - IGCHeap::gcHeapType is a static field used + // for a similar reason (the DAC needs to know what kind of heap it's looking at). + inline static unsigned GetMaxGeneration() + { + return IGCHeap::maxGeneration; + } + +private: + // This class should never be instantiated. + GCHeapUtilities() = delete; +}; + +#endif // _GCHEAPUTILITIES_H_
\ No newline at end of file diff --git a/src/vm/gchelpers.cpp b/src/vm/gchelpers.cpp index bf81847716..9b0a17fbb4 100644 --- a/src/vm/gchelpers.cpp +++ b/src/vm/gchelpers.cpp @@ -16,7 +16,7 @@ #include "threads.h" #include "eetwain.h" #include "eeconfig.h" -#include "gc.h" +#include "gcheaputilities.h" #include "corhost.h" #include "threads.h" #include "fieldmarshaler.h" @@ -51,11 +51,11 @@ orObject = (ArrayBase *) OBJECTREFToObject(objref); -inline alloc_context* GetThreadAllocContext() +inline gc_alloc_context* GetThreadAllocContext() { WRAPPER_NO_CONTRACT; - assert(GCHeap::UseAllocationContexts()); + assert(GCHeapUtilities::UseAllocationContexts()); return & GetThread()->m_alloc_context; } @@ -102,10 +102,10 @@ inline Object* Alloc(size_t size, BOOL bFinalize, BOOL bContainsPointers ) // We don't want to throw an SO during the GC, so make sure we have plenty // of stack before calling in. INTERIOR_STACK_PROBE_FOR(GetThread(), static_cast<unsigned>(DEFAULT_ENTRY_PROBE_AMOUNT * 1.5)); - if (GCHeap::UseAllocationContexts()) - retVal = GCHeap::GetGCHeap()->Alloc(GetThreadAllocContext(), size, flags); + if (GCHeapUtilities::UseAllocationContexts()) + retVal = GCHeapUtilities::GetGCHeap()->Alloc(GetThreadAllocContext(), size, flags); else - retVal = GCHeap::GetGCHeap()->Alloc(size, flags); + retVal = GCHeapUtilities::GetGCHeap()->Alloc(size, flags); END_INTERIOR_STACK_PROBE; return retVal; } @@ -130,10 +130,10 @@ inline Object* AllocAlign8(size_t size, BOOL bFinalize, BOOL bContainsPointers, // We don't want to throw an SO during the GC, so make sure we have plenty // of stack before calling in. INTERIOR_STACK_PROBE_FOR(GetThread(), static_cast<unsigned>(DEFAULT_ENTRY_PROBE_AMOUNT * 1.5)); - if (GCHeap::UseAllocationContexts()) - retVal = GCHeap::GetGCHeap()->AllocAlign8(GetThreadAllocContext(), size, flags); + if (GCHeapUtilities::UseAllocationContexts()) + retVal = GCHeapUtilities::GetGCHeap()->AllocAlign8(GetThreadAllocContext(), size, flags); else - retVal = GCHeap::GetGCHeap()->AllocAlign8(size, flags); + retVal = GCHeapUtilities::GetGCHeap()->AllocAlign8(size, flags); END_INTERIOR_STACK_PROBE; return retVal; @@ -173,7 +173,7 @@ inline Object* AllocLHeap(size_t size, BOOL bFinalize, BOOL bContainsPointers ) // We don't want to throw an SO during the GC, so make sure we have plenty // of stack before calling in. INTERIOR_STACK_PROBE_FOR(GetThread(), static_cast<unsigned>(DEFAULT_ENTRY_PROBE_AMOUNT * 1.5)); - retVal = GCHeap::GetGCHeap()->AllocLHeap(size, flags); + retVal = GCHeapUtilities::GetGCHeap()->AllocLHeap(size, flags); END_INTERIOR_STACK_PROBE; return retVal; } @@ -427,7 +427,7 @@ OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, B if (bAllocateInLargeHeap || (totalSize >= LARGE_OBJECT_SIZE)) { - GCHeap::GetGCHeap()->PublishObject((BYTE*)orArray); + GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orArray); } #ifdef _LOGALLOC @@ -651,7 +651,7 @@ OBJECTREF FastAllocatePrimitiveArray(MethodTable* pMT, DWORD cElements, BOOL b if (bPublish) { - GCHeap::GetGCHeap()->PublishObject((BYTE*)orObject); + GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject); } // Notify the profiler of the allocation @@ -860,7 +860,7 @@ STRINGREF SlowAllocateString( DWORD cchStringLength ) if (ObjectSize >= LARGE_OBJECT_SIZE) { - GCHeap::GetGCHeap()->PublishObject((BYTE*)orObject); + GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject); } // Notify the profiler of the allocation @@ -1000,7 +1000,7 @@ OBJECTREF AllocateObject(MethodTable *pMT if ((baseSize >= LARGE_OBJECT_SIZE)) { orObject->SetMethodTableForLargeObject(pMT); - GCHeap::GetGCHeap()->PublishObject((BYTE*)orObject); + GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject); } else { @@ -1234,7 +1234,7 @@ extern "C" HCIMPL2_RAW(VOID, JIT_WriteBarrier, Object **dst, Object *ref) *dst = ref; // If the store above succeeded, "dst" should be in the heap. - assert(GCHeap::GetGCHeap()->IsHeapPointer((void*)dst)); + assert(GCHeapUtilities::GetGCHeap()->IsHeapPointer((void*)dst)); #ifdef WRITE_BARRIER_CHECK updateGCShadow(dst, ref); // support debugging write barrier @@ -1280,7 +1280,7 @@ extern "C" HCIMPL2_RAW(VOID, JIT_WriteBarrierEnsureNonHeapTarget, Object **dst, STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_NOTRIGGER; - assert(!GCHeap::GetGCHeap()->IsHeapPointer((void*)dst)); + assert(!GCHeapUtilities::GetGCHeap()->IsHeapPointer((void*)dst)); // no HELPER_METHOD_FRAME because we are MODE_COOPERATIVE, GC_NOTRIGGER diff --git a/src/vm/gchost.cpp b/src/vm/gchost.cpp index 4f7d52f805..f20b438a0b 100644 --- a/src/vm/gchost.cpp +++ b/src/vm/gchost.cpp @@ -22,7 +22,7 @@ #include "corhost.h" #include "excep.h" #include "field.h" -#include "gc.h" +#include "gcheaputilities.h" #if !defined(FEATURE_CORECLR) inline size_t SizeInKBytes(size_t cbSize) @@ -48,7 +48,7 @@ HRESULT CorGCHost::_SetGCSegmentSize(SIZE_T SegmentSize) HRESULT hr = S_OK; // Sanity check the value, it must be a power of two and big enough. - if (!GCHeap::IsValidSegmentSize(SegmentSize)) + if (!GCHeapUtilities::IsValidSegmentSize(SegmentSize)) { hr = E_INVALIDARG; } @@ -74,7 +74,7 @@ HRESULT CorGCHost::_SetGCMaxGen0Size(SIZE_T MaxGen0Size) HRESULT hr = S_OK; // Sanity check the value is at least large enough. - if (!GCHeap::IsValidGen0MaxSize(MaxGen0Size)) + if (!GCHeapUtilities::IsValidGen0MaxSize(MaxGen0Size)) { hr = E_INVALIDARG; } @@ -151,7 +151,7 @@ HRESULT CorGCHost::Collect( HRESULT hr = E_FAIL; - if (Generation > (int) GCHeap::GetGCHeap()->GetMaxGeneration()) + if (Generation > (int) GCHeapUtilities::GetGCHeap()->GetMaxGeneration()) hr = E_INVALIDARG; else { @@ -170,7 +170,7 @@ HRESULT CorGCHost::Collect( EX_TRY { - hr = GCHeap::GetGCHeap()->GarbageCollect(Generation); + hr = GCHeapUtilities::GetGCHeap()->GarbageCollect(Generation); } EX_CATCH { @@ -268,7 +268,7 @@ HRESULT CorGCHost::SetVirtualMemLimit( } CONTRACTL_END; - GCHeap::GetGCHeap()->SetReservedVMLimit (sztMaxVirtualMemMB); + GCHeapUtilities::GetGCHeap()->SetReservedVMLimit (sztMaxVirtualMemMB); return (S_OK); } #endif // !defined(FEATURE_CORECLR) diff --git a/src/vm/gc.h b/src/vm/gcinterface.h index 825b5da803..cc70becdf1 100644 --- a/src/vm/gc.h +++ b/src/vm/gcinterface.h @@ -2,4 +2,4 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#include "../gc/gc.h" +#include "../gc/gcinterface.h"
\ No newline at end of file diff --git a/src/vm/gcstress.h b/src/vm/gcstress.h index 609276e148..04487c611e 100644 --- a/src/vm/gcstress.h +++ b/src/vm/gcstress.h @@ -280,17 +280,17 @@ namespace _GCStress // GC Trigger policy classes define how a garbage collection is triggered // This is the default GC Trigger policy that simply calls - // GCHeap::StressHeap + // IGCHeap::StressHeap class StressGcTriggerPolicy { public: FORCEINLINE static void Trigger() - { GCHeap::GetGCHeap()->StressHeap(); } + { GCHeapUtilities::GetGCHeap()->StressHeap(); } FORCEINLINE - static void Trigger(::alloc_context* acontext) - { GCHeap::GetGCHeap()->StressHeap(acontext); } + static void Trigger(::gc_alloc_context* acontext) + { GCHeapUtilities::GetGCHeap()->StressHeap(acontext); } }; // This is an overriding GC Trigger policy that triggers a GC by calling @@ -403,7 +403,7 @@ namespace _GCStress // Additionally it switches the GC mode as specified by GcModePolicy, and it // uses GcTriggerPolicy::Trigger(alloc_context*) to actually trigger the GC FORCEINLINE - static void MaybeTrigger(::alloc_context* acontext, DWORD minFastGc = 0) + static void MaybeTrigger(::gc_alloc_context* acontext, DWORD minFastGc = 0) { if (IsEnabled(minFastGc) && GCStressPolicy::IsEnabled()) { @@ -455,7 +455,7 @@ namespace _GCStress public: FORCEINLINE - static void MaybeTrigger(::alloc_context* acontext) + static void MaybeTrigger(::gc_alloc_context* acontext) { GcStressBase::MaybeTrigger(acontext); diff --git a/src/vm/hash.cpp b/src/vm/hash.cpp index 205f736b0d..6b6b21391f 100644 --- a/src/vm/hash.cpp +++ b/src/vm/hash.cpp @@ -547,8 +547,8 @@ UPTR HashMap::LookupValue(UPTR key, UPTR value) // BROKEN: This is called for the RCWCache on the GC thread // Also called by AppDomain::FindCachedAssembly to resolve AssemblyRef -- this is used by stack walking on the GC thread. - // See comments in GCHeap::RestartEE (above the call to SyncClean::CleanUp) for reason to enter COOP mode. - // However, if the current thread is the GC thread, we know we're not going to call GCHeap::RestartEE + // See comments in GCHeapUtilities::RestartEE (above the call to SyncClean::CleanUp) for reason to enter COOP mode. + // However, if the current thread is the GC thread, we know we're not going to call GCHeapUtilities::RestartEE // while accessing the HashMap, so it's safe to proceed. // (m_fAsyncMode && !IsGCThread() is the condition for entering COOP mode. I.e., enable COOP GC only if // the HashMap is in async mode and this is not a GC thread.) diff --git a/src/vm/i386/excepx86.cpp b/src/vm/i386/excepx86.cpp index 27c923b749..fb68963ae6 100644 --- a/src/vm/i386/excepx86.cpp +++ b/src/vm/i386/excepx86.cpp @@ -19,7 +19,7 @@ #include "comutilnative.h" #include "sigformat.h" #include "siginfo.hpp" -#include "gc.h" +#include "gcheaputilities.h" #include "eedbginterfaceimpl.h" //so we can clearexception in COMPlusThrow #include "perfcounters.h" #include "eventtrace.h" diff --git a/src/vm/i386/jitinterfacex86.cpp b/src/vm/i386/jitinterfacex86.cpp index 949b115ce2..f6d77668b7 100644 --- a/src/vm/i386/jitinterfacex86.cpp +++ b/src/vm/i386/jitinterfacex86.cpp @@ -57,10 +57,10 @@ extern "C" void STDCALL WriteBarrierAssert(BYTE* ptr, Object* obj) if (fVerifyHeap) { obj->Validate(FALSE); - if(GCHeap::GetGCHeap()->IsHeapPointer(ptr)) + if(GCHeapUtilities::GetGCHeap()->IsHeapPointer(ptr)) { Object* pObj = *(Object**)ptr; - _ASSERTE (pObj == NULL || GCHeap::GetGCHeap()->IsHeapPointer(pObj)); + _ASSERTE (pObj == NULL || GCHeapUtilities::GetGCHeap()->IsHeapPointer(pObj)); } } else @@ -610,7 +610,7 @@ void JIT_TrialAlloc::EmitCore(CPUSTUBLINKER *psl, CodeLabel *noLock, CodeLabel * if (flags & (ALIGN8 | SIZE_IN_EAX | ALIGN8OBJ)) { // MOV EBX, [edx]Thread.m_alloc_context.alloc_ptr - psl->X86EmitOffsetModRM(0x8B, kEBX, kEDX, offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_ptr)); + psl->X86EmitOffsetModRM(0x8B, kEBX, kEDX, offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr)); // add EAX, EBX psl->Emit16(0xC303); if (flags & ALIGN8) @@ -619,11 +619,11 @@ void JIT_TrialAlloc::EmitCore(CPUSTUBLINKER *psl, CodeLabel *noLock, CodeLabel * else { // add eax, [edx]Thread.m_alloc_context.alloc_ptr - psl->X86EmitOffsetModRM(0x03, kEAX, kEDX, offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_ptr)); + psl->X86EmitOffsetModRM(0x03, kEAX, kEDX, offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr)); } // cmp eax, [edx]Thread.m_alloc_context.alloc_limit - psl->X86EmitOffsetModRM(0x3b, kEAX, kEDX, offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_limit)); + psl->X86EmitOffsetModRM(0x3b, kEAX, kEDX, offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_limit)); // ja noAlloc psl->X86EmitCondJump(noAlloc, X86CondCode::kJA); @@ -631,7 +631,7 @@ void JIT_TrialAlloc::EmitCore(CPUSTUBLINKER *psl, CodeLabel *noLock, CodeLabel * // Fill in the allocation and get out. // mov [edx]Thread.m_alloc_context.alloc_ptr, eax - psl->X86EmitIndexRegStore(kEDX, offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_ptr), kEAX); + psl->X86EmitIndexRegStore(kEDX, offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr), kEAX); if (flags & (ALIGN8 | SIZE_IN_EAX | ALIGN8OBJ)) { @@ -1502,7 +1502,7 @@ void InitJITHelpers1() _ASSERTE(g_SystemInfo.dwNumberOfProcessors != 0); - JIT_TrialAlloc::Flags flags = GCHeap::UseAllocationContexts() ? + JIT_TrialAlloc::Flags flags = GCHeapUtilities::UseAllocationContexts() ? JIT_TrialAlloc::MP_ALLOCATOR : JIT_TrialAlloc::NORMAL; // Get CPU features and check for SSE2 support. diff --git a/src/vm/i386/virtualcallstubcpu.hpp b/src/vm/i386/virtualcallstubcpu.hpp index 33ce8199b9..8c16854d22 100644 --- a/src/vm/i386/virtualcallstubcpu.hpp +++ b/src/vm/i386/virtualcallstubcpu.hpp @@ -695,7 +695,7 @@ BOOL isDelegateCall(BYTE *interiorPtr) { LIMITED_METHOD_CONTRACT; - if (GCHeap::GetGCHeap()->IsHeapPointer((void*)interiorPtr)) + if (GCHeapUtilities::GetGCHeap()->IsHeapPointer((void*)interiorPtr)) { Object *delegate = (Object*)(interiorPtr - DelegateObject::GetOffsetOfMethodPtrAux()); VALIDATEOBJECTREF(ObjectToOBJECTREF(delegate)); diff --git a/src/vm/interoputil.cpp b/src/vm/interoputil.cpp index 33f04b9ab8..6a0fbded12 100644 --- a/src/vm/interoputil.cpp +++ b/src/vm/interoputil.cpp @@ -2130,7 +2130,7 @@ void MinorCleanupSyncBlockComData(InteropSyncBlockInfo* pInteropInfo) NOTHROW; GC_NOTRIGGER; MODE_ANY; - PRECONDITION( GCHeap::IsGCInProgress() || ( (g_fEEShutDown & ShutDown_SyncBlock) && g_fProcessDetach ) ); + PRECONDITION( GCHeapUtilities::IsGCInProgress() || ( (g_fEEShutDown & ShutDown_SyncBlock) && g_fProcessDetach ) ); } CONTRACTL_END; diff --git a/src/vm/interpreter.cpp b/src/vm/interpreter.cpp index a540cff0b0..ed289cb3cc 100644 --- a/src/vm/interpreter.cpp +++ b/src/vm/interpreter.cpp @@ -14,7 +14,7 @@ #include "openum.h" #include "fcall.h" #include "frames.h" -#include "gc.h" +#include "gcheaputilities.h" #include <float.h> #include "jitinterface.h" #include "safemath.h" diff --git a/src/vm/jithelpers.cpp b/src/vm/jithelpers.cpp index 276c2d6c58..dac9f59246 100644 --- a/src/vm/jithelpers.cpp +++ b/src/vm/jithelpers.cpp @@ -23,7 +23,7 @@ #include "security.h" #include "securitymeta.h" #include "dllimport.h" -#include "gc.h" +#include "gcheaputilities.h" #include "comdelegate.h" #include "jitperf.h" // to track jit perf #include "corprof.h" @@ -2858,7 +2858,7 @@ HCIMPL1(Object*, JIT_NewS_MP_FastPortable, CORINFO_CLASS_HANDLE typeHnd_) do { - _ASSERTE(GCHeap::UseAllocationContexts()); + _ASSERTE(GCHeapUtilities::UseAllocationContexts()); // This is typically the only call in the fast path. Making the call early seems to be better, as it allows the compiler // to use volatile registers for intermediate values. This reduces the number of push/pop instructions and eliminates @@ -2872,7 +2872,7 @@ HCIMPL1(Object*, JIT_NewS_MP_FastPortable, CORINFO_CLASS_HANDLE typeHnd_) SIZE_T size = methodTable->GetBaseSize(); _ASSERTE(size % DATA_ALIGNMENT == 0); - alloc_context *allocContext = thread->GetAllocContext(); + gc_alloc_context *allocContext = thread->GetAllocContext(); BYTE *allocPtr = allocContext->alloc_ptr; _ASSERTE(allocPtr <= allocContext->alloc_limit); if (size > static_cast<SIZE_T>(allocContext->alloc_limit - allocPtr)) @@ -2997,7 +2997,7 @@ HCIMPL1(StringObject*, AllocateString_MP_FastPortable, DWORD stringLength) do { - _ASSERTE(GCHeap::UseAllocationContexts()); + _ASSERTE(GCHeapUtilities::UseAllocationContexts()); // Instead of doing elaborate overflow checks, we just limit the number of elements. This will avoid all overflow // problems, as well as making sure big string objects are correctly allocated in the big object heap. @@ -3021,7 +3021,7 @@ HCIMPL1(StringObject*, AllocateString_MP_FastPortable, DWORD stringLength) _ASSERTE(alignedTotalSize >= totalSize); totalSize = alignedTotalSize; - alloc_context *allocContext = thread->GetAllocContext(); + gc_alloc_context *allocContext = thread->GetAllocContext(); BYTE *allocPtr = allocContext->alloc_ptr; _ASSERTE(allocPtr <= allocContext->alloc_limit); if (totalSize > static_cast<SIZE_T>(allocContext->alloc_limit - allocPtr)) @@ -3161,7 +3161,7 @@ HCIMPL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeHn do { - _ASSERTE(GCHeap::UseAllocationContexts()); + _ASSERTE(GCHeapUtilities::UseAllocationContexts()); // Do a conservative check here. This is to avoid overflow while doing the calculations. We don't // have to worry about "large" objects, since the allocation quantum is never big enough for @@ -3198,7 +3198,7 @@ HCIMPL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeHn _ASSERTE(alignedTotalSize >= totalSize); totalSize = alignedTotalSize; - alloc_context *allocContext = thread->GetAllocContext(); + gc_alloc_context *allocContext = thread->GetAllocContext(); BYTE *allocPtr = allocContext->alloc_ptr; _ASSERTE(allocPtr <= allocContext->alloc_limit); if (totalSize > static_cast<SIZE_T>(allocContext->alloc_limit - allocPtr)) @@ -3238,7 +3238,7 @@ HCIMPL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeH do { - _ASSERTE(GCHeap::UseAllocationContexts()); + _ASSERTE(GCHeapUtilities::UseAllocationContexts()); // Make sure that the total size cannot reach LARGE_OBJECT_SIZE, which also allows us to avoid overflow checks. The // "256" slack is to cover the array header size and round-up, using a constant value here out of laziness. @@ -3266,7 +3266,7 @@ HCIMPL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeH _ASSERTE(ALIGN_UP(totalSize, DATA_ALIGNMENT) == totalSize); - alloc_context *allocContext = thread->GetAllocContext(); + gc_alloc_context *allocContext = thread->GetAllocContext(); BYTE *allocPtr = allocContext->alloc_ptr; _ASSERTE(allocPtr <= allocContext->alloc_limit); if (totalSize > static_cast<SIZE_T>(allocContext->alloc_limit - allocPtr)) @@ -6431,7 +6431,7 @@ HCIMPL0(VOID, JIT_StressGC) bool fSkipGC = false; if (!fSkipGC) - GCHeap::GetGCHeap()->GarbageCollect(); + GCHeapUtilities::GetGCHeap()->GarbageCollect(); // <TODO>@TODO: the following ifdef is in error, but if corrected the // compiler complains about the *__ms->pRetAddr() saying machine state diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index 76d4568adb..65a804e320 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -27,7 +27,7 @@ #include "security.h" #include "securitymeta.h" #include "dllimport.h" -#include "gc.h" +#include "gcheaputilities.h" #include "comdelegate.h" #include "jitperf.h" // to track jit perf #include "corprof.h" diff --git a/src/vm/jitinterfacegen.cpp b/src/vm/jitinterfacegen.cpp index 0a90dc347d..f8a95bb759 100644 --- a/src/vm/jitinterfacegen.cpp +++ b/src/vm/jitinterfacegen.cpp @@ -221,7 +221,7 @@ void InitJITHelpers1() )) { // if (multi-proc || server GC) - if (GCHeap::UseAllocationContexts()) + if (GCHeapUtilities::UseAllocationContexts()) { #ifdef FEATURE_IMPLICIT_TLS SetJitHelperFunction(CORINFO_HELP_NEWSFAST, JIT_NewS_MP_FastPortable); diff --git a/src/vm/marshalnative.cpp b/src/vm/marshalnative.cpp index 48911b7190..5f05fa2daf 100644 --- a/src/vm/marshalnative.cpp +++ b/src/vm/marshalnative.cpp @@ -27,7 +27,7 @@ #include "log.h" #include "fieldmarshaler.h" #include "cgensys.h" -#include "gc.h" +#include "gcheaputilities.h" #include "security.h" #include "dbginterface.h" #include "objecthandle.h" diff --git a/src/vm/mdaassistants.cpp b/src/vm/mdaassistants.cpp index cc598c0a6c..e0e747bbaf 100644 --- a/src/vm/mdaassistants.cpp +++ b/src/vm/mdaassistants.cpp @@ -137,7 +137,7 @@ void TriggerGCForMDAInternal() EX_TRY { - GCHeap::GetGCHeap()->GarbageCollect(); + GCHeapUtilities::GetGCHeap()->GarbageCollect(); #ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT // @@ -868,7 +868,7 @@ LPVOID MdaInvalidOverlappedToPinvoke::CheckOverlappedPointer(UINT index, LPVOID { GCX_COOP(); - GCHeap *pHeap = GCHeap::GetGCHeap(); + GCHeap *pHeap = GCHeapUtilities::GetGCHeap(); fHeapPointer = pHeap->IsHeapPointer(pOverlapped); } diff --git a/src/vm/memberload.cpp b/src/vm/memberload.cpp index 8b7b2ce69c..1b24300a68 100644 --- a/src/vm/memberload.cpp +++ b/src/vm/memberload.cpp @@ -30,7 +30,7 @@ #include "log.h" #include "fieldmarshaler.h" #include "cgensys.h" -#include "gc.h" +#include "gcheaputilities.h" #include "security.h" #include "dbginterface.h" #include "comdelegate.h" diff --git a/src/vm/message.cpp b/src/vm/message.cpp index fa0370dd33..093f9a2629 100644 --- a/src/vm/message.cpp +++ b/src/vm/message.cpp @@ -249,7 +249,7 @@ void CMessage::GetObjectFromStack(OBJECTREF* ppDest, PVOID val, const CorElement _ASSERTE(ty.GetMethodTable()->IsValueType() || ty.GetMethodTable()->IsEnum()); - _ASSERTE(!GCHeap::GetGCHeap()->IsHeapPointer((BYTE *) ppDest) || + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE *) ppDest) || !"(pDest) can not point to GC Heap"); MethodTable* pMT = ty.GetMethodTable(); diff --git a/src/vm/methodtable.cpp b/src/vm/methodtable.cpp index bf863826d4..52a2ce4d98 100644 --- a/src/vm/methodtable.cpp +++ b/src/vm/methodtable.cpp @@ -33,7 +33,7 @@ #include "log.h" #include "fieldmarshaler.h" #include "cgensys.h" -#include "gc.h" +#include "gcheaputilities.h" #include "security.h" #include "dbginterface.h" #include "comdelegate.h" @@ -9804,11 +9804,11 @@ BOOL MethodTable::Validate() } DWORD dwLastVerifiedGCCnt = m_pWriteableData->m_dwLastVerifedGCCnt; - // Here we used to assert that (dwLastVerifiedGCCnt <= GCHeap::GetGCHeap()->GetGcCount()) but + // Here we used to assert that (dwLastVerifiedGCCnt <= GCHeapUtilities::GetGCHeap()->GetGcCount()) but // this is no longer true because with background gc. Since the purpose of having // m_dwLastVerifedGCCnt is just to only verify the same method table once for each GC // I am getting rid of the assert. - if (g_pConfig->FastGCStressLevel () > 1 && dwLastVerifiedGCCnt == GCHeap::GetGCHeap()->GetGcCount()) + if (g_pConfig->FastGCStressLevel () > 1 && dwLastVerifiedGCCnt == GCHeapUtilities::GetGCHeap()->GetGcCount()) return TRUE; #endif //_DEBUG @@ -9835,7 +9835,7 @@ BOOL MethodTable::Validate() // It is not a fatal error to fail the update the counter. We will run slower and retry next time, // but the system will function properly. if (EnsureWritablePagesNoThrow(m_pWriteableData, sizeof(MethodTableWriteableData))) - m_pWriteableData->m_dwLastVerifedGCCnt = GCHeap::GetGCHeap()->GetGcCount(); + m_pWriteableData->m_dwLastVerifedGCCnt = GCHeapUtilities::GetGCHeap()->GetGcCount(); #endif //_DEBUG return TRUE; diff --git a/src/vm/nativeoverlapped.h b/src/vm/nativeoverlapped.h index 854090c35f..9e4e861790 100644 --- a/src/vm/nativeoverlapped.h +++ b/src/vm/nativeoverlapped.h @@ -62,7 +62,7 @@ public: STATIC_CONTRACT_SO_TOLERANT; _ASSERTE (nativeOverlapped != NULL); - _ASSERTE (GCHeap::GetGCHeap()->IsHeapPointer((BYTE *) nativeOverlapped)); + _ASSERTE (GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE *) nativeOverlapped)); return (OverlappedDataObject*)((BYTE*)nativeOverlapped - offsetof(OverlappedDataObject, Internal)); } diff --git a/src/vm/object.cpp b/src/vm/object.cpp index 7c47e26627..c4fbc40c33 100644 --- a/src/vm/object.cpp +++ b/src/vm/object.cpp @@ -17,7 +17,7 @@ #include "threads.h" #include "excep.h" #include "eeconfig.h" -#include "gc.h" +#include "gcheaputilities.h" #ifdef FEATURE_REMOTING #include "remoting.h" #endif @@ -243,7 +243,7 @@ TypeHandle Object::GetGCSafeTypeHandleIfPossible() const // // where MyRefType2's module was unloaded by the time the GC occurred. In at least // one case, the GC was caused by the AD unload itself (AppDomain::Unload -> - // AppDomain::Exit -> GCInterface::AddMemoryPressure -> WKS::GCHeap::GarbageCollect). + // AppDomain::Exit -> GCInterface::AddMemoryPressure -> WKS::GCHeapUtilities::GarbageCollect). // // To protect against all scenarios, verify that // @@ -1764,9 +1764,9 @@ VOID Object::ValidateInner(BOOL bDeep, BOOL bVerifyNextHeader, BOOL bVerifySyncB BOOL bSmallObjectHeapPtr = FALSE, bLargeObjectHeapPtr = FALSE; if (!noRangeChecks) { - bSmallObjectHeapPtr = GCHeap::GetGCHeap()->IsHeapPointer(this, TRUE); + bSmallObjectHeapPtr = GCHeapUtilities::GetGCHeap()->IsHeapPointer(this, TRUE); if (!bSmallObjectHeapPtr) - bLargeObjectHeapPtr = GCHeap::GetGCHeap()->IsHeapPointer(this); + bLargeObjectHeapPtr = GCHeapUtilities::GetGCHeap()->IsHeapPointer(this); CHECK_AND_TEAR_DOWN(bSmallObjectHeapPtr || bLargeObjectHeapPtr); } @@ -1781,7 +1781,7 @@ VOID Object::ValidateInner(BOOL bDeep, BOOL bVerifyNextHeader, BOOL bVerifySyncB lastTest = 4; if (bDeep && (g_pConfig->GetHeapVerifyLevel() & EEConfig::HEAPVERIFY_GC)) { - GCHeap::GetGCHeap()->ValidateObjectMember(this); + GCHeapUtilities::GetGCHeap()->ValidateObjectMember(this); } lastTest = 5; @@ -1790,7 +1790,7 @@ VOID Object::ValidateInner(BOOL bDeep, BOOL bVerifyNextHeader, BOOL bVerifySyncB // we skip checking noRangeChecks since if skipping // is enabled bSmallObjectHeapPtr will always be false. if (bSmallObjectHeapPtr) { - CHECK_AND_TEAR_DOWN(!GCHeap::GetGCHeap()->IsObjectInFixedHeap(this)); + CHECK_AND_TEAR_DOWN(!GCHeapUtilities::GetGCHeap()->IsObjectInFixedHeap(this)); } lastTest = 6; @@ -1815,9 +1815,9 @@ VOID Object::ValidateInner(BOOL bDeep, BOOL bVerifyNextHeader, BOOL bVerifySyncB && bVerifyNextHeader && GCScan::GetGcRuntimeStructuresValid () //NextObj could be very slow if concurrent GC is going on - && !(GCHeap::IsGCHeapInitialized() && GCHeap::GetGCHeap ()->IsConcurrentGCInProgress ())) + && !(GCHeapUtilities::IsGCHeapInitialized() && GCHeapUtilities::GetGCHeap ()->IsConcurrentGCInProgress ())) { - Object * nextObj = GCHeap::GetGCHeap ()->NextObj (this); + Object * nextObj = GCHeapUtilities::GetGCHeap ()->NextObj (this); if ((nextObj != NULL) && (nextObj->GetGCSafeMethodTable() != g_pFreeObjectMethodTable)) { @@ -1949,7 +1949,7 @@ STRINGREF StringObject::NewString(const WCHAR *pwsz) // pinning and then later put into a struct and that struct is // then marshalled to managed. // - _ASSERTE(!GCHeap::GetGCHeap()->IsHeapPointer((BYTE *) pwsz) || + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE *) pwsz) || !"pwsz can not point to GC Heap"); #endif // 0 @@ -1988,7 +1988,7 @@ STRINGREF StringObject::NewString(const WCHAR *pwsz, int length) { // pinning and then later put into a struct and that struct is // then marshalled to managed. // - _ASSERTE(!GCHeap::GetGCHeap()->IsHeapPointer((BYTE *) pwsz) || + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE *) pwsz) || !"pwsz can not point to GC Heap"); #endif // 0 STRINGREF pString = AllocateString(length); @@ -2664,7 +2664,7 @@ OBJECTREF::OBJECTREF(const OBJECTREF & objref) // !!! Either way you need to fix the code. _ASSERTE(Thread::IsObjRefValid(&objref)); if ((objref.m_asObj != 0) && - ((GCHeap*)GCHeap::GetGCHeap())->IsHeapPointer( (BYTE*)this )) + ((IGCHeap*)GCHeapUtilities::GetGCHeap())->IsHeapPointer( (BYTE*)this )) { _ASSERTE(!"Write Barrier violation. Must use SetObjectReference() to assign OBJECTREF's into the GC heap!"); } @@ -2718,7 +2718,7 @@ OBJECTREF::OBJECTREF(Object *pObject) DEBUG_ONLY_FUNCTION; if ((pObject != 0) && - ((GCHeap*)GCHeap::GetGCHeap())->IsHeapPointer( (BYTE*)this )) + ((IGCHeap*)GCHeapUtilities::GetGCHeap())->IsHeapPointer( (BYTE*)this )) { _ASSERTE(!"Write Barrier violation. Must use SetObjectReference() to assign OBJECTREF's into the GC heap!"); } @@ -2901,7 +2901,7 @@ OBJECTREF& OBJECTREF::operator=(const OBJECTREF &objref) _ASSERTE(Thread::IsObjRefValid(&objref)); if ((objref.m_asObj != 0) && - ((GCHeap*)GCHeap::GetGCHeap())->IsHeapPointer( (BYTE*)this )) + ((IGCHeap*)GCHeapUtilities::GetGCHeap())->IsHeapPointer( (BYTE*)this )) { _ASSERTE(!"Write Barrier violation. Must use SetObjectReference() to assign OBJECTREF's into the GC heap!"); } @@ -2948,14 +2948,14 @@ void* __cdecl GCSafeMemCpy(void * dest, const void * src, size_t len) { Thread* pThread = GetThread(); - // GCHeap::IsHeapPointer has race when called in preemptive mode. It walks the list of segments + // GCHeapUtilities::IsHeapPointer has race when called in preemptive mode. It walks the list of segments // that can be modified by GC. Do the check below only if it is safe to do so. if (pThread != NULL && pThread->PreemptiveGCDisabled()) { // Note there is memcpyNoGCRefs which will allow you to do a memcpy into the GC // heap if you really know you don't need to call the write barrier - _ASSERTE(!GCHeap::GetGCHeap()->IsHeapPointer((BYTE *) dest) || + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE *) dest) || !"using memcpy to copy into the GC heap, use CopyValueClass"); } } diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp index 1f2e8c748c..b34b878a83 100644 --- a/src/vm/prestub.cpp +++ b/src/vm/prestub.cpp @@ -1179,7 +1179,7 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT) if (g_pConfig->ShouldPrestubGC(this)) { GCX_COOP(); - GCHeap::GetGCHeap()->GarbageCollect(-1); + GCHeapUtilities::GetGCHeap()->GarbageCollect(-1); } #endif // _DEBUG diff --git a/src/vm/profattach.cpp b/src/vm/profattach.cpp index f03db361f0..5b10e8f10e 100644 --- a/src/vm/profattach.cpp +++ b/src/vm/profattach.cpp @@ -806,7 +806,7 @@ void ProfilingAPIAttachDetach::InitializeAttachThreadingMode() // Environment variable trumps all, so check it first DWORD dwAlwaysOn = g_pConfig->GetConfigDWORD_DontUse_( CLRConfig::EXTERNAL_AttachThreadAlwaysOn, - GCHeap::IsServerHeap() ? 1 : 0); // Default depends on GC server mode + GCHeapUtilities::IsServerHeap() ? 1 : 0); // Default depends on GC server mode if (dwAlwaysOn == 0) { diff --git a/src/vm/profilinghelper.cpp b/src/vm/profilinghelper.cpp index 139ba89ec0..1dd60b47e1 100644 --- a/src/vm/profilinghelper.cpp +++ b/src/vm/profilinghelper.cpp @@ -1413,7 +1413,7 @@ void ProfilingAPIUtility::TerminateProfiling() { // We know for sure GC has been fully initialized as we've turned off concurrent GC before _ASSERTE(IsGarbageCollectorFullyInitialized()); - GCHeap::GetGCHeap()->TemporaryEnableConcurrentGC(); + GCHeapUtilities::GetGCHeap()->TemporaryEnableConcurrentGC(); g_profControlBlock.fConcurrentGCDisabledForAttach = FALSE; } diff --git a/src/vm/proftoeeinterfaceimpl.cpp b/src/vm/proftoeeinterfaceimpl.cpp index 551b38631a..fee883f0ef 100644 --- a/src/vm/proftoeeinterfaceimpl.cpp +++ b/src/vm/proftoeeinterfaceimpl.cpp @@ -754,7 +754,7 @@ struct GenerationTable //--------------------------------------------------------------------------------------- // -// This is a callback used by the GC when we call GCHeap::DescrGenerationsToProfiler +// This is a callback used by the GC when we call GCHeapUtilities::DescrGenerationsToProfiler // (from UpdateGenerationBounds() below). The GC gives us generation information through // this callback, which we use to update the GenerationDesc in the corresponding // GenerationTable @@ -874,7 +874,7 @@ void __stdcall UpdateGenerationBounds() #endif // fill in the values by calling back into the gc, which will report // the ranges by calling GenWalkFunc for each one - GCHeap *hp = GCHeap::GetGCHeap(); + IGCHeap *hp = GCHeapUtilities::GetGCHeap(); hp->DescrGenerationsToProfiler(GenWalkFunc, newGenerationTable); // remember the old table and plug in the new one @@ -1018,7 +1018,7 @@ ClassID SafeGetClassIDFromObject(Object * pObj) //--------------------------------------------------------------------------------------- // -// Callback of type walk_fn used by GCHeap::WalkObject. Keeps a count of each +// Callback of type walk_fn used by GCHeapUtilities::WalkObject. Keeps a count of each // object reference found. // // Arguments: @@ -1040,7 +1040,7 @@ BOOL CountContainedObjectRef(Object * pBO, void * context) //--------------------------------------------------------------------------------------- // -// Callback of type walk_fn used by GCHeap::WalkObject. Stores each object reference +// Callback of type walk_fn used by GCHeapUtilities::WalkObject. Stores each object reference // encountered into an array. // // Arguments: @@ -1113,7 +1113,7 @@ BOOL HeapWalkHelper(Object * pBO, void * pvContext) if (pMT->ContainsPointersOrCollectible()) { // First round through calculates the number of object refs for this class - GCHeap::GetGCHeap()->WalkObject(pBO, &CountContainedObjectRef, (void *)&cNumRefs); + GCHeapUtilities::GetGCHeap()->WalkObject(pBO, &CountContainedObjectRef, (void *)&cNumRefs); if (cNumRefs > 0) { @@ -1138,7 +1138,7 @@ BOOL HeapWalkHelper(Object * pBO, void * pvContext) // Second round saves off all of the ref values OBJECTREF * pCurObjRef = arrObjRef; - GCHeap::GetGCHeap()->WalkObject(pBO, &SaveContainedObjectRef, (void *)&pCurObjRef); + GCHeapUtilities::GetGCHeap()->WalkObject(pBO, &SaveContainedObjectRef, (void *)&pCurObjRef); } } @@ -9461,7 +9461,7 @@ FCIMPL2(void, ProfilingFCallHelper::FC_RemotingClientSendingMessage, GUID *pId, // it is a value class declared on the stack and so GC doesn't // know about it. - _ASSERTE (!GCHeap::GetGCHeap()->IsHeapPointer(pId)); // should be on the stack, not in the heap + _ASSERTE (!GCHeapUtilities::GetGCHeap()->IsHeapPointer(pId)); // should be on the stack, not in the heap HELPER_METHOD_FRAME_BEGIN_NOPOLL(); { diff --git a/src/vm/rcwwalker.cpp b/src/vm/rcwwalker.cpp index ad718126c1..0b875360fd 100644 --- a/src/vm/rcwwalker.cpp +++ b/src/vm/rcwwalker.cpp @@ -129,10 +129,10 @@ STDMETHODIMP CLRServicesImpl::GarbageCollect(DWORD dwFlags) { GCX_COOP_THREAD_EXISTS(GET_THREAD()); if (dwFlags & GC_FOR_APPX_SUSPEND) { - GCHeap::GetGCHeap()->GarbageCollect(2, TRUE, collection_blocking | collection_optimized); + GCHeapUtilities::GetGCHeap()->GarbageCollect(2, TRUE, collection_blocking | collection_optimized); } else - GCHeap::GetGCHeap()->GarbageCollect(); + GCHeapUtilities::GetGCHeap()->GarbageCollect(); } END_EXTERNAL_ENTRYPOINT; return hr; diff --git a/src/vm/runtimecallablewrapper.cpp b/src/vm/runtimecallablewrapper.cpp index d12d5568f6..8aeaec606a 100644 --- a/src/vm/runtimecallablewrapper.cpp +++ b/src/vm/runtimecallablewrapper.cpp @@ -1591,7 +1591,7 @@ public: if (pRCW->IsValid()) { - if (!GCHeap::GetGCHeap()->IsPromoted(OBJECTREFToObject(pRCW->GetExposedObject())) && + if (!GCHeapUtilities::GetGCHeap()->IsPromoted(OBJECTREFToObject(pRCW->GetExposedObject())) && !pRCW->IsDetached()) { // No need to use InterlockedOr here since every other place that modifies the flags @@ -1612,7 +1612,7 @@ void RCWCache::DetachWrappersWorker() NOTHROW; GC_NOTRIGGER; MODE_ANY; - PRECONDITION(GCHeap::IsGCInProgress()); // GC is in progress and the runtime is suspended + PRECONDITION(GCHeapUtilities::IsGCInProgress()); // GC is in progress and the runtime is suspended } CONTRACTL_END; @@ -2808,7 +2808,7 @@ void RCW::MinorCleanup() NOTHROW; GC_NOTRIGGER; MODE_ANY; - PRECONDITION(GCHeap::IsGCInProgress() || ( (g_fEEShutDown & ShutDown_SyncBlock) && g_fProcessDetach )); + PRECONDITION(GCHeapUtilities::IsGCInProgress() || ( (g_fEEShutDown & ShutDown_SyncBlock) && g_fProcessDetach )); } CONTRACTL_END; diff --git a/src/vm/safehandle.cpp b/src/vm/safehandle.cpp index 3336e693b5..828b221025 100644 --- a/src/vm/safehandle.cpp +++ b/src/vm/safehandle.cpp @@ -246,7 +246,7 @@ void SafeHandle::Dispose() // Suppress finalization on this object (we may be racing here but the // operation below is idempotent and a dispose should never race a // finalization). - GCHeap::GetGCHeap()->SetFinalizationRun(OBJECTREFToObject(sh)); + GCHeapUtilities::GetGCHeap()->SetFinalizationRun(OBJECTREFToObject(sh)); GCPROTECT_END(); } @@ -394,7 +394,7 @@ FCIMPL1(void, SafeHandle::SetHandleAsInvalid, SafeHandle* refThisUNSAFE) } while (InterlockedCompareExchange((LONG*)&sh->m_state, newState, oldState) != oldState); - GCHeap::GetGCHeap()->SetFinalizationRun(OBJECTREFToObject(sh)); + GCHeapUtilities::GetGCHeap()->SetFinalizationRun(OBJECTREFToObject(sh)); } FCIMPLEND diff --git a/src/vm/siginfo.cpp b/src/vm/siginfo.cpp index decd3c0aab..9adfb4998c 100644 --- a/src/vm/siginfo.cpp +++ b/src/vm/siginfo.cpp @@ -14,7 +14,7 @@ #include "clsload.hpp" #include "vars.hpp" #include "excep.h" -#include "gc.h" +#include "gcheaputilities.h" #include "field.h" #include "eeconfig.h" #include "runtimehandles.h" // for SignatureNative diff --git a/src/vm/stubhelpers.cpp b/src/vm/stubhelpers.cpp index 6e7fb49b96..cbe1d37c94 100644 --- a/src/vm/stubhelpers.cpp +++ b/src/vm/stubhelpers.cpp @@ -19,7 +19,7 @@ #include "security.h" #include "eventtrace.h" #include "comdatetime.h" -#include "gc.h" +#include "gcheaputilities.h" #include "interoputil.h" #include "gcscan.h" #ifdef FEATURE_REMOTING @@ -70,7 +70,7 @@ void StubHelpers::ValidateObjectInternal(Object *pObjUNSAFE, BOOL fValidateNextO // and the next object as required if (fValidateNextObj) { - Object *nextObj = GCHeap::GetGCHeap()->NextObj(pObjUNSAFE); + Object *nextObj = GCHeapUtilities::GetGCHeap()->NextObj(pObjUNSAFE); if (nextObj != NULL) { // Note that the MethodTable of the object (i.e. the pointer at offset 0) can change from @@ -162,7 +162,7 @@ void StubHelpers::ProcessByrefValidationList() { entry = s_ByrefValidationEntries[i]; - Object *pObjUNSAFE = GCHeap::GetGCHeap()->GetGCHeap()->GetContainingObject(entry.pByref); + Object *pObjUNSAFE = GCHeapUtilities::GetGCHeap()->GetContainingObject(entry.pByref); ValidateObjectInternal(pObjUNSAFE, TRUE); } } @@ -2004,7 +2004,7 @@ FCIMPL3(void, StubHelpers::ValidateObject, Object *pObjUNSAFE, MethodDesc *pMD, AVInRuntimeImplOkayHolder AVOkay; // don't validate the next object if a BGC is in progress. we can race with background // sweep which could make the next object a Free object underneath us if it's dead. - ValidateObjectInternal(pObjUNSAFE, !(GCHeap::GetGCHeap()->IsConcurrentGCInProgress())); + ValidateObjectInternal(pObjUNSAFE, !(GCHeapUtilities::GetGCHeap()->IsConcurrentGCInProgress())); } EX_CATCH { @@ -2031,7 +2031,7 @@ FCIMPL3(void, StubHelpers::ValidateByref, void *pByref, MethodDesc *pMD, Object // perform the validation on next GC (see code:StubHelpers.ProcessByrefValidationList). // Skip byref if is not pointing inside managed heap - if (!GCHeap::GetGCHeap()->IsHeapPointer(pByref)) + if (!GCHeapUtilities::GetGCHeap()->IsHeapPointer(pByref)) { return; } @@ -2066,7 +2066,7 @@ FCIMPL3(void, StubHelpers::ValidateByref, void *pByref, MethodDesc *pMD, Object if (NumOfEntries > BYREF_VALIDATION_LIST_MAX_SIZE) { // if the list is too big, trigger GC now - GCHeap::GetGCHeap()->GarbageCollect(0); + GCHeapUtilities::GetGCHeap()->GarbageCollect(0); } HELPER_METHOD_FRAME_END(); diff --git a/src/vm/syncblk.cpp b/src/vm/syncblk.cpp index 3975542d98..171a8d3bb7 100644 --- a/src/vm/syncblk.cpp +++ b/src/vm/syncblk.cpp @@ -1372,7 +1372,7 @@ void SyncBlockCache::GCWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintp STRESS_LOG0 (LF_GC | LF_SYNC, LL_INFO100, "GCWeakPtrScan starting\n"); #endif - if (GCHeap::GetGCHeap()->GetCondemnedGeneration() < GCHeap::GetGCHeap()->GetMaxGeneration()) + if (GCHeapUtilities::GetGCHeap()->GetCondemnedGeneration() < GCHeapUtilities::GetGCHeap()->GetMaxGeneration()) { #ifdef VERIFY_HEAP //for VSW 294550: we saw stale obeject reference in SyncBlkCache, so we want to make sure the card @@ -1416,7 +1416,7 @@ void SyncBlockCache::GCWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintp Object* o = SyncTableEntry::GetSyncTableEntry()[nb].m_Object; if (o && !((size_t)o & 1)) { - if (GCHeap::GetGCHeap()->IsEphemeral (o)) + if (GCHeapUtilities::GetGCHeap()->IsEphemeral (o)) { clear_card = FALSE; @@ -1615,8 +1615,8 @@ void SyncBlockCache::GCDone(BOOL demoting, int max_gen) CONTRACTL_END; if (demoting && - (GCHeap::GetGCHeap()->GetCondemnedGeneration() == - GCHeap::GetGCHeap()->GetMaxGeneration())) + (GCHeapUtilities::GetGCHeap()->GetCondemnedGeneration() == + GCHeapUtilities::GetGCHeap()->GetMaxGeneration())) { //scan the bitmap size_t dw = 0; @@ -1643,7 +1643,7 @@ void SyncBlockCache::GCDone(BOOL demoting, int max_gen) Object* o = SyncTableEntry::GetSyncTableEntry()[nb].m_Object; if (o && !((size_t)o & 1)) { - if (GCHeap::GetGCHeap()->WhichGeneration (o) < (unsigned int)max_gen) + if (GCHeapUtilities::GetGCHeap()->WhichGeneration (o) < (unsigned int)max_gen) { SetCard (card); break; @@ -1713,7 +1713,7 @@ void SyncBlockCache::VerifySyncTableEntry() DWORD idx = o->GetHeader()->GetHeaderSyncBlockIndex(); _ASSERTE(idx == nb || ((0 == idx) && (loop == max_iterations))); - _ASSERTE(!GCHeap::GetGCHeap()->IsEphemeral(o) || CardSetP(CardOf(nb))); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsEphemeral(o) || CardSetP(CardOf(nb))); } } } @@ -2498,10 +2498,10 @@ BOOL ObjHeader::Validate (BOOL bVerifySyncBlkIndex) //BIT_SBLK_GC_RESERVE (0x20000000) is only set during GC. But for frozen object, we don't clean the bit if (bits & BIT_SBLK_GC_RESERVE) { - if (!GCHeap::GetGCHeap()->IsGCInProgress () && !GCHeap::GetGCHeap()->IsConcurrentGCInProgress ()) + if (!GCHeapUtilities::IsGCInProgress () && !GCHeapUtilities::GetGCHeap()->IsConcurrentGCInProgress ()) { #ifdef FEATURE_BASICFREEZE - ASSERT_AND_CHECK (GCHeap::GetGCHeap()->IsInFrozenSegment(obj)); + ASSERT_AND_CHECK (GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)); #else //FEATURE_BASICFREEZE _ASSERTE(!"Reserve bit not cleared"); return FALSE; diff --git a/src/vm/syncclean.cpp b/src/vm/syncclean.cpp index e02c2f90c2..133f448e16 100644 --- a/src/vm/syncclean.cpp +++ b/src/vm/syncclean.cpp @@ -73,7 +73,7 @@ void SyncClean::CleanUp () // Only GC thread can call this. _ASSERTE (g_fProcessDetach || IsGCSpecialThread() || - (GCHeap::IsGCInProgress() && GetThread() == ThreadSuspend::GetSuspensionThread())); + (GCHeapUtilities::IsGCInProgress() && GetThread() == ThreadSuspend::GetSuspensionThread())); if (m_HashMap) { Bucket * pTempBucket = FastInterlockExchangePointer(m_HashMap.GetPointer(), NULL); diff --git a/src/vm/testhookmgr.cpp b/src/vm/testhookmgr.cpp index 9ec53f8e45..48370134d2 100644 --- a/src/vm/testhookmgr.cpp +++ b/src/vm/testhookmgr.cpp @@ -655,7 +655,7 @@ HRESULT CLRTestHookManager::GC(int generation) CONTRACTL_END; _ASSERTE(GetThread()==NULL || !GetThread()->PreemptiveGCDisabled()); - GCHeap::GetGCHeap()->GarbageCollect(generation); + GCHeapUtilities::GetGCHeap()->GarbageCollect(generation); FinalizerThread::FinalizerThreadWait(); return S_OK; } diff --git a/src/vm/threadpoolrequest.cpp b/src/vm/threadpoolrequest.cpp index 8d47e6b810..a5c1c4263d 100644 --- a/src/vm/threadpoolrequest.cpp +++ b/src/vm/threadpoolrequest.cpp @@ -517,11 +517,11 @@ void UnManagedPerAppDomainTPCount::DispatchWorkItem(bool* foundWork, bool* wasNo firstIteration = false; *foundWork = true; - if (GCHeap::IsGCInProgress(TRUE)) + if (GCHeapUtilities::IsGCInProgress(TRUE)) { // GC is imminent, so wait until GC is complete before executing next request. // this reduces in-flight objects allocated right before GC, easing the GC's work - GCHeap::WaitForGCCompletion(TRUE); + GCHeapUtilities::WaitForGCCompletion(TRUE); } PREFIX_ASSUME(pWorkRequest != NULL); diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp index cc2e4eb5e4..54cd03ed89 100644 --- a/src/vm/threads.cpp +++ b/src/vm/threads.cpp @@ -18,7 +18,7 @@ #include "excep.h" #include "comsynchronizable.h" #include "log.h" -#include "gc.h" +#include "gcheaputilities.h" #include "mscoree.h" #include "dbginterface.h" #include "corprof.h" // profiling @@ -3889,14 +3889,14 @@ void Thread::OnThreadTerminate(BOOL holdingLock) #endif } - if (GCHeap::IsGCHeapInitialized()) + if (GCHeapUtilities::IsGCHeapInitialized()) { // Guaranteed to NOT be a shutdown case, because we tear down the heap before // we tear down any threads during shutdown. if (ThisThreadID == CurrentThreadID) { GCX_COOP(); - GCHeap::GetGCHeap()->FixAllocContext(&m_alloc_context, FALSE, NULL, NULL); + GCHeapUtilities::GetGCHeap()->FixAllocContext(&m_alloc_context, FALSE, NULL, NULL); m_alloc_context.init(); } } @@ -3957,11 +3957,11 @@ void Thread::OnThreadTerminate(BOOL holdingLock) #endif } - if (GCHeap::IsGCHeapInitialized() && ThisThreadID != CurrentThreadID) + if (GCHeapUtilities::IsGCHeapInitialized() && ThisThreadID != CurrentThreadID) { // We must be holding the ThreadStore lock in order to clean up alloc context. // We should never call FixAllocContext during GC. - GCHeap::GetGCHeap()->FixAllocContext(&m_alloc_context, FALSE, NULL, NULL); + GCHeapUtilities::GetGCHeap()->FixAllocContext(&m_alloc_context, FALSE, NULL, NULL); m_alloc_context.init(); } @@ -9846,7 +9846,7 @@ void Thread::DoExtraWorkForFinalizer() Thread::CleanupDetachedThreads(); } - if(ExecutionManager::IsCacheCleanupRequired() && GCHeap::GetGCHeap()->GetCondemnedGeneration()>=1) + if(ExecutionManager::IsCacheCleanupRequired() && GCHeapUtilities::GetGCHeap()->GetCondemnedGeneration()>=1) { ExecutionManager::ClearCaches(); } @@ -11186,7 +11186,7 @@ void Thread::SetHasPromotedBytes () m_fPromoted = TRUE; - _ASSERTE(GCHeap::IsGCInProgress() && IsGCThread ()); + _ASSERTE(GCHeapUtilities::IsGCInProgress() && IsGCThread ()); if (!m_fPreemptiveGCDisabled) { diff --git a/src/vm/threads.h b/src/vm/threads.h index ec047f2ddd..bb54a85f45 100644 --- a/src/vm/threads.h +++ b/src/vm/threads.h @@ -142,7 +142,7 @@ #include "regdisp.h" #include "mscoree.h" #include "appdomainstack.h" -#include "gc.h" +#include "gcheaputilities.h" #include "gcinfotypes.h" #include <clrhost.h> @@ -1739,9 +1739,9 @@ public: // on MP systems, each thread has its own allocation chunk so we can avoid // lock prefixes and expensive MP cache snooping stuff - alloc_context m_alloc_context; + gc_alloc_context m_alloc_context; - inline alloc_context *GetAllocContext() { LIMITED_METHOD_CONTRACT; return &m_alloc_context; } + inline gc_alloc_context *GetAllocContext() { LIMITED_METHOD_CONTRACT; return &m_alloc_context; } // This is the type handle of the first object in the alloc context at the time // we fire the AllocationTick event. It's only for tooling purpose. @@ -4884,7 +4884,7 @@ private: private: // When we create an object, or create an OBJECTREF, or create an Interior Pointer, or enter EE from managed // code, we will set this flag. - // Inside GCHeap::StressHeap, we only do GC if this flag is TRUE. Then we reset it to zero. + // Inside GCHeapUtilities::StressHeap, we only do GC if this flag is TRUE. Then we reset it to zero. BOOL m_fStressHeapCount; public: void EnableStressHeap() diff --git a/src/vm/threadsuspend.cpp b/src/vm/threadsuspend.cpp index c71855f45f..0458b7dd57 100644 --- a/src/vm/threadsuspend.cpp +++ b/src/vm/threadsuspend.cpp @@ -3276,7 +3276,7 @@ void Thread::RareDisablePreemptiveGC() __SwitchToThread(0, CALLER_LIMITS_SPINNING); } - if (!GCHeap::IsGCHeapInitialized()) + if (!GCHeapUtilities::IsGCHeapInitialized()) { goto Exit; } @@ -3284,7 +3284,7 @@ void Thread::RareDisablePreemptiveGC() // Note IsGCInProgress is also true for say Pause (anywhere SuspendEE happens) and GCThread is the // thread that did the Pause. While in Pause if another thread attempts Rev/Pinvoke it should get inside the following and // block until resume - if (((GCHeap::IsGCInProgress() && (this != ThreadSuspend::GetSuspensionThread())) || + if (((GCHeapUtilities::IsGCInProgress() && (this != ThreadSuspend::GetSuspensionThread())) || (m_State & (TS_UserSuspendPending | TS_DebugSuspendPending | TS_StackCrawlNeeded))) && (!g_fSuspendOnShutdown || IsFinalizerThread() || IsShutdownSpecialThread())) { @@ -3350,7 +3350,7 @@ void Thread::RareDisablePreemptiveGC() DWORD status = S_OK; SetThreadStateNC(TSNC_WaitUntilGCFinished); - status = GCHeap::GetGCHeap()->WaitUntilGCComplete(); + status = GCHeapUtilities::GetGCHeap()->WaitUntilGCComplete(); ResetThreadStateNC(TSNC_WaitUntilGCFinished); if (status == (DWORD)COR_E_STACKOVERFLOW) @@ -3359,7 +3359,7 @@ void Thread::RareDisablePreemptiveGC() // 1. GC is suspending the process. GC needs to wait. // 2. GC is proceeding after suspension. The current thread needs to spin. SetThreadState(TS_BlockGCForSO); - while (GCHeap::IsGCInProgress() && m_fPreemptiveGCDisabled.Load() == 0) + while (GCHeapUtilities::IsGCInProgress() && m_fPreemptiveGCDisabled.Load() == 0) { #undef Sleep // We can not go to a host for blocking operation due ot lack of stack. @@ -3376,7 +3376,7 @@ void Thread::RareDisablePreemptiveGC() break; } } - if (!GCHeap::IsGCInProgress()) + if (!GCHeapUtilities::IsGCInProgress()) { if (HasThreadState(TS_StackCrawlNeeded)) { @@ -3411,7 +3411,7 @@ void Thread::RareDisablePreemptiveGC() // thread while in this loop. This happens if you use the COM+ // debugger to suspend this thread and then release it. - } while ((GCHeap::IsGCInProgress() && (this != ThreadSuspend::GetSuspensionThread())) || + } while ((GCHeapUtilities::IsGCInProgress() && (this != ThreadSuspend::GetSuspensionThread())) || (m_State & (TS_UserSuspendPending | TS_DebugSuspendPending | TS_StackCrawlNeeded))); } STRESS_LOG0(LF_SYNC, LL_INFO1000, "RareDisablePreemptiveGC: leaving\n"); @@ -3705,7 +3705,7 @@ void Thread::PerformPreemptiveGC() if (!GCStressPolicy::IsEnabled() || !GCStress<cfg_transition>::IsEnabled()) return; - if (!GCHeap::IsGCHeapInitialized()) + if (!GCHeapUtilities::IsGCHeapInitialized()) return; if (!m_GCOnTransitionsOK @@ -3713,8 +3713,8 @@ void Thread::PerformPreemptiveGC() || RawGCNoTrigger() #endif || g_fEEShutDown - || GCHeap::IsGCInProgress(TRUE) - || GCHeap::GetGCHeap()->GetGcCount() == 0 // Need something that works for isolated heap. + || GCHeapUtilities::IsGCInProgress(TRUE) + || GCHeapUtilities::GetGCHeap()->GetGcCount() == 0 // Need something that works for isolated heap. || ThreadStore::HoldingThreadStore()) return; @@ -3738,7 +3738,7 @@ void Thread::PerformPreemptiveGC() { GCX_COOP(); m_bGCStressing = TRUE; - GCHeap::GetGCHeap()->StressHeap(); + GCHeapUtilities::GetGCHeap()->StressHeap(); m_bGCStressing = FALSE; } m_GCOnTransitionsOK = TRUE; @@ -4846,7 +4846,7 @@ HRESULT ThreadSuspend::SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason) // Caller is expected to be holding the ThreadStore lock. Also, caller must // have set GcInProgress before coming here, or things will break; _ASSERTE(ThreadStore::HoldingThreadStore() || IsAtProcessExit()); - _ASSERTE(GCHeap::IsGCInProgress() ); + _ASSERTE(GCHeapUtilities::IsGCInProgress() ); STRESS_LOG1(LF_SYNC, LL_INFO1000, "Thread::SuspendRuntime(reason=0x%x)\n", reason); @@ -5547,7 +5547,7 @@ void ThreadSuspend::ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceded) // reset GcInProgress, or threads will continue to suspend themselves and won't // be resumed until the next GC. _ASSERTE(IsGCSpecialThread() || ThreadStore::HoldingThreadStore()); - _ASSERTE(!GCHeap::IsGCInProgress() ); + _ASSERTE(!GCHeapUtilities::IsGCInProgress() ); STRESS_LOG2(LF_SYNC, LL_INFO1000, "Thread::ResumeRuntime(finishedGC=%d, SuspendSucceeded=%d) - Start\n", bFinishedGC, SuspendSucceded); @@ -5564,7 +5564,7 @@ void ThreadSuspend::ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceded) { // If we the suspension was for a GC, tell the host what generation GC. DWORD Generation = (bFinishedGC - ? GCHeap::GetGCHeap()->GetCondemnedGeneration() + ? GCHeapUtilities::GetGCHeap()->GetCondemnedGeneration() : ~0U); pGCThreadControl->SuspensionEnding(Generation); @@ -5574,7 +5574,7 @@ void ThreadSuspend::ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceded) { // If we the suspension was for a GC, tell the host what generation GC. DWORD Generation = (bFinishedGC - ? GCHeap::GetGCHeap()->GetCondemnedGeneration() + ? GCHeapUtilities::GetGCHeap()->GetCondemnedGeneration() : ~0U); BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread()); @@ -7898,7 +7898,7 @@ void ThreadSuspend::RestartEE(BOOL bFinishedGC, BOOL SuspendSucceded) // Revert to being a normal thread // ClrFlsClearThreadType (ThreadType_DynamicSuspendEE); - GCHeap::GetGCHeap()->SetGCInProgress(FALSE); + GCHeapUtilities::GetGCHeap()->SetGCInProgress(FALSE); // // Allow threads to enter COOP mode (though we still need to wake the ones @@ -7906,7 +7906,7 @@ void ThreadSuspend::RestartEE(BOOL bFinishedGC, BOOL SuspendSucceded) // // Note: this is the last barrier that keeps managed threads // from entering cooperative mode. If the sequence changes, - // you may have to change routine GCHeap::SafeToRestartManagedThreads + // you may have to change routine GCHeapUtilities::SafeToRestartManagedThreads // as well. // ThreadStore::TrapReturningThreads(FALSE); @@ -7915,7 +7915,7 @@ void ThreadSuspend::RestartEE(BOOL bFinishedGC, BOOL SuspendSucceded) // // Any threads that are waiting in WaitUntilGCComplete will continue now. // - GCHeap::GetGCHeap()->GetWaitForGCEvent()->Set(); + GCHeapUtilities::GetGCHeap()->GetWaitForGCEvent()->Set(); _ASSERTE(IsGCSpecialThread() || ThreadStore::HoldingThreadStore()); ResumeRuntime(bFinishedGC, SuspendSucceded); @@ -7964,7 +7964,7 @@ void ThreadSuspend::SuspendEE(SUSPEND_REASON reason) ETW::GCLog::ETW_GC_INFO Info; Info.SuspendEE.Reason = reason; Info.SuspendEE.GcCount = (((reason == SUSPEND_FOR_GC) || (reason == SUSPEND_FOR_GC_PREP)) ? - (ULONG)GCHeap::GetGCHeap()->GetGcCount() : (ULONG)-1); + (ULONG)GCHeapUtilities::GetGCHeap()->GetGcCount() : (ULONG)-1); FireEtwGCSuspendEEBegin_V1(Info.SuspendEE.Reason, Info.SuspendEE.GcCount, GetClrInstanceId()); @@ -8041,7 +8041,7 @@ retry_for_debugger: // // First, we reset the event that we're about to tell other threads to wait for. // - GCHeap::GetGCHeap()->GetWaitForGCEvent()->Reset(); + GCHeapUtilities::GetGCHeap()->GetWaitForGCEvent()->Reset(); // // Remember that we're the one doing the GC. Actually, maybe we're not doing a GC - @@ -8066,7 +8066,7 @@ retry_for_debugger: // It seems like much of the above is redundant. We should investigate reducing the number // of mechanisms we use to indicate that a suspension is in progress. // - GCHeap::GetGCHeap()->SetGCInProgress(TRUE); + GCHeapUtilities::GetGCHeap()->SetGCInProgress(TRUE); // // Gratuitous memory barrier. (may be needed - but I'm not sure why.) @@ -8357,7 +8357,7 @@ void ThreadSuspend::Initialize() BOOL Debug_IsLockedViaThreadSuspension() { LIMITED_METHOD_CONTRACT; - return GCHeap::IsGCInProgress() && + return GCHeapUtilities::IsGCInProgress() && (dbgOnly_IsSpecialEEThread() || IsGCSpecialThread() || GetThread() == ThreadSuspend::GetSuspensionThread()); @@ -8485,7 +8485,7 @@ void SuspendStatistics::EndSuspend(BOOL bForGC) // details on suspends... if (!bForGC) cntNonGCSuspends++; - if (GCHeap::GetGCHeap()->IsConcurrentGCInProgress()) + if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCInProgress()) { cntSuspendsInBGC++; if (!bForGC) diff --git a/src/vm/vars.hpp b/src/vm/vars.hpp index d197e0559d..4148725769 100644 --- a/src/vm/vars.hpp +++ b/src/vm/vars.hpp @@ -81,7 +81,7 @@ typedef unsigned short wchar_t; class ClassLoader; class LoaderHeap; -class GCHeap; +class IGCHeap; class Object; class StringObject; class TransparentProxyObject; diff --git a/src/vm/win32threadpool.cpp b/src/vm/win32threadpool.cpp index 1121417492..1b4a8690e0 100644 --- a/src/vm/win32threadpool.cpp +++ b/src/vm/win32threadpool.cpp @@ -2367,11 +2367,11 @@ Work: counts = oldCounts; } - if (GCHeap::IsGCInProgress(TRUE)) + if (GCHeapUtilities::IsGCInProgress(TRUE)) { // GC is imminent, so wait until GC is complete before executing next request. // this reduces in-flight objects allocated right before GC, easing the GC's work - GCHeap::WaitForGCCompletion(TRUE); + GCHeapUtilities::WaitForGCCompletion(TRUE); } { @@ -3986,7 +3986,7 @@ Top: if (key != 0) { - if (GCHeap::IsGCInProgress(TRUE)) + if (GCHeapUtilities::IsGCInProgress(TRUE)) { //Indicate that this thread is free, and waiting on GC, not doing any user work. //This helps in threads not getting injected when some threads have woken up from the @@ -4003,7 +4003,7 @@ Top: // GC is imminent, so wait until GC is complete before executing next request. // this reduces in-flight objects allocated right before GC, easing the GC's work - GCHeap::WaitForGCCompletion(TRUE); + GCHeapUtilities::WaitForGCCompletion(TRUE); while (true) { @@ -4217,7 +4217,7 @@ BOOL ThreadpoolMgr::ShouldGrowCompletionPortThreadpool(ThreadCounter::Counts cou if (counts.NumWorking >= counts.NumActive && NumCPInfrastructureThreads == 0 - && (counts.NumActive == 0 || !GCHeap::IsGCInProgress(TRUE)) + && (counts.NumActive == 0 || !GCHeapUtilities::IsGCInProgress(TRUE)) ) { // adjust limit if neeeded @@ -4618,7 +4618,7 @@ DWORD __stdcall ThreadpoolMgr::GateThreadStart(LPVOID lpArgs) EX_END_CATCH(SwallowAllExceptions); } - if (!GCHeap::IsGCInProgress(FALSE) ) + if (!GCHeapUtilities::IsGCInProgress(FALSE) ) { if (IgnoreNextSample) { @@ -4660,7 +4660,7 @@ DWORD __stdcall ThreadpoolMgr::GateThreadStart(LPVOID lpArgs) oldCounts.NumActive < MaxLimitTotalCPThreads && !g_fCompletionPortDrainNeeded && NumCPInfrastructureThreads == 0 && // infrastructure threads count as "to be free as needed" - !GCHeap::IsGCInProgress(TRUE)) + !GCHeapUtilities::IsGCInProgress(TRUE)) { BOOL status; |