diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 4687027514a62..cd1736ad8c9cc 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -46166,7 +46166,7 @@ void gc_heap::descr_generations_to_profiler (gen_walk_fn fn, void *context) for (int curr_gen_number = total_generation_count-1; curr_gen_number >= 0; curr_gen_number--) { generation* gen = hp->generation_of (curr_gen_number); - heap_segment* seg = generation_start_segment (gen); + heap_segment* seg = heap_segment_rw (generation_start_segment (gen)); #ifdef USE_REGIONS while (seg) { @@ -46174,7 +46174,7 @@ void gc_heap::descr_generations_to_profiler (gen_walk_fn fn, void *context) heap_segment_allocated (seg), heap_segment_reserved (seg)); - seg = heap_segment_next (seg); + seg = heap_segment_next_rw (seg); } #else while (seg && (seg != hp->ephemeral_heap_segment)) @@ -46190,7 +46190,7 @@ void gc_heap::descr_generations_to_profiler (gen_walk_fn fn, void *context) (curr_gen_number > max_generation) ? heap_segment_reserved (seg) : heap_segment_allocated (seg)); - seg = heap_segment_next (seg); + seg = heap_segment_next_rw (seg); } if (seg) diff --git a/src/coreclr/gc/gcee.cpp b/src/coreclr/gc/gcee.cpp index 745aefccb69f8..6dd651f173541 100644 --- a/src/coreclr/gc/gcee.cpp +++ b/src/coreclr/gc/gcee.cpp @@ -62,6 +62,7 @@ void GCHeap::ReportGenerationBounds() { g_theGCHeap->DiagDescrGenerations([](void*, int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved) { + ASSERT((0 <= generation) && (generation <= poh_generation)); uint64_t range = static_cast(rangeEnd - rangeStart); uint64_t rangeReserved = static_cast(rangeEndReserved - rangeStart); FIRE_EVENT(GCGenerationRange, (uint8_t)generation, rangeStart, range, rangeReserved); diff --git a/src/coreclr/gc/gceventstatus.h b/src/coreclr/gc/gceventstatus.h index 58d8b2e873a1e..0c95c516305e1 100644 --- a/src/coreclr/gc/gceventstatus.h +++ b/src/coreclr/gc/gceventstatus.h @@ -174,9 +174,9 @@ class GCEventStatus fprintf(stderr, "GCHeapSurvivalAndMovement "); } - if (keyword & GCEventKeyword_GCHeapCollect) + if (keyword & GCEventKeyword_ManagedHeapCollect) { - fprintf(stderr, "GCHeapCollect "); + fprintf(stderr, "ManagedHeapCollect "); } if (keyword & GCEventKeyword_GCHeapAndTypeNames) diff --git a/src/coreclr/gc/gcinterface.h b/src/coreclr/gc/gcinterface.h index 53512895427b2..5f779a3611d79 100644 --- a/src/coreclr/gc/gcinterface.h +++ b/src/coreclr/gc/gcinterface.h @@ -277,7 +277,7 @@ enum GCEventKeyword GCEventKeyword_GCHeapDump = 0x100000, GCEventKeyword_GCSampledObjectAllocationHigh = 0x200000, GCEventKeyword_GCHeapSurvivalAndMovement = 0x400000, - GCEventKeyword_GCHeapCollect = 0x800000, + GCEventKeyword_ManagedHeapCollect = 0x800000, GCEventKeyword_GCHeapAndTypeNames = 0x1000000, GCEventKeyword_GCSampledObjectAllocationLow = 0x2000000, GCEventKeyword_All = GCEventKeyword_GC @@ -287,7 +287,7 @@ enum GCEventKeyword | GCEventKeyword_GCHeapDump | GCEventKeyword_GCSampledObjectAllocationHigh | GCEventKeyword_GCHeapSurvivalAndMovement - | GCEventKeyword_GCHeapCollect + | GCEventKeyword_ManagedHeapCollect | GCEventKeyword_GCHeapAndTypeNames | GCEventKeyword_GCSampledObjectAllocationLow }; diff --git a/src/coreclr/nativeaot/Runtime/eventtrace.cpp b/src/coreclr/nativeaot/Runtime/eventtrace.cpp index 4988dcf37f9fd..e1d9437e980ef 100644 --- a/src/coreclr/nativeaot/Runtime/eventtrace.cpp +++ b/src/coreclr/nativeaot/Runtime/eventtrace.cpp @@ -417,7 +417,7 @@ void ETW::GCLog::EndMovedReferences(size_t profilingContext, } /***************************************************************************/ -/* This implements the public runtime provider's GCHeapCollectKeyword. It +/* This implements the public runtime provider's ManagedHeapCollectKeyword. It performs a full, gen-2, blocking GC. /***************************************************************************/ void ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber) diff --git a/src/coreclr/nativeaot/Runtime/gcrhenv.cpp b/src/coreclr/nativeaot/Runtime/gcrhenv.cpp index 75dfb0f78c9ac..12158aa676ca5 100644 --- a/src/coreclr/nativeaot/Runtime/gcrhenv.cpp +++ b/src/coreclr/nativeaot/Runtime/gcrhenv.cpp @@ -87,12 +87,12 @@ uint32_t EtwCallback(uint32_t IsEnabled, RH_ETW_CONTEXT * pContext) GCHeapUtilities::GetGCHeap()->DiagTraceGCSegments(); } - // Special check for the runtime provider's GCHeapCollectKeyword. Profilers + // Special check for the runtime provider's ManagedHeapCollectKeyword. Profilers // flick this to force a full GC. if (IsEnabled && (pContext->RegistrationHandle == Microsoft_Windows_Redhawk_GC_PublicHandle) && GCHeapUtilities::IsGCHeapInitialized() && - ((pContext->MatchAnyKeyword & CLR_GCHEAPCOLLECT_KEYWORD) != 0)) + ((pContext->MatchAnyKeyword & CLR_MANAGEDHEAPCOLLECT_KEYWORD) != 0)) { // Profilers may (optionally) specify extra data in the filter parameter // to log with the GCStart event. diff --git a/src/coreclr/nativeaot/Runtime/rheventtrace.h b/src/coreclr/nativeaot/Runtime/rheventtrace.h index 004907d6393d4..253a037175295 100644 --- a/src/coreclr/nativeaot/Runtime/rheventtrace.h +++ b/src/coreclr/nativeaot/Runtime/rheventtrace.h @@ -40,7 +40,7 @@ #define CLR_GCHEAPDUMP_KEYWORD 0x100000 #define CLR_GCHEAPALLOC_KEYWORD 0x200000 #define CLR_GCHEAPSURVIVALANDMOVEMENT_KEYWORD 0x400000 -#define CLR_GCHEAPCOLLECT_KEYWORD 0x800000 +#define CLR_MANAGEDHEAPCOLLECT_KEYWORD 0x800000 #define CLR_GCHEAPANDTYPENAMES_KEYWORD 0x1000000 #define CLR_PERFTRACK_KEYWORD 0x20000000 #define CLR_STACK_KEYWORD 0x40000000 diff --git a/src/coreclr/vm/ClrEtwAll.man b/src/coreclr/vm/ClrEtwAll.man index 644b1b8e58898..18f44568bf786 100644 --- a/src/coreclr/vm/ClrEtwAll.man +++ b/src/coreclr/vm/ClrEtwAll.man @@ -57,8 +57,8 @@ message="$(string.RuntimePublisher.GCSampledObjectAllocationHighKeywordMessage)" symbol="CLR_GCHEAPALLOCHIGH_KEYWORD"/> - + @@ -9074,7 +9074,7 @@ - + diff --git a/src/coreclr/vm/eventtrace.cpp b/src/coreclr/vm/eventtrace.cpp index f2d83ebee3f66..7c7a24f2cf4a1 100644 --- a/src/coreclr/vm/eventtrace.cpp +++ b/src/coreclr/vm/eventtrace.cpp @@ -851,7 +851,7 @@ VOID ETW::GCLog::EndMovedReferences(size_t profilingContext, BOOL fAllowProfApiN } /***************************************************************************/ -/* This implements the public runtime provider's GCHeapCollectKeyword. It +/* This implements the public runtime provider's ManagedHeapCollectKeyword. It performs a full, gen-2, blocking GC. */ /***************************************************************************/ VOID ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber) @@ -4326,10 +4326,10 @@ void InitializeEventTracing() // that ultimately funnels them all into a common handler. #if defined(HOST_UNIX) -// CLR_GCHEAPCOLLECT_KEYWORD is defined by the generated ETW manifest on Windows. +// CLR_MANAGEDHEAPCOLLECT_KEYWORD is defined by the generated ETW manifest on Windows. // On non-Windows, we need to make sure that this is defined. Given that we can't change // the value due to compatibility, we specify it here rather than generating defines based on the manifest. -#define CLR_GCHEAPCOLLECT_KEYWORD 0x800000 +#define CLR_MANAGEDHEAPCOLLECT_KEYWORD 0x800000 #endif // defined(HOST_UNIX) // CallbackProviderIndex provides a quick identification of which provider triggered the @@ -4417,10 +4417,10 @@ VOID EtwCallbackCommon( GCHeapUtilities::RecordEventStateChange(bIsPublicTraceHandle, keywords, level); } - // Special check for the runtime provider's GCHeapCollectKeyword. Profilers + // Special check for the runtime provider's ManagedHeapCollectKeyword. Profilers // flick this to force a full GC. if (g_fEEStarted && !g_fEEShutDown && bIsPublicTraceHandle && - ((MatchAnyKeyword & CLR_GCHEAPCOLLECT_KEYWORD) != 0)) + ((MatchAnyKeyword & CLR_MANAGEDHEAPCOLLECT_KEYWORD) != 0)) { // Profilers may (optionally) specify extra data in the filter parameter // to log with the GCStart event. diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index 92df0d4b94906..845296fc12861 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -7689,7 +7689,7 @@ HRESULT ProfToEEInterfaceImpl::GetNonGCHeapBounds(ULONG cObjectRanges, ranges[segIdx].rangeStart = (ObjectID)firstObj; // Total size reserved for a segment - ranges[segIdx].rangeLengthReserved = (UINT_PTR)segments[segIdx]->m_Size; + ranges[segIdx].rangeLengthReserved = (UINT_PTR)segments[segIdx]->m_Size - sizeof(ObjHeader); // Size of the segment that is currently in use ranges[segIdx].rangeLength = (UINT_PTR)(segments[segIdx]->m_pCurrent - firstObj); diff --git a/src/tests/profiler/native/nongcheap/nongcheap.cpp b/src/tests/profiler/native/nongcheap/nongcheap.cpp index eca9270d33b43..d517112c4d6fd 100644 --- a/src/tests/profiler/native/nongcheap/nongcheap.cpp +++ b/src/tests/profiler/native/nongcheap/nongcheap.cpp @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. #include "nongcheap.h" +#include GUID NonGcHeapProfiler::GetClsid() { @@ -59,17 +60,20 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished() _garbageCollections++; - const int MAX_NON_GC_HEAP_SEGMENTS = 16; - COR_PRF_NONGC_HEAP_RANGE segments[MAX_NON_GC_HEAP_SEGMENTS]; + std::vector segment_starts; + std::vector segment_ends; + const int MAX_SEGMENTS = 16; + COR_PRF_NONGC_HEAP_RANGE nongc_segments[MAX_SEGMENTS]; + COR_PRF_GC_GENERATION_RANGE gc_segments[MAX_SEGMENTS]; ULONG segCount; ObjectID firstObj = 0; - HRESULT hr = pCorProfilerInfo->GetNonGCHeapBounds(MAX_NON_GC_HEAP_SEGMENTS, &segCount, segments); + HRESULT hr = pCorProfilerInfo->GetNonGCHeapBounds(MAX_SEGMENTS, &segCount, nongc_segments); if (FAILED(hr)) { printf("GetNonGCHeapBounds returned an error\n!"); _failures++; } - else if (segCount == 0 || segCount > MAX_NON_GC_HEAP_SEGMENTS) + else if (segCount == 0 || segCount > MAX_SEGMENTS) { printf("GetNonGCHeapBounds: invalid segCount (%u)\n!", segCount); _failures++; @@ -77,28 +81,85 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished() else { // Save very first object ID to compare with EnumerateNonGCObjects - firstObj = segments[0].rangeStart; + firstObj = nongc_segments[0].rangeStart; printf("\nGetNonGCHeapBounds (segCount = %u):\n", segCount); for (ULONG i = 0; i < segCount; i++) { printf("\tseg#%u, rangeStart=%p, rangeLength=%u, rangeLengthReserved=%u\n", - i, (void*)segments[i].rangeStart, (ULONG)segments[i].rangeLength, (ULONG)segments[i].rangeLengthReserved); + i, (void*)nongc_segments[i].rangeStart, (ULONG)nongc_segments[i].rangeLength, (ULONG)nongc_segments[i].rangeLengthReserved); - if ((ULONG)segments[i].rangeLength > (ULONG)segments[i].rangeLengthReserved) + if ((ULONG)nongc_segments[i].rangeLength > (ULONG)nongc_segments[i].rangeLengthReserved) { printf("GetNonGCHeapBounds: rangeLength > rangeLengthReserved"); _failures++; } - if (!segments[i].rangeStart) + if (!nongc_segments[i].rangeStart) { printf("GetNonGCHeapBounds: rangeStart is null"); _failures++; } + segment_starts.emplace_back((ULONG)nongc_segments[i].rangeStart); + segment_ends.emplace_back((ULONG)nongc_segments[i].rangeStart + (ULONG)nongc_segments[i].rangeLengthReserved); } printf("\n"); } + hr = pCorProfilerInfo->GetGenerationBounds(MAX_SEGMENTS, &segCount, gc_segments); + if (FAILED(hr)) + { + printf("GetGenerationBounds returned an error\n!"); + _failures++; + } + else if (segCount == 0 || segCount > MAX_SEGMENTS) + { + printf("GetGenerationBounds: invalid segCount (%u)\n!", segCount); + _failures++; + } + else + { + printf("\nGetGenerationBounds (segCount = %u):\n", segCount); + for (ULONG i = 0; i < segCount; i++) + { + printf("\tseg#%u, rangeStart=%p, rangeLength=%u, rangeLengthReserved=%u\n", + i, (void*)gc_segments[i].rangeStart, (ULONG)gc_segments[i].rangeLength, (ULONG)gc_segments[i].rangeLengthReserved); + + if ((ULONG)gc_segments[i].rangeLength > (ULONG)gc_segments[i].rangeLengthReserved) + { + printf("GetGenerationBounds: rangeLength > rangeLengthReserved"); + _failures++; + } + + if (!gc_segments[i].rangeStart) + { + printf("GetGenerationBounds: rangeStart is null"); + _failures++; + } + segment_starts.emplace_back((ULONG)gc_segments[i].rangeStart); + segment_ends.emplace_back((ULONG)gc_segments[i].rangeStart + (ULONG)gc_segments[i].rangeLengthReserved); + } + printf("\n"); + } + sort(segment_starts.begin(), segment_starts.end()); + sort(segment_ends.begin(), segment_ends.end()); + for (size_t i = 0; i < segment_starts.size() - 1; i++) + { + if (segment_starts[i] == segment_starts[i+1]) + { + printf("Duplicated segment starts"); + _failures++; + } + if (segment_ends[i] == segment_ends[i+1]) + { + printf("Duplicated segment ends"); + _failures++; + } + if (segment_ends[i] > segment_starts[i+1]) + { + printf("Overlapping segments\n"); + _failures++; + } + } // Let's make sure we got the same number of objects as we got from the callback // by testing the EnumerateNonGCObjects API.