/// <summary>
        /// Returns the result of canonicalizing this method over the given kind of Canon
        /// </summary>
        public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
        {
            InstantiatedMethod canonicalMethodResult = GetCachedCanonValue(kind);

            if (canonicalMethodResult == null)
            {
                bool          instantiationChanged;
                Instantiation canonInstantiation            = Context.ConvertInstantiationToCanonForm(Instantiation, kind, out instantiationChanged);
                MethodDesc    openMethodOnCanonicalizedType = _methodDef.GetCanonMethodTarget(kind);

                if (instantiationChanged || (openMethodOnCanonicalizedType != _methodDef))
                {
                    canonicalMethodResult = Context.GetInstantiatedMethod(openMethodOnCanonicalizedType, canonInstantiation);
                }
                else
                {
                    canonicalMethodResult = this;
                }

                // If the method instantiation is universal, we use a __UniversalCanon for all instantiation arguments for simplicity.
                // This is to not end up having method instantiations like Foo<__UniversalCanon>.Method<int> or Foo<__UniversalCanon>.Method<string>
                // or Foo<__UniversalCanon>.Method<__Canon> or Foo<int>.Method<__UniversalCanon>
                // It should just be Foo<__UniversalCanon>.Method<__UniversalCanon>
                if ((kind == CanonicalFormKind.Specific) &&
                    canonicalMethodResult.IsCanonicalMethod(CanonicalFormKind.Universal))
                {
                    canonicalMethodResult = (InstantiatedMethod)canonicalMethodResult.GetCanonMethodTarget(CanonicalFormKind.Universal);
                }

                SetCachedCanonValue(kind, canonicalMethodResult);
            }

            return(canonicalMethodResult);
        }
 private void InitializeMethodInstantiation(Cts.MethodDesc entity, MethodInstantiation record)
 {
     Cts.InstantiatedMethod instantiation = (Cts.InstantiatedMethod)entity;
     record.Method = HandleQualifiedMethod(instantiation.GetMethodDefinition());
     record.GenericTypeArguments.Capacity = instantiation.Instantiation.Length;
     foreach (Cts.TypeDesc typeArgument in instantiation.Instantiation)
     {
         record.GenericTypeArguments.Add(HandleType(typeArgument));
     }
 }
        void SetCachedCanonValue(CanonicalFormKind kind, InstantiatedMethod value)
        {
            switch(kind)
            {
                case CanonicalFormKind.Specific:
                    Debug.Assert(_specificCanonCache == null || _specificCanonCache == value);
                    _specificCanonCache = value;
                    break;

                case CanonicalFormKind.Universal:
                    Debug.Assert(_universalCanonCache == null || _universalCanonCache == value);
                    _universalCanonCache = value;
                    break;

                default:
                    Debug.Fail("Invalid CanonicalFormKind: " + kind);
                    break;
            }
        }
        void SetCachedCanonValue(CanonicalFormKind kind, InstantiatedMethod value)
        {
            switch (kind)
            {
            case CanonicalFormKind.Specific:
                Debug.Assert(_specificCanonCache == null || _specificCanonCache == value);
                _specificCanonCache = value;
                break;

            case CanonicalFormKind.Universal:
                Debug.Assert(_universalCanonCache == null || _universalCanonCache == value);
                _universalCanonCache = value;
                break;

            default:
                Debug.Fail("Invalid CanonicalFormKind: " + kind);
                break;
            }
        }
Exemple #5
0
        /// <summary>
        /// Returns the result of canonicalizing this method over the given kind of Canon
        /// </summary>
        public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
        {
            InstantiatedMethod canonicalMethodResult = GetCachedCanonValue(kind);

            if (canonicalMethodResult != null)
            {
                return(canonicalMethodResult);
            }

            MethodDesc openMethodOnCanonicalizedType = _methodDef.GetCanonMethodTarget(kind);

            // TODO: We should avoid the array allocation if conversion to canon is not change (take hint from MethodDesc.InstantiateSignature)
            Instantiation newInstantiation = CanonUtilites.ConvertInstantiationToCanonForm(Context, Instantiation, kind);

            canonicalMethodResult = Context.GetInstantiatedMethod(openMethodOnCanonicalizedType, newInstantiation);

            SetCachedCanonValue(kind, canonicalMethodResult);
            return(GetCachedCanonValue(kind));
        }
        /// <summary>
        /// Returns the result of canonicalizing this method over the given kind of Canon
        /// </summary>
        public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
        {
            InstantiatedMethod canonicalMethodResult = GetCachedCanonValue(kind);

            if (canonicalMethodResult == null)
            {
                bool          needsChange;
                Instantiation canonInstantiation = CanonUtilites.ConvertInstantiationToCanonForm(Instantiation, kind, out needsChange);
                if (needsChange)
                {
                    MethodDesc openMethodOnCanonicalizedType = _methodDef.GetCanonMethodTarget(kind);
                    canonicalMethodResult = Context.GetInstantiatedMethod(openMethodOnCanonicalizedType, canonInstantiation);
                }
                else
                {
                    canonicalMethodResult = this;
                }

                SetCachedCanonValue(kind, canonicalMethodResult);
            }

            return(canonicalMethodResult);
        }
        /// <summary>
        /// Returns the result of canonicalizing this method over the given kind of Canon
        /// </summary>
        public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
        {
            InstantiatedMethod canonicalMethodResult = GetCachedCanonValue(kind);

            if (canonicalMethodResult == null)
            {
                bool          instantiationChanged;
                Instantiation canonInstantiation            = Context.ConvertInstantiationToCanonForm(Instantiation, kind, out instantiationChanged);
                MethodDesc    openMethodOnCanonicalizedType = _methodDef.GetCanonMethodTarget(kind);

                if (instantiationChanged || (openMethodOnCanonicalizedType != _methodDef))
                {
                    canonicalMethodResult = Context.GetInstantiatedMethod(openMethodOnCanonicalizedType, canonInstantiation);
                }
                else
                {
                    canonicalMethodResult = this;
                }

                SetCachedCanonValue(kind, canonicalMethodResult);
            }

            return(canonicalMethodResult);
        }
Exemple #8
0
        private InstantiatedMethod TryGetGenericMethodTemplate_Internal(InstantiatedMethod concreteMethod, CanonicalFormKind kind, out IntPtr nativeLayoutInfoModule, out uint nativeLayoutInfoToken)
        {
            nativeLayoutInfoModule = default(IntPtr);
            nativeLayoutInfoToken = 0;
            var canonForm = concreteMethod.GetCanonMethodTarget(kind);
            var hashCode = canonForm.GetHashCode();
            var loadedModulesCount = RuntimeAugments.GetLoadedModules(null);
            var loadedModuleHandles = new IntPtr[loadedModulesCount];
            var loadedModules = RuntimeAugments.GetLoadedModules(loadedModuleHandles);
            Debug.Assert(loadedModulesCount == loadedModules);

            foreach (var moduleHandle in loadedModuleHandles)
            {
                NativeReader nativeLayoutReader = TypeLoaderEnvironment.Instance.GetNativeLayoutInfoReader(moduleHandle);
                if (nativeLayoutReader == null)
                    continue;

                ExternalReferencesTable externalFixupsTable;
                NativeHashtable genericMethodTemplatesHashtable = LoadHashtable(moduleHandle, ReflectionMapBlob.GenericMethodsTemplateMap, out externalFixupsTable);

                if (genericMethodTemplatesHashtable.IsNull)
                    continue;

                var context = new NativeLayoutInfoLoadContext
                {
                    _typeSystemContext = concreteMethod.Context,
                    _typeArgumentHandles = concreteMethod.OwningType.Instantiation,
                    _methodArgumentHandles = concreteMethod.Instantiation,
                    _moduleHandle = moduleHandle
                };

                var enumerator = genericMethodTemplatesHashtable.Lookup(hashCode);

                NativeParser entryParser;
                while (!(entryParser = enumerator.GetNext()).IsNull)
                {
                    var methodSignatureParser = new NativeParser(nativeLayoutReader, externalFixupsTable.GetRvaFromIndex(entryParser.GetUnsigned()));

                    // Get the unified generic method holder and convert it to its canonical form
                    var candidateTemplate = (InstantiatedMethod)context.GetMethod(ref methodSignatureParser);
                    Debug.Assert(candidateTemplate.Instantiation.Length > 0);

                    if (canonForm == candidateTemplate.GetCanonMethodTarget(kind))
                    {
                        TypeLoaderLogger.WriteLine("Found template for generic method " + concreteMethod.ToString() + ": " + candidateTemplate.ToString());
                        nativeLayoutInfoModule = moduleHandle;
                        nativeLayoutInfoToken = (uint)externalFixupsTable.GetRvaFromIndex(entryParser.GetUnsigned());
                        if (nativeLayoutInfoToken == BadTokenFixupValue)
                        {
                            // TODO: once multifile gets fixed up, make this throw a BadImageFormatException
                            TypeLoaderLogger.WriteLine("ERROR: template not fixed up, skipping");
                            continue;
                        }

                        Debug.Assert(
                            (kind != CanonicalFormKind.Universal && candidateTemplate != candidateTemplate.GetCanonMethodTarget(kind)) ||
                            (kind == CanonicalFormKind.Universal && candidateTemplate == candidateTemplate.GetCanonMethodTarget(kind)));

                        return candidateTemplate;
                    }
                }
            }

            TypeLoaderLogger.WriteLine("ERROR: Cannot find a suitable template for generic method " + concreteMethod.ToString());
            return null;
        }
Exemple #9
0
        //
        // Returns the template method for a generic method instantation
        //
        public InstantiatedMethod TryGetGenericMethodTemplate(InstantiatedMethod concreteMethod, out IntPtr nativeLayoutInfoModule, out uint nativeLayoutInfoToken)
        {
            // First, see if there is a specific canonical template
            InstantiatedMethod result = TryGetGenericMethodTemplate_Internal(concreteMethod, CanonicalFormKind.Specific, out nativeLayoutInfoModule, out nativeLayoutInfoToken);

            // If not found, see if there's a universal canonical template
            if (result == null)
                result = TryGetGenericMethodTemplate_Internal(concreteMethod, CanonicalFormKind.Universal, out nativeLayoutInfoModule, out nativeLayoutInfoToken);

            return result;
        }
        public static void RegisterDebugDataForMethod(TypeBuilder typeBuilder, InstantiatedMethod method)
        {
            NativePrimitiveEncoder encoder = new NativePrimitiveEncoder();
            encoder.Init();

            byte sharedMethodFlags = 0;
            sharedMethodFlags |= (byte)(method.OwningType.IsGeneric() ? SharedMethodFlags.HasDeclaringTypeHandle : 0);

            Instance.SerializeDataBlobTypeAndFlags(ref encoder, SerializedDataBlobKind.SharedMethod, sharedMethodFlags);
            encoder.WriteUnsignedLong((ulong)method.RuntimeMethodDictionary.ToInt64());
            encoder.WriteUnsigned((uint)method.Instantiation.Length);

            foreach (var instParam in method.Instantiation)
            {
                encoder.WriteUnsignedLong((ulong)typeBuilder.GetRuntimeTypeHandle(instParam).ToIntPtr().ToInt64());
            }

            if (method.OwningType.IsGeneric())
            {
                encoder.WriteUnsignedLong((ulong)typeBuilder.GetRuntimeTypeHandle(method.OwningType).ToIntPtr().ToInt64());
            }

            Instance.ThreadSafeWriteBytes(encoder.GetBytes());
        }