Repository: dotnet/runtime
File: src/coreclr/tools/Common/Compiler/DevirtualizationManager.cs (C#)

Code before:
                // The derived class should be a subclass of the base class.
                // this check is performed via typedef checking instead of casting, as we accept canon methods calling exact types
                TypeDesc checkType;
                for (checkType = implType; checkType != null && !checkType.HasSameTypeDefinition(declMethod.OwningType); checkType = checkType.BaseType)
                { }

                if ((checkType == null) || (checkType.ConvertToCanonForm(CanonicalFormKind.Specific) != declMethod.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific)))
                {
                    // The derived class should be a subclass of the base class.
                    devirtualizationDetail = CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_FAILED_SUBCLASS;
                    return null;
                }
                else
                {
                    // At this point, the decl method may be only canonically compatible, but not an exact match to a method in the type hierarchy
                    // Convert it to an exact match. (Or if it is an exact match, the FindMethodOnTypeWithMatchingTypicalMethod will be a no-op)
                    declMethod = checkType.FindMethodOnTypeWithMatchingTypicalMethod(declMethod);
                }

                impl = implType.FindVirtualFunctionTargetMethodOnObjectType(declMethod);

                if (impl != null)
                {
                    // We need to bring the original instantiation back so that we can still try devirtualizing
                    // when the method is a generic virtual method
                    if (originalDeclMethod.HasInstantiation)
                    {
                        // We may end up with a method that has subsituted type parameters, so we need to instantiate
                        // on the method definition
                        impl = impl.GetMethodDefinition().MakeInstantiatedMethod(originalDeclMethod.Instantiation);
                    }

                    if (impl != declMethod)
                    {
                        MethodDesc slotDefiningMethodImpl = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(impl.GetMethodDefinition());
                        MethodDesc slotDefiningMethodDecl = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(declMethod);

                        if (slotDefiningMethodImpl != slotDefiningMethodDecl)
                        {
                            // If the derived method's slot does not match the vtable slot,
                            // bail on devirtualization, as the method was installed into
                            // the vtable slot via an explicit override and even if the
                            // method is final, the slot may not be.
                            //
                            // Note the jit could still safely devirtualize if it had an exact
                            // class, but such cases are likely rare.
                            devirtualizationDetail = CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_FAILED_SLOT;
                            impl = null;
                        }

                    }

Review comment (refactor):
Could you move this right under the `impl = implType.FindVirtualFunctionTargetMethodOnObjectType(declMethod);` line as `if (impl != null && originalDeclMethod.HasInstantiation)` to reduce the diff in this PR and nesting?

The fact that `FindVirtualFunctionTargetMethodOnObjectType` will strip the method instantiation is a nuisance. I'd like to fix these (there's a couple more resolution APIs that annoying do this) at some point. But let's not perturb the git history for this wart.

Code after:
                // The derived class should be a subclass of the base class.
                // this check is performed via typedef checking instead of casting, as we accept canon methods calling exact types
                TypeDesc checkType;
                for (checkType = implType; checkType != null && !checkType.HasSameTypeDefinition(declMethod.OwningType); checkType = checkType.BaseType)
                { }

                if ((checkType == null) || (checkType.ConvertToCanonForm(CanonicalFormKind.Specific) != declMethod.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific)))
                {
                    // The derived class should be a subclass of the base class.
                    devirtualizationDetail = CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_FAILED_SUBCLASS;
                    return null;
                }
                else
                {
                    // At this point, the decl method may be only canonically compatible, but not an exact match to a method in the type hierarchy
                    // Convert it to an exact match. (Or if it is an exact match, the FindMethodOnTypeWithMatchingTypicalMethod will be a no-op)
                    declMethod = checkType.FindMethodOnTypeWithMatchingTypicalMethod(declMethod);
                }

                impl = implType.FindVirtualFunctionTargetMethodOnObjectType(declMethod);

                // We need to bring the original instantiation back so that we can still try devirtualizing
                // when the method is a generic virtual method
                if (impl != null && originalDeclMethod.HasInstantiation)
                {
                    // We may end up with a method that has substituted type parameters, so we need to instantiate
                    // on the method definition
                    impl = impl.GetMethodDefinition().MakeInstantiatedMethod(originalDeclMethod.Instantiation);
                }

                if (impl != null && (impl != declMethod))
                {
                    MethodDesc slotDefiningMethodImpl = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(impl.GetMethodDefinition());
                    MethodDesc slotDefiningMethodDecl = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(declMethod);

                    if (slotDefiningMethodImpl != slotDefiningMethodDecl)
                    {
                        // If the derived method's slot does not match the vtable slot,
                        // bail on devirtualization, as the method was installed into
                        // the vtable slot via an explicit override and even if the
                        // method is final, the slot may not be.
                        //
                        // Note the jit could still safely devirtualize if it had an exact
                        // class, but such cases are likely rare.
                        devirtualizationDetail = CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_FAILED_SLOT;
                        impl = null;
                    }
                }
            }

            if (impl != null && impl.HasInstantiation && impl.GetCanonMethodTarget(CanonicalFormKind.Specific).IsCanonicalMethod(CanonicalFormKind.Specific))