public static MethodDesc ToMethodDesc(this RuntimeMethodHandle rmh, TypeSystemContext typeSystemContext)
        {
            RuntimeTypeHandle      declaringTypeHandle;
            MethodNameAndSignature nameAndSignature;

            RuntimeTypeHandle[] genericMethodArgs;

            if (!TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(rmh, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs))
            {
                return(null);
            }

            QMethodDefinition methodHandle;

            if (!TypeLoaderEnvironment.Instance.TryGetMetadataForTypeMethodNameAndSignature(declaringTypeHandle, nameAndSignature, out methodHandle))
            {
                return(null);
            }

            TypeDesc declaringType = typeSystemContext.ResolveRuntimeTypeHandle(declaringTypeHandle);

            TypeDesc   declaringTypeDefinition = declaringType.GetTypeDefinition();
            MethodDesc typicalMethod           = null;

            if (methodHandle.IsNativeFormatMetadataBased)
            {
                var nativeFormatType = (NativeFormatType)declaringTypeDefinition;
                typicalMethod = nativeFormatType.MetadataUnit.GetMethod(methodHandle.NativeFormatHandle, nativeFormatType);
            }
            else if (methodHandle.IsEcmaFormatMetadataBased)
            {
                var ecmaFormatType = (EcmaType)declaringTypeDefinition;
                typicalMethod = ecmaFormatType.EcmaModule.GetMethod(methodHandle.EcmaFormatHandle);
            }
            Debug.Assert(typicalMethod != null);

            MethodDesc methodOnInstantiatedType = typicalMethod;

            if (declaringType != declaringTypeDefinition)
            {
                methodOnInstantiatedType = typeSystemContext.GetMethodForInstantiatedType(typicalMethod, (InstantiatedType)declaringType);
            }

            MethodDesc instantiatedMethod = methodOnInstantiatedType;

            if (genericMethodArgs != null)
            {
                Debug.Assert(genericMethodArgs.Length > 0);
                Instantiation genericMethodInstantiation = typeSystemContext.ResolveRuntimeTypeHandles(genericMethodArgs);
                typeSystemContext.GetInstantiatedMethod(methodOnInstantiatedType, genericMethodInstantiation);
            }

            return(instantiatedMethod);
        }
Пример #2
0
        /// <summary>
        /// Retrieves method whose runtime handle is suitable for use with GVMLookupForSlot.
        /// </summary>
        public MethodDesc GetTargetOfGenericVirtualMethodCall(MethodDesc calledMethod)
        {
            // Should be a generic virtual method
            Debug.Assert(calledMethod.HasInstantiation && calledMethod.IsVirtual);

            // Needs to be either a concrete method, or a runtime determined form.
            Debug.Assert(!calledMethod.IsCanonicalMethod(CanonicalFormKind.Specific));

            MethodDesc targetMethod           = calledMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
            MethodDesc targetMethodDefinition = targetMethod.GetMethodDefinition();

            MethodDesc slotNormalizedMethodDefinition = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(targetMethodDefinition);

            // If the method defines the slot, we can use that.
            if (slotNormalizedMethodDefinition == targetMethodDefinition)
            {
                return(calledMethod);
            }

            // Normalize to the slot defining method
            MethodDesc slotNormalizedMethod = TypeSystemContext.GetInstantiatedMethod(
                slotNormalizedMethodDefinition,
                targetMethod.Instantiation);

            // Since the slot normalization logic modified what method we're looking at, we need to compute the new target of lookup.
            //
            // If we could use virtual method resolution logic with runtime determined methods, we wouldn't need what we're going
            // to do below.
            MethodDesc runtimeDeterminedSlotNormalizedMethod;

            if (!slotNormalizedMethod.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any))
            {
                // If the owning type is not generic, we can use it as-is, potentially only replacing the runtime-determined
                // method instantiation part.
                runtimeDeterminedSlotNormalizedMethod = slotNormalizedMethod.GetMethodDefinition();
            }
            else
            {
                // If we need a runtime lookup but a normalization to the slot defining method happened above, we need to compute
                // the runtime lookup in terms of the base type that introduced the slot.
                //
                // To do that, we walk the base hierarchy of the runtime determined thing, looking for a type definition that matches
                // the slot-normalized virtual method. We then find the method on that type.
                TypeDesc runtimeDeterminedOwningType = calledMethod.OwningType;

                Debug.Assert(!runtimeDeterminedOwningType.IsInterface);

                while (!slotNormalizedMethod.OwningType.HasSameTypeDefinition(runtimeDeterminedOwningType))
                {
                    TypeDesc runtimeDeterminedBaseTypeDefinition = runtimeDeterminedOwningType.GetTypeDefinition().BaseType;
                    if (runtimeDeterminedBaseTypeDefinition.HasInstantiation)
                    {
                        runtimeDeterminedOwningType = runtimeDeterminedBaseTypeDefinition.InstantiateSignature(runtimeDeterminedOwningType.Instantiation, default);
                    }
                    else
                    {
                        runtimeDeterminedOwningType = runtimeDeterminedBaseTypeDefinition;
                    }
                }

                // Now get the method on the newly found type
                Debug.Assert(runtimeDeterminedOwningType.HasInstantiation);
                runtimeDeterminedSlotNormalizedMethod = TypeSystemContext.GetMethodForInstantiatedType(
                    slotNormalizedMethod.GetTypicalMethodDefinition(),
                    (InstantiatedType)runtimeDeterminedOwningType);
            }

            return(TypeSystemContext.GetInstantiatedMethod(runtimeDeterminedSlotNormalizedMethod, calledMethod.Instantiation));
        }
Пример #3
0
        /// <summary>
        /// Constructs a new instance of <see cref="DelegateCreationInfo"/> set up to construct a delegate of type
        /// '<paramref name="delegateType"/>' pointing to '<paramref name="targetMethod"/>'.
        /// </summary>
        public static DelegateCreationInfo Create(TypeDesc delegateType, MethodDesc targetMethod, NodeFactory factory, bool followVirtualDispatch)
        {
            TypeSystemContext context        = delegateType.Context;
            DefType           systemDelegate = context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType;

            int paramCountTargetMethod = targetMethod.Signature.Length;

            if (!targetMethod.Signature.IsStatic)
            {
                paramCountTargetMethod++;
            }

            DelegateInfo delegateInfo             = context.GetDelegateInfo(delegateType.GetTypeDefinition());
            int          paramCountDelegateClosed = delegateInfo.Signature.Length + 1;
            bool         closed = false;

            if (paramCountDelegateClosed == paramCountTargetMethod)
            {
                closed = true;
            }
            else
            {
                Debug.Assert(paramCountDelegateClosed == paramCountTargetMethod + 1);
            }

            if (targetMethod.Signature.IsStatic)
            {
                MethodDesc invokeThunk;
                MethodDesc initMethod;

                if (!closed)
                {
                    // Open delegate to a static method
                    if (targetMethod.IsNativeCallable)
                    {
                        // If target method is native callable, create a reverse PInvoke delegate
                        initMethod  = systemDelegate.GetKnownMethod("InitializeReversePInvokeThunk", null);
                        invokeThunk = delegateInfo.Thunks[DelegateThunkKind.ReversePinvokeThunk];

                        // You might hit this when the delegate is generic: you need to make the delegate non-generic.
                        // If the code works on Project N, it's because the delegate is used in connection with
                        // AddrOf intrinsic (please validate that). We don't have the necessary AddrOf expansion in
                        // the codegen to make this work without actually constructing the delegate. You can't construct
                        // the delegate if it's generic, even on Project N.
                        // TODO: Make this throw something like "TypeSystemException.InvalidProgramException"?
                        Debug.Assert(invokeThunk != null, "Delegate with a non-native signature for a NativeCallable method");
                    }
                    else
                    {
                        initMethod  = systemDelegate.GetKnownMethod("InitializeOpenStaticThunk", null);
                        invokeThunk = delegateInfo.Thunks[DelegateThunkKind.OpenStaticThunk];
                    }
                }
                else
                {
                    // Closed delegate to a static method (i.e. delegate to an extension method that locks the first parameter)
                    invokeThunk = delegateInfo.Thunks[DelegateThunkKind.ClosedStaticThunk];
                    initMethod  = systemDelegate.GetKnownMethod("InitializeClosedStaticThunk", null);
                }

                var instantiatedDelegateType = delegateType as InstantiatedType;
                if (instantiatedDelegateType != null)
                {
                    invokeThunk = context.GetMethodForInstantiatedType(invokeThunk, instantiatedDelegateType);
                }

                return(new DelegateCreationInfo(
                           factory.MethodEntrypoint(initMethod),
                           targetMethod,
                           TargetKind.ExactCallableAddress,
                           factory.MethodEntrypoint(invokeThunk)));
            }
            else
            {
                if (!closed)
                {
                    throw new NotImplementedException("Open instance delegates");
                }

                string     initializeMethodName = "InitializeClosedInstance";
                MethodDesc targetCanonMethod    = targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
                TargetKind kind;
                if (targetMethod.HasInstantiation)
                {
                    if (targetMethod.IsVirtual)
                    {
                        initializeMethodName = "InitializeClosedInstanceWithGVMResolution";
                        kind = TargetKind.MethodHandle;
                    }
                    else
                    {
                        if (targetMethod != targetCanonMethod)
                        {
                            // Closed delegates to generic instance methods need to be constructed through a slow helper that
                            // checks for the fat function pointer case (function pointer + instantiation argument in a single
                            // pointer) and injects an invocation thunk to unwrap the fat function pointer as part of
                            // the invocation if necessary.
                            initializeMethodName = "InitializeClosedInstanceSlow";
                        }

                        kind = TargetKind.ExactCallableAddress;
                    }
                }
                else
                {
                    if (followVirtualDispatch && targetMethod.IsVirtual)
                    {
                        if (targetMethod.OwningType.IsInterface)
                        {
                            kind = TargetKind.InterfaceDispatch;
                            initializeMethodName = "InitializeClosedInstanceToInterface";
                        }
                        else
                        {
                            kind         = TargetKind.VTableLookup;
                            targetMethod = targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
                        }
                    }
                    else
                    {
                        kind         = TargetKind.CanonicalEntrypoint;
                        targetMethod = targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
                    }
                }

                return(new DelegateCreationInfo(
                           factory.MethodEntrypoint(systemDelegate.GetKnownMethod(initializeMethodName, null)),
                           targetMethod,
                           kind));
            }
        }
Пример #4
0
        /// <summary>
        /// Constructs a new instance of <see cref="DelegateCreationInfo"/> set up to construct a delegate of type
        /// '<paramref name="delegateType"/>' pointing to '<paramref name="targetMethod"/>'.
        /// </summary>
        public static DelegateCreationInfo Create(TypeDesc delegateType, MethodDesc targetMethod, NodeFactory factory, bool followVirtualDispatch)
        {
            TypeSystemContext context        = delegateType.Context;
            DefType           systemDelegate = context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType;

            int paramCountTargetMethod = targetMethod.Signature.Length;

            if (!targetMethod.Signature.IsStatic)
            {
                paramCountTargetMethod++;
            }

            DelegateInfo delegateInfo             = context.GetDelegateInfo(delegateType.GetTypeDefinition());
            int          paramCountDelegateClosed = delegateInfo.Signature.Length + 1;
            bool         closed = false;

            if (paramCountDelegateClosed == paramCountTargetMethod)
            {
                closed = true;
            }
            else
            {
                Debug.Assert(paramCountDelegateClosed == paramCountTargetMethod + 1);
            }

            if (targetMethod.Signature.IsStatic)
            {
                MethodDesc invokeThunk;
                MethodDesc initMethod;

                if (!closed)
                {
                    initMethod  = systemDelegate.GetKnownMethod("InitializeOpenStaticThunk", null);
                    invokeThunk = delegateInfo.Thunks[DelegateThunkKind.OpenStaticThunk];
                }
                else
                {
                    // Closed delegate to a static method (i.e. delegate to an extension method that locks the first parameter)
                    invokeThunk = delegateInfo.Thunks[DelegateThunkKind.ClosedStaticThunk];
                    initMethod  = systemDelegate.GetKnownMethod("InitializeClosedStaticThunk", null);
                }

                var instantiatedDelegateType = delegateType as InstantiatedType;
                if (instantiatedDelegateType != null)
                {
                    invokeThunk = context.GetMethodForInstantiatedType(invokeThunk, instantiatedDelegateType);
                }

                return(new DelegateCreationInfo(
                           factory.MethodEntrypoint(initMethod),
                           targetMethod,
                           TargetKind.ExactCallableAddress,
                           factory.MethodEntrypoint(invokeThunk)));
            }
            else
            {
                if (!closed)
                {
                    throw new NotImplementedException("Open instance delegates");
                }

                string     initializeMethodName = "InitializeClosedInstance";
                MethodDesc targetCanonMethod    = targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
                TargetKind kind;
                if (targetMethod.HasInstantiation)
                {
                    if (followVirtualDispatch && targetMethod.IsVirtual)
                    {
                        initializeMethodName = "InitializeClosedInstanceWithGVMResolution";
                        kind = TargetKind.MethodHandle;
                    }
                    else
                    {
                        if (targetMethod != targetCanonMethod)
                        {
                            // Closed delegates to generic instance methods need to be constructed through a slow helper that
                            // checks for the fat function pointer case (function pointer + instantiation argument in a single
                            // pointer) and injects an invocation thunk to unwrap the fat function pointer as part of
                            // the invocation if necessary.
                            initializeMethodName = "InitializeClosedInstanceSlow";
                        }

                        kind = TargetKind.ExactCallableAddress;
                    }
                }
                else
                {
                    if (followVirtualDispatch && targetMethod.IsVirtual)
                    {
                        if (targetMethod.OwningType.IsInterface)
                        {
                            kind = TargetKind.InterfaceDispatch;
                            initializeMethodName = "InitializeClosedInstanceToInterface";
                        }
                        else
                        {
                            kind         = TargetKind.VTableLookup;
                            targetMethod = targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
                        }
                    }
                    else
                    {
                        kind         = TargetKind.CanonicalEntrypoint;
                        targetMethod = targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
                    }
                }

                return(new DelegateCreationInfo(
                           factory.MethodEntrypoint(systemDelegate.GetKnownMethod(initializeMethodName, null)),
                           targetMethod,
                           kind));
            }
        }
Пример #5
0
        /// <summary>
        /// Attempts to resolve constrained call to <paramref name="interfaceMethod"/> into a concrete non-unboxing
        /// method on <paramref name="constrainedType"/>.
        /// The ability to resolve constraint methods is affected by the degree of code sharing we are performing
        /// for generic code.
        /// </summary>
        /// <returns>The resolved method or null if the constraint couldn't be resolved.</returns>
        public static MethodDesc TryResolveConstraintMethodApprox(this TypeDesc constrainedType, TypeDesc interfaceType, MethodDesc interfaceMethod, out bool forceRuntimeLookup)
        {
            forceRuntimeLookup = false;

            // We can't resolve constraint calls effectively for reference types, and there's
            // not a lot of perf. benefit in doing it anyway.
            if (!constrainedType.IsValueType)
            {
                return(null);
            }

            // Interface method may or may not be fully canonicalized here.
            // It would be canonical on the CoreCLR side so canonicalize here to keep the algorithms similar.
            Instantiation methodInstantiation = interfaceMethod.Instantiation;

            interfaceMethod = interfaceMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);

            // 1. Find the (possibly generic) method that would implement the
            // constraint if we were making a call on a boxed value type.

            TypeDesc          canonType = constrainedType.ConvertToCanonForm(CanonicalFormKind.Specific);
            TypeSystemContext context   = constrainedType.Context;

            MethodDesc genInterfaceMethod = interfaceMethod.GetMethodDefinition();
            MethodDesc method             = null;

            if (genInterfaceMethod.OwningType.IsInterface)
            {
                // Sometimes (when compiling shared generic code)
                // we don't have enough exact type information at JIT time
                // even to decide whether we will be able to resolve to an unboxed entry point...
                // To cope with this case we always go via the helper function if there's any
                // chance of this happening by checking for all interfaces which might possibly
                // be compatible with the call (verification will have ensured that
                // at least one of them will be)

                // Enumerate all potential interface instantiations
                int potentialMatchingInterfaces = 0;
                foreach (DefType potentialInterfaceType in canonType.RuntimeInterfaces)
                {
                    if (potentialInterfaceType.ConvertToCanonForm(CanonicalFormKind.Specific) ==
                        interfaceType.ConvertToCanonForm(CanonicalFormKind.Specific))
                    {
                        potentialMatchingInterfaces++;
                        MethodDesc potentialInterfaceMethod = genInterfaceMethod;
                        if (potentialInterfaceMethod.OwningType != potentialInterfaceType)
                        {
                            potentialInterfaceMethod = context.GetMethodForInstantiatedType(
                                potentialInterfaceMethod.GetTypicalMethodDefinition(), (InstantiatedType)potentialInterfaceType);
                        }

                        method = canonType.ResolveInterfaceMethodToVirtualMethodOnType(potentialInterfaceMethod);

                        // See code:#TryResolveConstraintMethodApprox_DoNotReturnParentMethod
                        if (method != null && !method.OwningType.IsValueType)
                        {
                            // We explicitly wouldn't want to abort if we found a default implementation.
                            // The above resolution doesn't consider the default methods.
                            Debug.Assert(!method.OwningType.IsInterface);
                            return(null);
                        }
                    }
                }

                Debug.Assert(potentialMatchingInterfaces != 0);

                if (potentialMatchingInterfaces > 1)
                {
                    // We have more potentially matching interfaces
                    Debug.Assert(interfaceType.HasInstantiation);

                    bool isExactMethodResolved = false;

                    if (!interfaceType.IsCanonicalSubtype(CanonicalFormKind.Any) &&
                        !interfaceType.IsGenericDefinition &&
                        !constrainedType.IsCanonicalSubtype(CanonicalFormKind.Any) &&
                        !constrainedType.IsGenericDefinition)
                    {
                        // We have exact interface and type instantiations (no generic variables and __Canon used
                        // anywhere)
                        if (constrainedType.CanCastTo(interfaceType))
                        {
                            // We can resolve to exact method
                            MethodDesc exactInterfaceMethod = context.GetMethodForInstantiatedType(
                                genInterfaceMethod.GetTypicalMethodDefinition(), (InstantiatedType)interfaceType);
                            method = constrainedType.ResolveVariantInterfaceMethodToVirtualMethodOnType(exactInterfaceMethod);
                            isExactMethodResolved = method != null;
                        }
                    }

                    if (!isExactMethodResolved)
                    {
                        // We couldn't resolve the interface statically
                        // Notify the caller that it should use runtime lookup
                        // Note that we can leave pMD incorrect, because we will use runtime lookup
                        forceRuntimeLookup = true;
                    }
                }
                else
                {
                    // If we can resolve the interface exactly then do so (e.g. when doing the exact
                    // lookup at runtime, or when not sharing generic code).
                    if (constrainedType.CanCastTo(interfaceType))
                    {
                        MethodDesc exactInterfaceMethod = genInterfaceMethod;
                        if (genInterfaceMethod.OwningType != interfaceType)
                        {
                            exactInterfaceMethod = context.GetMethodForInstantiatedType(
                                genInterfaceMethod.GetTypicalMethodDefinition(), (InstantiatedType)interfaceType);
                        }
                        method = constrainedType.ResolveVariantInterfaceMethodToVirtualMethodOnType(exactInterfaceMethod);
                    }
                }
            }
            else if (genInterfaceMethod.IsVirtual)
            {
                MethodDesc targetMethod = interfaceType.FindMethodOnTypeWithMatchingTypicalMethod(genInterfaceMethod);
                method = constrainedType.FindVirtualFunctionTargetMethodOnObjectType(targetMethod);
            }
            else
            {
                // The method will be null if calling a non-virtual instance
                // methods on System.Object, i.e. when these are used as a constraint.
                method = null;
            }

            if (method == null)
            {
                // Fall back to VSD
                return(null);
            }

            //#TryResolveConstraintMethodApprox_DoNotReturnParentMethod
            // Only return a method if the value type itself declares the method,
            // otherwise we might get a method from Object or System.ValueType
            if (!method.OwningType.IsValueType)
            {
                // Fall back to VSD
                return(null);
            }

            // We've resolved the method, ignoring its generic method arguments
            // If the method is a generic method then go and get the instantiated descriptor
            if (methodInstantiation.Length != 0)
            {
                method = method.MakeInstantiatedMethod(methodInstantiation);
            }

            Debug.Assert(method != null);

            return(method);
        }
Пример #6
0
        public override IEnumerable <CombinedDependencyListEntry> SearchDynamicDependencies(List <DependencyNodeCore <NodeFactory> > markedNodes, int firstNode, NodeFactory factory)
        {
            List <CombinedDependencyListEntry> dynamicDependencies = new List <CombinedDependencyListEntry>();

            TypeDesc methodOwningType = _method.OwningType;
            bool     methodIsShared   = _method.IsSharedByGenericInstantiations;

            TypeSystemContext context = _method.Context;

            for (int i = firstNode; i < markedNodes.Count; i++)
            {
                DependencyNodeCore <NodeFactory> entry = markedNodes[i];
                EETypeNode entryAsEETypeNode           = entry as EETypeNode;

                if (entryAsEETypeNode == null)
                {
                    continue;
                }

                TypeDesc potentialOverrideType = entryAsEETypeNode.Type;
                if (!potentialOverrideType.IsDefType || potentialOverrideType.IsInterface)
                {
                    continue;
                }

                // If method is canonical, don't allow using it with non-canonical types - we can wait until
                // we see the __Canon instantiation. If there isn't one, the canonical method wouldn't be useful anyway.
                if (methodIsShared &&
                    potentialOverrideType.ConvertToCanonForm(CanonicalFormKind.Specific) != potentialOverrideType)
                {
                    continue;
                }

                // Similarly, if the type is canonical but this method instantiation isn't, don't mix them.
                if (!methodIsShared &&
                    potentialOverrideType.IsCanonicalSubtype(CanonicalFormKind.Any))
                {
                    continue;
                }

                // If this is an interface gvm, look for types that implement the interface
                // and other instantantiations that have the same canonical form.
                // This ensure the various slot numbers remain equivalent across all types where there is an equivalence
                // relationship in the vtable.
                if (methodOwningType.IsInterface)
                {
                    // We go over definitions because a single canonical interface method could actually be implemented
                    // by multiple methods - consider:
                    //
                    // class Foo<T, U> : IFoo<T>, IFoo<U>, IFoo<string> { }
                    //
                    // If we ask what implements IFoo<__Canon>.Method, the answer could be "three methods"
                    // and that's expected. We therefore resolve IFoo<__Canon>.Method for each IFoo<!0>.Method,
                    // IFoo<!1>.Method, and IFoo<string>.Method, adding GVMDependencies for each.
                    TypeDesc  potentialOverrideDefinition   = potentialOverrideType.GetTypeDefinition();
                    DefType[] potentialInterfaces           = potentialOverrideType.RuntimeInterfaces;
                    DefType[] potentialDefinitionInterfaces = potentialOverrideDefinition.RuntimeInterfaces;
                    for (int interfaceIndex = 0; interfaceIndex < potentialInterfaces.Length; interfaceIndex++)
                    {
                        if (potentialInterfaces[interfaceIndex].ConvertToCanonForm(CanonicalFormKind.Specific) == methodOwningType)
                        {
                            MethodDesc interfaceMethod = _method.GetMethodDefinition();
                            if (methodOwningType.HasInstantiation)
                            {
                                interfaceMethod = context.GetMethodForInstantiatedType(
                                    _method.GetTypicalMethodDefinition(), (InstantiatedType)potentialDefinitionInterfaces[interfaceIndex]);
                            }

                            MethodDesc slotDecl = potentialOverrideDefinition.InstantiateAsOpen().ResolveInterfaceMethodTarget(interfaceMethod);
                            if (slotDecl == null)
                            {
                                // The method might be implemented through a default interface method
                                var result = potentialOverrideDefinition.InstantiateAsOpen().ResolveInterfaceMethodToDefaultImplementationOnType(interfaceMethod, out slotDecl);
                                if (result != DefaultInterfaceMethodResolution.DefaultImplementation)
                                {
                                    slotDecl = null;
                                }
                            }

                            if (slotDecl != null)
                            {
                                TypeDesc[] openInstantiation = new TypeDesc[_method.Instantiation.Length];
                                for (int instArg = 0; instArg < openInstantiation.Length; instArg++)
                                {
                                    openInstantiation[instArg] = context.GetSignatureVariable(instArg, method: true);
                                }
                                MethodDesc implementingMethodInstantiation = slotDecl.MakeInstantiatedMethod(openInstantiation).InstantiateSignature(potentialOverrideType.Instantiation, _method.Instantiation);
                                dynamicDependencies.Add(new CombinedDependencyListEntry(factory.GVMDependencies(implementingMethodInstantiation.GetCanonMethodTarget(CanonicalFormKind.Specific)), null, "ImplementingMethodInstantiation"));
                            }
                        }
                    }
                }
                else
                {
                    // This is not an interface GVM. Check whether the current type overrides the virtual method.
                    // We might need to change what virtual method we ask about - consider:
                    //
                    // class Base<T> { virtual Method(); }
                    // class Derived : Base<string> { override Method(); }
                    //
                    // We need to resolve Base<__Canon>.Method on Derived, but if we were to ask the virtual
                    // method resolution algorithm, the answer would be "does not override" because Base<__Canon>
                    // is not even in the inheritance hierarchy.
                    //
                    // So we need to modify the question to resolve Base<string>.Method instead and then
                    // canonicalize the result.

                    TypeDesc overrideTypeCur = potentialOverrideType;
                    do
                    {
                        if (overrideTypeCur.ConvertToCanonForm(CanonicalFormKind.Specific) == methodOwningType)
                        {
                            break;
                        }

                        overrideTypeCur = overrideTypeCur.BaseType;
                    }while (overrideTypeCur != null);

                    if (overrideTypeCur == null)
                    {
                        continue;
                    }

                    MethodDesc methodToResolve;
                    if (methodOwningType == overrideTypeCur)
                    {
                        methodToResolve = _method;
                    }
                    else
                    {
                        methodToResolve = context
                                          .GetMethodForInstantiatedType(_method.GetTypicalMethodDefinition(), (InstantiatedType)overrideTypeCur)
                                          .MakeInstantiatedMethod(_method.Instantiation);
                    }

                    MethodDesc instantiatedTargetMethod = potentialOverrideType.FindVirtualFunctionTargetMethodOnObjectType(methodToResolve)
                                                          .GetCanonMethodTarget(CanonicalFormKind.Specific);
                    if (instantiatedTargetMethod != _method)
                    {
                        dynamicDependencies.Add(new CombinedDependencyListEntry(
                                                    factory.GVMDependencies(instantiatedTargetMethod), null, "DerivedMethodInstantiation"));
                    }
                }
            }

            return(dynamicDependencies);
        }