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);

            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());
        }
Example #2
0
 internal HandleBasedGenericMethodLookup(InstantiatedMethod methodToLookup) : base(methodToLookup)
 {
     Debug.Assert(methodToLookup != null);
     _declaringType    = _methodToLookup.OwningType.RuntimeTypeHandle;
     _nameAndSignature = _methodToLookup.NameAndSignature;
     // _genericMethodArgumentHandles not initialized here to avoid allocation of a new array (and it's not used if we initialize _typeToLookup).
 }
Example #3
0
            internal override bool MatchParsedEntry(ref NativeParser entryParser, ref ExternalReferencesTable externalReferencesLookup, IntPtr moduleHandle)
            {
                //
                // Entries read from the hashtable are loaded as GenericMethodDescs, and compared to the input.
                // This lookup is slower than the lookups using RuntimeTypeHandles, but can handle cases where we don't have
                // RuntimeTypeHandle values for all of the components of the input GenericMethodDesc, but still need to look it up in case the
                // method dictionary statically really exists
                //
                TypeSystemContext context = _methodToLookup.Context;

                RuntimeTypeHandle parsedDeclaringTypeHandle = externalReferencesLookup.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

                // Hash table names / sigs are indirected through to the native layout info
                MethodNameAndSignature nameAndSignature;

                if (!TypeLoaderEnvironment.Instance.TryGetMethodNameAndSignatureFromNativeLayoutOffset(moduleHandle, entryParser.GetUnsigned(), out nameAndSignature))
                {
                    return(false);
                }

                RuntimeTypeHandle[] parsedArgsHandles = GetTypeSequence(ref externalReferencesLookup, ref entryParser);

                DefType            parsedDeclaringType = context.ResolveRuntimeTypeHandle(parsedDeclaringTypeHandle) as DefType;
                Instantiation      parsedArgs          = context.ResolveRuntimeTypeHandles(parsedArgsHandles);
                InstantiatedMethod parsedGenericMethod = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, parsedDeclaringType, nameAndSignature, parsedArgs, IntPtr.Zero, false);

                return(parsedGenericMethod == _methodToLookup);
            }
Example #4
0
        //
        // Returns the template method for a generic method instantiation
        //
        public static InstantiatedMethod TryGetGenericMethodTemplate(InstantiatedMethod concreteMethod, out NativeFormatModuleInfo 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
            result ??= TryGetGenericMethodTemplate_Internal(concreteMethod, CanonicalFormKind.Universal, out nativeLayoutInfoModule, out nativeLayoutInfoToken);

            return(result);
        }
Example #5
0
            internal override bool MatchGenericMethodEntry(GenericMethodEntry entry)
            {
                TypeSystemContext context = _methodToLookup.Context;

                DefType            parsedDeclaringType = context.ResolveRuntimeTypeHandle(entry._declaringTypeHandle) as DefType;
                Instantiation      parsedArgs          = context.ResolveRuntimeTypeHandles(entry._genericMethodArgumentHandles);
                InstantiatedMethod parsedGenericMethod = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, parsedDeclaringType, entry._methodNameAndSignature, parsedArgs, IntPtr.Zero, false);

                return(parsedGenericMethod == _methodToLookup);
            }
Example #6
0
        private static InstantiatedMethod TryGetGenericMethodTemplate_Internal(InstantiatedMethod concreteMethod, CanonicalFormKind kind, out NativeFormatModuleInfo nativeLayoutInfoModule, out uint nativeLayoutInfoToken)
        {
            nativeLayoutInfoModule = null;
            nativeLayoutInfoToken  = 0;
            var canonForm = concreteMethod.GetCanonMethodTarget(kind);
            var hashCode  = canonForm.GetHashCode();

            foreach (NativeFormatModuleInfo moduleInfo in ModuleList.EnumerateModules())
            {
                NativeReader nativeLayoutReader = TypeLoaderEnvironment.GetNativeLayoutInfoReader(moduleInfo.Handle);
                if (nativeLayoutReader == null)
                {
                    continue;
                }

                NativeHashtable genericMethodTemplatesHashtable = LoadHashtable(moduleInfo, ReflectionMapBlob.GenericMethodsTemplateMap, out _);

                if (genericMethodTemplatesHashtable.IsNull)
                {
                    continue;
                }

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

                var enumerator = genericMethodTemplatesHashtable.Lookup(hashCode);

                NativeParser entryParser;
                while (!(entryParser = enumerator.GetNext()).IsNull)
                {
                    var methodSignatureParser = new NativeParser(nativeLayoutReader, 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 = moduleInfo;
                        nativeLayoutInfoToken  = 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) ||
                            (kind == CanonicalFormKind.Universal && candidateTemplate == candidateTemplate.GetCanonMethodTarget(kind)));

                        return(candidateTemplate);
                    }
                }
            }

            TypeLoaderLogger.WriteLine("ERROR: Cannot find a suitable template for generic method " + concreteMethod.ToString());
            return(null);
        }
Example #7
0
        // This method computes the method pointer and dictionary pointer for a GVM.
        // Inputs:
        //      - targetTypeHanlde: target type on which the GVM is implemented
        //      - nameAndSignature: name and signature of the GVM method
        //      - genericMethodArgumentHandles: GVM instantiation arguments
        // Outputs:
        //      - methodPointer: pointer to the GVM's implementation
        //      - dictionaryPointer: (if applicable) pointer to the dictionary to be used with the GVM call
        public bool TryGetGenericVirtualMethodPointer(RuntimeTypeHandle targetTypeHandle, MethodNameAndSignature nameAndSignature, RuntimeTypeHandle[] genericMethodArgumentHandles, out IntPtr methodPointer, out IntPtr dictionaryPointer)
        {
            methodPointer = dictionaryPointer = IntPtr.Zero;

            TypeSystemContext context = TypeSystemContextFactory.Create();

            DefType            targetType          = (DefType)context.ResolveRuntimeTypeHandle(targetTypeHandle);
            Instantiation      methodInstantiation = context.ResolveRuntimeTypeHandles(genericMethodArgumentHandles);
            InstantiatedMethod method = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, targetType, nameAndSignature, methodInstantiation, IntPtr.Zero, false);

            if (!method.CanShareNormalGenericCode())
            {
                // First see if we can find an exact method implementation for the GVM (avoid using USG implementations if we can,
                // because USG code is much slower).
                if (TryLookupExactMethodPointerForComponents(targetTypeHandle, nameAndSignature, genericMethodArgumentHandles, out methodPointer))
                {
                    Debug.Assert(methodPointer != IntPtr.Zero);
                    TypeSystemContextFactory.Recycle(context);
                    return(true);
                }
            }

            // If we cannot find an exact method entry point, look for an equivalent template and compute the generic dictinoary
            TemplateLocator    templateLocator  = new TemplateLocator();
            NativeLayoutInfo   nativeLayoutInfo = new NativeLayoutInfo();
            InstantiatedMethod templateMethod   = templateLocator.TryGetGenericMethodTemplate(method, out nativeLayoutInfo.Module, out nativeLayoutInfo.Token);

            if (templateMethod == null)
            {
                return(false);
            }

            methodPointer = templateMethod.IsCanonicalMethod(CanonicalFormKind.Universal) ?
                            templateMethod.UsgFunctionPointer :
                            templateMethod.FunctionPointer;

            if (!TryLookupGenericMethodDictionaryForComponents(targetTypeHandle, nameAndSignature, genericMethodArgumentHandles, out dictionaryPointer))
            {
                using (LockHolder.Hold(_typeLoaderLock))
                {
                    // Now that we hold the lock, we may find that existing types can now find
                    // their associated RuntimeTypeHandle. Flush the type builder states as a way
                    // to force the reresolution of RuntimeTypeHandles which couldn't be found before.
                    context.FlushTypeBuilderStates();

                    if (!TypeBuilder.TryBuildGenericMethod(method, out dictionaryPointer))
                    {
                        return(false);
                    }
                }
            }

            Debug.Assert(methodPointer != IntPtr.Zero && dictionaryPointer != IntPtr.Zero);

            if (templateMethod.IsCanonicalMethod(CanonicalFormKind.Universal))
            {
                // Check if we need to wrap the method pointer into a calling convention converter thunk
                if (!TypeLoaderEnvironment.Instance.MethodSignatureHasVarsNeedingCallingConventionConverter(context, nameAndSignature.Signature))
                {
                    TypeSystemContextFactory.Recycle(context);
                    return(true);
                }

                RuntimeTypeHandle[] typeArgs = Array.Empty <RuntimeTypeHandle>();

                if (RuntimeAugments.IsGenericType(targetTypeHandle))
                {
                    RuntimeAugments.GetGenericInstantiation(targetTypeHandle, out typeArgs);
                }

                // Create a CallingConventionConverter to call the method correctly
                IntPtr thunkPtr = CallConverterThunk.MakeThunk(
                    CallConverterThunk.ThunkKind.StandardToGenericInstantiating,
                    methodPointer,
                    nameAndSignature.Signature,
                    dictionaryPointer,
                    typeArgs,
                    genericMethodArgumentHandles);

                Debug.Assert(thunkPtr != IntPtr.Zero);

                methodPointer = thunkPtr;
                // Set dictionaryPointer to null so we don't make a fat function pointer around the whole thing.
                dictionaryPointer = IntPtr.Zero;

                // TODO! add a new call converter thunk that will pass the instantiating arg through and use a fat function pointer.
                // should allow us to make fewer thunks.
            }

            TypeSystemContextFactory.Recycle(context);
            return(true);
        }
Example #8
0
 internal MethodDescBasedGenericMethodLookup(InstantiatedMethod methodToLookup)
 {
     _methodToLookup = methodToLookup;
 }
Example #9
0
        public string Visit(IMethod method, OutputSettings settings)
        {
            StringBuilder result = new StringBuilder();

            result.Append(settings.EmitModifiers(base.GetString(method.Modifiers)));

            if (settings.IncludeReturnType && !settings.ReturnTypesLast && !method.IsConstructor && !method.IsFinalizer)
            {
                result.Append(GetString(method.ReturnType, settings));
                result.Append(settings.Markup(" "));
            }

            if (!settings.IncludeReturnType && settings.UseFullName)
            {
                result.Append(GetString(method.DeclaringType, OutputFlags.UseFullName));
                result.Append(settings.Markup("."));
            }
            AppendExplicitInterfaces(result, method, settings);
            if (method.IsConstructor)
            {
                result.Append(settings.EmitName(method, Format(FilterName(method.DeclaringType.Name))));
            }
            else if (method.IsFinalizer)
            {
                result.Append(settings.EmitName(method, settings.Markup("~") + Format(FilterName(method.DeclaringType.Name))));
            }
            else
            {
                result.Append(settings.EmitName(method, Format(FilterName(method.Name))));
            }
            //this is only ever used if GeneralizeGenerics is true
            DomMethod.GenericMethodInstanceResolver resolver = null;
            if (settings.GeneralizeGenerics)
            {
                resolver = new DomMethod.GenericMethodInstanceResolver();
            }

            if (settings.IncludeGenerics)
            {
                if (method.TypeParameters.Count > 0)
                {
                    result.Append(settings.Markup("<"));

                    InstantiatedMethod instantiatedMethod = method as InstantiatedMethod;

                    for (int i = 0; i < method.TypeParameters.Count; i++)
                    {
                        if (i > 0)
                        {
                            result.Append(settings.Markup(settings.HideGenericParameterNames ? "," : ", "));
                        }
                        if (!settings.HideGenericParameterNames)
                        {
                            if (instantiatedMethod != null)
                            {
                                result.Append(this.GetString(instantiatedMethod.GenericParameters[i], settings));
                            }
                            else
                            {
                                if (settings.GeneralizeGenerics)
                                {
                                    string generalizedName = "$M" + i;
                                    result.Append(generalizedName);
                                    var t = new DomReturnType();
                                    t.Name = generalizedName;
                                    resolver.Add(method.DeclaringType.SourceProjectDom, new DomReturnType(method.TypeParameters[i].Name), t);
                                }
                                else
                                {
                                    result.Append(NetToCSharpTypeName(method.TypeParameters[i].Name));
                                }
                            }
                        }
                    }
                    result.Append(settings.Markup(">"));
                }
            }

            if (settings.IncludeParameters)
            {
                CSharpFormattingPolicy policy = GetPolicy(settings);
                if (policy.BeforeMethodCallParentheses)
                {
                    result.Append(settings.Markup(" "));
                }

                result.Append(settings.Markup("("));
                bool first = !settings.StaticUsage;
                if (method.Parameters != null)
                {
                    foreach (IParameter parameter in method.Parameters)
                    {
                        if (settings.HideExtensionsParameter && method.IsExtension && first)
                        {
                            continue;
                        }
                        if (method.IsExtension && first)
                        {
                            result.Append(settings.Markup("this "));
                        }
                        if (!first)
                        {
                            result.Append(settings.Markup(", "));
                        }
                        if (settings.GeneralizeGenerics)
                        {
                            AppendParameter(settings, result, (IParameter)resolver.Visit(parameter, method));
                        }
                        else
                        {
                            AppendParameter(settings, result, parameter);
                        }
                        first = false;
                    }
                }
                result.Append(settings.Markup(")"));
            }
            OutputConstraints(result, settings, method.TypeParameters);

            if (settings.IncludeReturnType && settings.ReturnTypesLast && !method.IsConstructor && !method.IsFinalizer)
            {
                result.Append(settings.Markup(" : "));
                result.Append(GetString(method.ReturnType, settings));
            }

            return(result.ToString());
        }
Example #10
0
 public JitGenericMethodDictionaryNode(InstantiatedMethod method)
 {
     Method = method;
 }
        public string Visit(IMethod method, OutputSettings settings)
        {
            StringBuilder result = new StringBuilder();

            result.Append(settings.EmitModifiers(base.GetString(method.Modifiers)));

            if (settings.IncludeReturnType && !method.IsConstructor && !method.IsFinalizer)
            {
                result.Append(GetString(method.ReturnType, settings));
                result.Append(settings.Markup(" "));
            }
            if (!settings.IncludeReturnType && settings.UseFullName)
            {
                result.Append(GetString(method.DeclaringType, OutputFlags.UseFullName));
                result.Append(settings.Markup("."));
            }
            AppendExplicitInterfaces(result, method, settings);
            if (method.IsConstructor)
            {
                result.Append(settings.EmitName(method, Format(method.DeclaringType.Name)));
            }
            else if (method.IsFinalizer)
            {
                result.Append(settings.EmitName(method, settings.Markup("~") + Format(method.DeclaringType.Name)));
            }
            else
            {
                result.Append(settings.EmitName(method, Format(method.Name)));
            }

            if (settings.IncludeGenerics)
            {
                if (method.TypeParameters.Count > 0)
                {
                    result.Append(settings.Markup("<"));

                    InstantiatedMethod instantiatedMethod = method as InstantiatedMethod;

                    for (int i = 0; i < method.TypeParameters.Count; i++)
                    {
                        if (i > 0)
                        {
                            result.Append(settings.Markup(settings.HideGenericParameterNames ? "," : ", "));
                        }
                        if (!settings.HideGenericParameterNames)
                        {
                            if (instantiatedMethod != null)
                            {
                                result.Append(this.GetString(instantiatedMethod.GenericParameters[i], settings));
                            }
                            else
                            {
                                result.Append(NetToCSharpTypeName(method.TypeParameters[i].Name));
                            }
                        }
                    }
                    result.Append(settings.Markup(">"));
                }
            }

            if (settings.IncludeParameters)
            {
                CSharpFormattingPolicy policy = GetPolicy(settings);
                if (policy.BeforeMethodCallParentheses)
                {
                    result.Append(settings.Markup(" "));
                }

                result.Append(settings.Markup("("));
                bool first = true;
                if (method.Parameters != null)
                {
                    foreach (IParameter parameter in method.Parameters)
                    {
                        if (settings.HideExtensionsParameter && method.IsExtension && parameter == method.Parameters[0])
                        {
                            continue;
                        }
                        if (!first)
                        {
                            result.Append(settings.Markup(", "));
                        }
                        AppendParameter(settings, result, parameter);
                        first = false;
                    }
                }
                result.Append(settings.Markup(")"));
            }

            return(result.ToString());
        }
 public static bool CanShareNormalGenericCode(this InstantiatedMethod method)
 {
     return(method != method.GetCanonMethodTarget(CanonicalFormKind.Specific));
 }