Skip to content

Commit dd76387

Browse files
filipnavaraagocke
andauthored
Improve performance of interface method resolution in ILC (#103066)
* Reverse order of loop in MightHaveInterfaceDispatchMap Presumably the last interfaces on the list are more likely to be coming from the less nested classes and allow short circuiting the loop earlier. * Short-circuit recursive ResolveInterfaceMethodToVirtualMethodOnType When ResolveInterfaceMethodToVirtualMethodOnType is recursively calling itself, use the result instead of returning `null` and then continuing the outer loop that is effectively doing the same recursion on base types. * Add comment --------- Co-authored-by: Andy Gocke <angocke@microsoft.com>
1 parent 6c58f79 commit dd76387

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,18 @@ public override MethodDesc ResolveVariantInterfaceMethodToStaticVirtualMethodOnT
629629
// function returns null if the interface method implementation is not defined by the current type in
630630
// the hierarchy.For variance to work correctly, this requires that interfaces be queried in correct order.
631631
// See current interface call resolution for details on how that happens.
632-
private static MethodDesc ResolveInterfaceMethodToVirtualMethodOnType(MethodDesc interfaceMethod, MetadataType currentType)
632+
//
633+
// The returnRecursive parameter is solely intended to optimize the recursion through
634+
// the ResolveInterfaceMethodToVirtualMethodOnTypeRecursive helper method and should not
635+
// be used for anything else. ResolveInterfaceMethodToVirtualMethodOnTypeRecursive walks
636+
// up the type hierarchy, calls ResolveInterfaceMethodToVirtualMethodOnType on each base
637+
// type, and bails out on a first successful match. Since we perform the same expansion in
638+
// the last branch of this method by calling ResolveInterfaceMethodToVirtualMethodOnTypeRecursive
639+
// for the base type, we allow the caller to specify that such computed value should be
640+
// returned instead of discarded. This allows short-circuiting the outer loop over type
641+
// hierarchy and avoids unnecessary exponential algorithmic complexity of the resolution
642+
// algorithm.
643+
private static MethodDesc ResolveInterfaceMethodToVirtualMethodOnType(MethodDesc interfaceMethod, MetadataType currentType, bool returnRecursive = false)
633644
{
634645
Debug.Assert(!interfaceMethod.Signature.IsStatic);
635646

@@ -684,7 +695,7 @@ private static MethodDesc ResolveInterfaceMethodToVirtualMethodOnType(MethodDesc
684695
MethodDesc baseClassImplementationOfInterfaceMethod = ResolveInterfaceMethodToVirtualMethodOnTypeRecursive(interfaceMethod, baseType);
685696
if (baseClassImplementationOfInterfaceMethod != null)
686697
{
687-
return null;
698+
return returnRecursive ? baseClassImplementationOfInterfaceMethod : null;
688699
}
689700
else
690701
{
@@ -748,7 +759,7 @@ private static MethodDesc ResolveInterfaceMethodToVirtualMethodOnTypeRecursive(M
748759
return null;
749760
}
750761

751-
MethodDesc currentTypeInterfaceResolution = ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod, currentType);
762+
MethodDesc currentTypeInterfaceResolution = ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod, currentType, returnRecursive: true);
752763
if (currentTypeInterfaceResolution != null)
753764
return currentTypeInterfaceResolution;
754765

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public static bool MightHaveInterfaceDispatchMap(TypeDesc type, NodeFactory fact
8989

9090
DefType declType = type.GetClosestDefType();
9191

92-
for (int interfaceIndex = 0; interfaceIndex < declType.RuntimeInterfaces.Length; interfaceIndex++)
92+
for (int interfaceIndex = declType.RuntimeInterfaces.Length - 1; interfaceIndex >= 0; interfaceIndex--)
9393
{
9494
DefType interfaceType = declType.RuntimeInterfaces[interfaceIndex];
9595
InstantiatedType interfaceOnDefinitionType = interfaceType.IsTypeDefinition ?

0 commit comments

Comments
 (0)