diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index f7a238c5ce7373..74bab557b4416d 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -8613,18 +8613,18 @@ bool CEEInfo::resolveVirtualMethodHelper(CORINFO_DEVIRTUALIZATION_INFO * info) if (pObjMT->IsArray()) { + if (pBaseMT->IsSharedByGenericInstantiations()) + { + info->detail = CORINFO_DEVIRTUALIZATION_FAILED_CANON; + return false; + } + // Does the array implicitly implement this interface? // isArrayImplicitInterface = pBaseMT->HasInstantiation() && IsImplicitInterfaceOfSZArray(pBaseMT); if (!isArrayImplicitInterface) { - if (pBaseMT->IsSharedByGenericInstantiations()) - { - info->detail = CORINFO_DEVIRTUALIZATION_FAILED_CANON; - return false; - } - // Ensure we can cast the array to the interface type // if (!TypeHandle(pObjMT).CanCastTo(TypeHandle(pBaseMT))) @@ -8650,15 +8650,12 @@ bool CEEInfo::resolveVirtualMethodHelper(CORINFO_DEVIRTUALIZATION_INFO * info) { _ASSERTE(pObjMT->IsArray()); - // We cannot devirtualize unless we know the exact array element type - // - TypeHandle elemType = pObjMT->GetArrayElementTypeHandle(); - if (elemType.IsCanonicalSubtype()) - { - info->detail = CORINFO_DEVIRTUALIZATION_FAILED_LOOKUP; - return false; - } - pDevirtMD = GetActualImplementationForArrayGenericIListOrIReadOnlyListMethod(pBaseMD, elemType); + // The instantiation we want is based on the interface element type, not the + // array element type. + TypeHandle resultElemType = pBaseMT->GetInstantiation()[0]; + // We should have ruled this out above. + _ASSERTE(!resultElemType.IsCanonicalSubtype()); + pDevirtMD = GetActualImplementationForArrayGenericIListOrIReadOnlyListMethod(pBaseMD, resultElemType); } else if (pObjMT->IsSharedByGenericInstantiations() || pBaseMT->IsSharedByGenericInstantiations()) { diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_120270/Runtime_120270.cs b/src/tests/JIT/Regression/JitBlue/Runtime_120270/Runtime_120270.cs new file mode 100644 index 00000000000000..7455331f282124 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_120270/Runtime_120270.cs @@ -0,0 +1,97 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using Xunit; + +class Base{} +class Derived : Base {} + +public class Runtime_120270 +{ + [Fact] + public static int TestEntryPoint() + { + int i = 0; + bool failed = false; + try + { + while (i < 100_000) + { + i++; + var values = new[] { DayOfWeek.Saturday }.Cast(); + foreach (var value in values) + { + } + } + } + catch (Exception ex) + { + Console.WriteLine(i); + Console.WriteLine(ex); + failed = true; + } + + return failed ? -1 : 100; + } + + [Fact] + public static int TestEntryPoint2() + { + bool failed = false; + try + { + Foo([new Derived()]); + } + catch (Exception ex) + { + Console.WriteLine(ex); + failed = true; + } + return failed ? -1 : 100; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Foo(object[] x) + { + int i = 0; + while (i < 100_000) + { + i++; + var values = x.Cast(); + foreach (var value in values) + { + } + } + } + + [Fact] + public static int TestEntryPoint3() + { + Type enumeratorType = null; + for (int i = 0; i < 100_000; i++) + { + Derived[] d = [new Derived()]; + IEnumerable e = d; + IEnumerator en = e.GetEnumerator(); + Type currentEnumeratorType = en.GetType(); + + if (i == 0) + { + Console.WriteLine($"Enumerator type: {currentEnumeratorType.ToString()}"); + enumeratorType = currentEnumeratorType; + } + + if (enumeratorType != currentEnumeratorType) + { + Console.WriteLine($"Enumerator type changed at {i} from {enumeratorType.ToString()} to {currentEnumeratorType.ToString()}"); + return -1; + } + } + return 100; + } +} + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_120270/Runtime_120270.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_120270/Runtime_120270.csproj new file mode 100644 index 00000000000000..501217e4d86892 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_120270/Runtime_120270.csproj @@ -0,0 +1,9 @@ + + + None + True + + + + +