예제 #1
0
        /// <summary>
        /// Scan the type and its base types for an implementation of an interface method. Returns null if no
        /// implementation is found.
        /// </summary>
        public static MethodDesc ResolveInterfaceMethodTarget(this TypeDesc thisType, MethodDesc interfaceMethodToResolve)
        {
            Debug.Assert(interfaceMethodToResolve.OwningType.IsInterface);

            MethodDesc result      = null;
            TypeDesc   currentType = thisType;

            do
            {
                result      = currentType.ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethodToResolve);
                currentType = currentType.BaseType;
            }while (result == null && currentType != null);

            return(result);
        }
예제 #2
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);
            }

            // Non-virtual methods called through constraints simply resolve to the specified method without constraint resolution.
            if (!interfaceMethod.IsVirtual)
            {
                return(null);
            }

            MethodDesc method;

            MethodDesc genInterfaceMethod = interfaceMethod.GetMethodDefinition();

            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

                // TODO: this code assumes no shared generics
                Debug.Assert(interfaceType == interfaceMethod.OwningType);

                method = constrainedType.ResolveInterfaceMethodToVirtualMethodOnType(genInterfaceMethod);
            }
            else if (genInterfaceMethod.IsVirtual)
            {
                method = constrainedType.FindVirtualFunctionTargetMethodOnObjectType(genInterfaceMethod);
            }
            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 (interfaceMethod.HasInstantiation)
            {
                method = method.MakeInstantiatedMethod(interfaceMethod.Instantiation);
            }

            Debug.Assert(method != null);
            //assert(!pMD->IsUnboxingStub());

            return(method);
        }
예제 #3
0
        /// <summary>
        /// Resolve a call on the interface method targetVirtualMethod, on the type instanceDefTypeToExamine utilizing metadata to
        /// its associated virtual method.
        /// </summary>
        /// <param name="instanceDefTypeToExamine">(in) The class type on which the interface call is made, (out) the class type where the search may continue using non-metadata means</param>
        /// <param name="targetVirtualMethod">The interface method to translate into a virtual method for execution</param>
        /// <returns>virtual method slot which implements the interface method OR null if an implementation should fall back to non-metadata based lookup.</returns>
        public static MethodDesc ResolveInterfaceMethodToVirtualMethod(TypeDesc instanceType, out TypeDesc instanceDefTypeToExamine, MethodDesc targetVirtualMethod)
        {
            instanceDefTypeToExamine = instanceType.GetClosestDefType();

            MethodDesc newlyFoundVirtualMethod = null;
            LowLevelList<MethodDesc> variantTargets = null;

            if (targetVirtualMethod.OwningType.HasVariance)
            {
                foreach (TypeDesc type in instanceType.RuntimeInterfaces)
                {
                    if (type != targetVirtualMethod.OwningType &&
                        type.GetTypeDefinition() == targetVirtualMethod.OwningType.GetTypeDefinition())
                    {
                        // Check to see if these interfaces are appropriately assignable
                        if (RuntimeAugments.IsAssignableFrom(targetVirtualMethod.OwningType.GetRuntimeTypeHandle(), type.GetRuntimeTypeHandle()))
                        {
                            if (variantTargets == null)
                                variantTargets = new LowLevelList<MethodDesc>();

                            MethodDesc targetVariantMatch = type.Context.GetMethodForInstantiatedType(
                                targetVirtualMethod.GetTypicalMethodDefinition(),
                                (InstantiatedType)type);

                            variantTargets.Add(targetVariantMatch);
                        }
                    }
                }
            }

            do
            {
                newlyFoundVirtualMethod = instanceDefTypeToExamine.ResolveInterfaceMethodToVirtualMethodOnType(targetVirtualMethod);

                if (newlyFoundVirtualMethod == null && variantTargets != null)
                {
                    for (int i = 0; i < variantTargets.Count; i++)
                    {
                        newlyFoundVirtualMethod = instanceDefTypeToExamine.ResolveInterfaceMethodToVirtualMethodOnType(variantTargets[i]);
                        if (newlyFoundVirtualMethod != null)
                            break;
                    }
                }
                instanceDefTypeToExamine = instanceDefTypeToExamine.BaseType;
            } while ((newlyFoundVirtualMethod == null) && (instanceDefTypeToExamine != null) && !IsPregeneratedOrTemplateTypeLoaded(instanceDefTypeToExamine));

            return newlyFoundVirtualMethod;
        }