Fix profiler\gc\gcbasic test to work with SVR GC on many cores. (#54057)
authorPeter Sollich <petersol@microsoft.com>
Sun, 13 Jun 2021 15:25:30 +0000 (17:25 +0200)
committerGitHub <noreply@github.com>
Sun, 13 Jun 2021 15:25:30 +0000 (17:25 +0200)
Problem was that we had a fixed size buffer (32 entries), and we may have way more generation bounds than that, especially with regions.

Fix is to heap allocate the buffer if the size of the buffer on the stack is exceeded.

src/tests/profiler/native/gcbasicprofiler/gcbasicprofiler.cpp

index dfea99b..a9f2801 100644 (file)
@@ -66,33 +66,64 @@ HRESULT GCBasicProfiler::GarbageCollectionStarted(int cGenerations, BOOL generat
     if(_gcStarts == 1)
     {
         ULONG nObjectRanges;
-        const ULONG cRanges = 32;
-        COR_PRF_GC_GENERATION_RANGE objectRanges[cRanges];
+        bool fHeapAlloc = false;
+        COR_PRF_GC_GENERATION_RANGE* pObjectRanges = nullptr;
+        {
+            const ULONG cRanges = 32;
+            COR_PRF_GC_GENERATION_RANGE objectRangesStackBuffer[cRanges];
+
+            HRESULT hr = pCorProfilerInfo->GetGenerationBounds(cRanges, &nObjectRanges, objectRangesStackBuffer);
+            if (FAILED(hr))
+            {
+                _failures++;
+                printf("GCBasicProfiler::GarbageCollectionStarted: FAIL: GetGenerationBounds hr=0x%x\n", hr);
+                return S_OK;
+            }
+            if (nObjectRanges <= cRanges)
+            {
+                pObjectRanges = objectRangesStackBuffer;
+            }
+        }
 
-        HRESULT hr = pCorProfilerInfo->GetGenerationBounds(cRanges, &nObjectRanges, objectRanges);
-        if (FAILED(hr))
+        if (pObjectRanges == nullptr)
         {
-            _failures++;
-            printf("GCBasicProfiler::GarbageCollectionStarted: FAIL: GetGenerationBounds hr=0x%x\n", hr);
-            return S_OK;
+            pObjectRanges = new COR_PRF_GC_GENERATION_RANGE[nObjectRanges];
+            if (pObjectRanges == nullptr)
+            {
+                _failures++;
+                printf("Couldn't allocate buffer for generation ranges\n");
+                return S_OK;
+            }
+            fHeapAlloc = true;
+
+            ULONG nObjectRanges2;
+            HRESULT hr = pCorProfilerInfo->GetGenerationBounds(nObjectRanges, &nObjectRanges2, pObjectRanges);
+            if (FAILED(hr) || nObjectRanges != nObjectRanges2)
+            {
+                _failures++;
+                printf("GCBasicProfiler::GarbageCollectionStarted: FAIL: GetGenerationBounds hr=0x%x, %d != %d\n", hr, nObjectRanges, nObjectRanges2);
+                return S_OK;
+            }
         }
         // loop through all ranges
         for (int i = nObjectRanges - 1; i >= 0; i--)
         {
-            if (0 > objectRanges[i].generation || objectRanges[i].generation > 4)
+            if (0 > pObjectRanges[i].generation || pObjectRanges[i].generation > 4)
             {
                 _failures++;
-                printf("GCBasicProfiler::GarbageCollectionStarted: FAIL: invalid generation: %d\n",objectRanges[i].generation);
+                printf("GCBasicProfiler::GarbageCollectionStarted: FAIL: invalid generation: %d\n",pObjectRanges[i].generation);
             }
         }
-        if (nObjectRanges > 3 && objectRanges[2].generation == 2 && objectRanges[2].rangeLength == 0x18 && objectRanges[2].generation == 1)
+        if (nObjectRanges > 3 && pObjectRanges[2].generation == 2 && pObjectRanges[2].rangeLength == 0x18 && pObjectRanges[2].generation == 1)
         {
-            if (objectRanges[3].rangeLength != 0x18)
+            if (pObjectRanges[3].rangeLength != 0x18)
             {
                 _failures++;
                 printf("GCBasicProfiler::GarbageCollectionStarted: FAIL: in the first GC for the segment case, gen 1 should have size 0x18");
             }
         }
+        if (fHeapAlloc)
+            delete[] pObjectRanges;
     }
 
     return S_OK;