You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Build: 🔎 Result validation:⚠️ Validation could not be done without an Azure DevOps build URL on the issue. Please add it to the "Build: 🔎" line. Validation performed at: 7/29/2025 1:27:05 AM UTC
The managed method that calls VSD resolve is System.Linq.Enumerable.ContainsIterate[System.__Canon](System.Collections.Generic.IEnumerable`1<System.__Canon>, System.__Canon, System.Collections.Generic.IEqualityComparer`1<System.__Canon>)
The problem is that "this" points into the method stack frame. Looks like stack allocation did not detect escaping object reference.
Thanks Jan. I was able to get a repro after 38 runs of this. Looks like normally ContainsIterate does not reach the optimized tier.
Were you able to get the dac to load for the coredump above? I would like to know what collection type is being enumerated and verify what code version was running so I can try and create a simpler repro case.
The bug is in conditional escape analysis. Say the collection type is only knowable via GDV, and the likely case is a LinkedList<T> for a ref class T. The LinkedList enumerator first checks if the Count == 0, if so it creates an empty enumerator, if not, a linked list enumerator. For the empty case it (at least for a time) looks like it might allocate a new array enumerator or use the "empty static" enumerator. So there are 4 possible enumerators (unknown, linked list, empty static array, array).
CEA is able to prove the linked list enumerator won't escape, but also thinks the array enumerator won't escape. It also (mistakenly) forces control for empty linked list to always take the array enumerator path (which is stack allocated).
When we clone for CEA we split off the linked list case and force the other 3 cases to make interface calls, but we've stack allocated the array case and so things fail then when we try and enumerate an empty list.
We need to realize that the array enumerator allocation happens on the "failed" side of a CEA and so block its stack allocation.
The code below will repro the issue on linux. On windows we are missing PGO data (possibly from R2R) and do not inline SZGenericArrayEnumeratorBase and so the array enumerator allocation escapes.
This pattern of checking for empty and special casing seems common in many collections, so it's a bit of a mystery still why this bug isn't more prominent. Perhaps the missing PGO is an explanation.
Activity
dotnet-policy-service commentedon Jan 28, 2025
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.
JulieLeeMSFT commentedon Jan 30, 2025
@AndyAyersMS, PTAL.
AndyAyersMS commentedon Feb 13, 2025
Seems like this happened before #111937, so likely something else. Unfortunately, the log is gone already. Will close and hope we get a repro later.
AndyAyersMS commentedon Feb 13, 2025
https://helixr1107v0xdcypoyl9e7f.blob.core.windows.net/dotnet-runtime-refs-pull-112151-merge-4df3d17f7ce144de85/System.Text.RegularExpressions.Tests/1/console.e0976529.log?helixlogtype=result has a more recent repro and hasn't been purged yet, so will look at that.
AndyAyersMS commentedon Feb 19, 2025
This is a very generic GC failure message and the various repros above seem to be quite diverse. So could be more than one underlying issue.
AndyAyersMS commentedon Feb 19, 2025
Dump from example run -- linux arm64 is not very useful?
Can't get very far with either lldb or dotnet-dump.
Going to see if I can get a local repro.
28 remaining items
jkotas commentedon Jul 29, 2025
Adding back "Known Build Error" label so that it gets matched by build analysis.
Hit again in System.Collections.Tests in #117939 on (azurelinux.3.amd64.open.rt:
jkotas commentedon Jul 29, 2025
Analysis of crash dump -
runfo get-helix-payload -j a25026df-8744-4b99-b80d-1e5e9322b482 -w System.Collections.Tests -o c:\helix_payload:Stack trace of the crash:
The managed method that calls VSD resolve is
System.Linq.Enumerable.ContainsIterate[System.__Canon](System.Collections.Generic.IEnumerable`1<System.__Canon>, System.__Canon, System.Collections.Generic.IEqualityComparer`1<System.__Canon>)The problem is that "this" points into the method stack frame. Looks like stack allocation did not detect escaping object reference.
[-]Assert failure '!CREATE_CHECK_STRING(bSmallObjectHeapPtr || bLargeObjectHeapPtr)'[/-][+]System.Collections.Test: Assert failure '!CREATE_CHECK_STRING(bSmallObjectHeapPtr || bLargeObjectHeapPtr)'[/+]jkotas commentedon Jul 29, 2025
I have update the match to be specific to
System.Collections.Testso that this does not get matched against every other GC hole.AndyAyersMS commentedon Jul 29, 2025
Thanks Jan. I was able to get a repro after 38 runs of this. Looks like normally ContainsIterate does not reach the optimized tier.
Were you able to get the dac to load for the coredump above? I would like to know what collection type is being enumerated and verify what code version was running so I can try and create a simpler repro case.
AndyAyersMS commentedon Jul 29, 2025
Looks like it was Tier1 (not OSR) during
LinkedList_Generic_Testsand the collection type wasLinkedList<string>.AndyAyersMS commentedon Jul 29, 2025
Consistent and fairly quick repro:
on the xunit invocation, pass
System.Collections.Tests.dllas an arg 16 times, and addThis executes the test methods enough that we reliably hit the problem.
AndyAyersMS commentedon Jul 29, 2025
The bug is in conditional escape analysis. Say the collection type is only knowable via GDV, and the likely case is a
LinkedList<T>for a ref classT. TheLinkedListenumerator first checks if theCount == 0, if so it creates an empty enumerator, if not, a linked list enumerator. For the empty case it (at least for a time) looks like it might allocate a new array enumerator or use the "empty static" enumerator. So there are 4 possible enumerators (unknown, linked list, empty static array, array).CEA is able to prove the linked list enumerator won't escape, but also thinks the array enumerator won't escape. It also (mistakenly) forces control for empty linked list to always take the array enumerator path (which is stack allocated).
When we clone for CEA we split off the linked list case and force the other 3 cases to make interface calls, but we've stack allocated the array case and so things fail then when we try and enumerate an empty list.
We need to realize that the array enumerator allocation happens on the "failed" side of a CEA and so block its stack allocation.
The code below will repro the issue on linux. On windows we are missing PGO data (possibly from R2R) and do not inline
SZGenericArrayEnumeratorBaseand so the array enumerator allocation escapes.This pattern of checking for empty and special casing seems common in many collections, so it's a bit of a mystery still why this bug isn't more prominent. Perhaps the missing PGO is an explanation.
JIT: fix issue in conditional escape analysis
JIT: fix issue in conditional escape analysis
JIT: fix issue in conditional escape analysis (#118214)