diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs index f1d4cde1ad3bab..bab6cd0e8121df 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs @@ -629,7 +629,18 @@ public override MethodDesc ResolveVariantInterfaceMethodToStaticVirtualMethodOnT // function returns null if the interface method implementation is not defined by the current type in // the hierarchy.For variance to work correctly, this requires that interfaces be queried in correct order. // See current interface call resolution for details on how that happens. - private static MethodDesc ResolveInterfaceMethodToVirtualMethodOnType(MethodDesc interfaceMethod, MetadataType currentType) + // + // The returnRecursive parameter is solely intended to optimize the recursion through + // the ResolveInterfaceMethodToVirtualMethodOnTypeRecursive helper method and should not + // be used for anything else. ResolveInterfaceMethodToVirtualMethodOnTypeRecursive walks + // up the type hierarchy, calls ResolveInterfaceMethodToVirtualMethodOnType on each base + // type, and bails out on a first successful match. Since we perform the same expansion in + // the last branch of this method by calling ResolveInterfaceMethodToVirtualMethodOnTypeRecursive + // for the base type, we allow the caller to specify that such computed value should be + // returned instead of discarded. This allows short-circuiting the outer loop over type + // hierarchy and avoids unnecessary exponential algorithmic complexity of the resolution + // algorithm. + private static MethodDesc ResolveInterfaceMethodToVirtualMethodOnType(MethodDesc interfaceMethod, MetadataType currentType, bool returnRecursive = false) { Debug.Assert(!interfaceMethod.Signature.IsStatic); @@ -684,7 +695,7 @@ private static MethodDesc ResolveInterfaceMethodToVirtualMethodOnType(MethodDesc MethodDesc baseClassImplementationOfInterfaceMethod = ResolveInterfaceMethodToVirtualMethodOnTypeRecursive(interfaceMethod, baseType); if (baseClassImplementationOfInterfaceMethod != null) { - return null; + return returnRecursive ? baseClassImplementationOfInterfaceMethod : null; } else { @@ -748,7 +759,7 @@ private static MethodDesc ResolveInterfaceMethodToVirtualMethodOnTypeRecursive(M return null; } - MethodDesc currentTypeInterfaceResolution = ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod, currentType); + MethodDesc currentTypeInterfaceResolution = ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod, currentType, returnRecursive: true); if (currentTypeInterfaceResolution != null) return currentTypeInterfaceResolution; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs index 74aee3c3dd5dd0..8b1a535fdfca58 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs @@ -89,7 +89,7 @@ public static bool MightHaveInterfaceDispatchMap(TypeDesc type, NodeFactory fact DefType declType = type.GetClosestDefType(); - for (int interfaceIndex = 0; interfaceIndex < declType.RuntimeInterfaces.Length; interfaceIndex++) + for (int interfaceIndex = declType.RuntimeInterfaces.Length - 1; interfaceIndex >= 0; interfaceIndex--) { DefType interfaceType = declType.RuntimeInterfaces[interfaceIndex]; InstantiatedType interfaceOnDefinitionType = interfaceType.IsTypeDefinition ?