protected override void ComputeMetadata(NodeFactory factory,
                                                out byte[] metadataBlob,
                                                out List <MetadataMapping <MetadataType> > typeMappings,
                                                out List <MetadataMapping <MethodDesc> > methodMappings,
                                                out List <MetadataMapping <FieldDesc> > fieldMappings,
                                                out List <MetadataMapping <MethodDesc> > stackTraceMapping)
        {
            MetadataLoadedInfo loadedMetadata = _loadedMetadata.Value;

            metadataBlob = _metadataBlob;

            typeMappings   = new List <MetadataMapping <MetadataType> >();
            methodMappings = new List <MetadataMapping <MethodDesc> >();
            fieldMappings  = new List <MetadataMapping <FieldDesc> >();

            Dictionary <MethodDesc, MethodDesc> canonicalToSpecificMethods = new Dictionary <MethodDesc, MethodDesc>();

            HashSet <FieldDesc>  canonicalFieldsAddedToMap  = new HashSet <FieldDesc>();
            HashSet <MethodDesc> canonicalMethodsAddedToMap = new HashSet <MethodDesc>();

            // The handling of generic methods which are implemented by canonical code is interesting, the invoke map
            // needs to have a specific instantiation for each canonical bit of code.
            foreach (GenericDictionaryNode dictionaryNode in GetCompiledGenericDictionaries())
            {
                MethodGenericDictionaryNode methodDictionary = dictionaryNode as MethodGenericDictionaryNode;
                if (methodDictionary == null)
                {
                    continue;
                }

                MethodDesc method = methodDictionary.OwningMethod;
                Debug.Assert(method.HasInstantiation && !method.IsCanonicalMethod(CanonicalFormKind.Any));

                MethodDesc canonicalMethod = method.GetCanonMethodTarget(CanonicalFormKind.Specific);

                if (canonicalToSpecificMethods.ContainsKey(canonicalMethod))
                {
                    // We only need to record 1 specific to canonical method mapping
                    continue;
                }

                canonicalToSpecificMethods.Add(canonicalMethod, method);
            }

            // Generate type definition mappings
            foreach (var type in GetTypesWithEETypes())
            {
                MetadataType definition = type.IsTypeDefinition ? type as MetadataType : null;
                if (definition == null)
                {
                    continue;
                }

                int token;
                if (loadedMetadata.AllTypeMappings.TryGetValue(definition, out token))
                {
                    typeMappings.Add(new MetadataMapping <MetadataType>(definition, token));
                }
            }

            // Mappings for all compiled methods
            foreach (var method in GetCompiledMethods())
            {
                AddMethodMapping(factory, method, canonicalMethodsAddedToMap, canonicalToSpecificMethods, methodMappings);
            }

            // Mappings for reflectable abstract non-generic methods (methods with compiled bodies are handled above)
            foreach (var method in loadedMetadata.MethodMappings.Keys)
            {
                if (!method.IsAbstract)
                {
                    continue;
                }

                if (method.HasInstantiation || method.OwningType.HasInstantiation)
                {
                    continue;
                }

                AddMethodMapping(factory, method, canonicalMethodsAddedToMap, canonicalToSpecificMethods, methodMappings);
            }

            foreach (var eetypeGenerated in GetTypesWithEETypes())
            {
                if (eetypeGenerated.IsGenericDefinition)
                {
                    continue;
                }

                foreach (FieldDesc field in eetypeGenerated.GetFields())
                {
                    AddFieldMapping(field, canonicalFieldsAddedToMap, fieldMappings);
                }
            }

            stackTraceMapping = GenerateStackTraceMetadata(factory);
        }
        protected override void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List <MetadataMapping <MetadataType> > typeMappings, out List <MetadataMapping <MethodDesc> > methodMappings, out List <MetadataMapping <FieldDesc> > fieldMappings)
        {
            MetadataLoadedInfo loadedMetadata = _loadedMetadata.Value;

            metadataBlob = _metadataBlob;

            typeMappings   = new List <MetadataMapping <MetadataType> >();
            methodMappings = new List <MetadataMapping <MethodDesc> >();
            fieldMappings  = new List <MetadataMapping <FieldDesc> >();

            Dictionary <MethodDesc, MethodDesc> canonicalToSpecificMethods = new Dictionary <MethodDesc, MethodDesc>();

            // The handling of generic methods which are implemented by canonical code is interesting, the invoke map
            // needs to have a specific instantiation for each canonical bit of code.
            foreach (GenericDictionaryNode dictionaryNode in GetCompiledGenericDictionaries())
            {
                MethodGenericDictionaryNode methodDictionary = dictionaryNode as MethodGenericDictionaryNode;
                if (methodDictionary == null)
                {
                    continue;
                }

                MethodDesc method = methodDictionary.OwningMethod;
                Debug.Assert(method.HasInstantiation && !method.IsCanonicalMethod(CanonicalFormKind.Any));

                MethodDesc canonicalMethod = method.GetCanonMethodTarget(CanonicalFormKind.Specific);

                if (canonicalToSpecificMethods.ContainsKey(canonicalMethod))
                {
                    // We only need to record 1 specific to canonical method mapping
                    continue;
                }

                canonicalToSpecificMethods.Add(canonicalMethod, method);
            }

            // Generate type definition mappings
            foreach (var definition in _typeDefinitionsGenerated)
            {
                int token;
                if (loadedMetadata.AllTypeMappings.TryGetValue(definition, out token))
                {
                    typeMappings.Add(new MetadataMapping <MetadataType>(definition, token));
                }
            }

            foreach (var method in GetCompiledMethods())
            {
                int token;
                if (loadedMetadata.MethodMappings.TryGetValue(method.GetTypicalMethodDefinition(), out token))
                {
                    MethodDesc invokeMapMethod = method;
                    if (method.HasInstantiation && method.IsCanonicalMethod(CanonicalFormKind.Specific))
                    {
                        Debug.Assert(canonicalToSpecificMethods.ContainsKey(method));

                        invokeMapMethod = canonicalToSpecificMethods[method];
                    }

                    // Non-generic instance canonical methods on generic structures are only available in the invoke map
                    // if the unboxing stub entrypoint is marked already (which will mean that the unboxing stub
                    // has been compiled, On ProjectN abi, this may will not be triggered by the CodeBasedDependencyAlgorithm.
                    // See the ProjectN abi specific code in there.
                    if (!method.HasInstantiation && method.OwningType.IsValueType && method.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any) && !method.Signature.IsStatic)
                    {
                        if (!factory.MethodEntrypoint(method, true).Marked)
                        {
                            continue;
                        }
                    }

                    methodMappings.Add(new MetadataMapping <MethodDesc>(invokeMapMethod, token));
                }
            }

            foreach (var eetypeGenerated in GetTypesWithEETypes())
            {
                if (eetypeGenerated.IsGenericDefinition)
                {
                    continue;
                }

                foreach (FieldDesc field in eetypeGenerated.GetFields())
                {
                    int token;
                    if (loadedMetadata.FieldMappings.TryGetValue(field.GetTypicalFieldDefinition(), out token))
                    {
                        fieldMappings.Add(new MetadataMapping <FieldDesc>(field, token));
                    }
                }
            }
        }
Ejemplo n.º 3
0
        protected override void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List <MetadataMapping <MetadataType> > typeMappings, out List <MetadataMapping <MethodDesc> > methodMappings, out List <MetadataMapping <FieldDesc> > fieldMappings)
        {
            MetadataLoadedInfo loadedMetadata = _loadedMetadata.Value;

            metadataBlob = _metadataBlob;

            typeMappings   = new List <MetadataMapping <MetadataType> >();
            methodMappings = new List <MetadataMapping <MethodDesc> >();
            fieldMappings  = new List <MetadataMapping <FieldDesc> >();

            Dictionary <MethodDesc, MethodDesc> canonicalToSpecificMethods = new Dictionary <MethodDesc, MethodDesc>();

            // The handling of generic methods which are implemented by canonical code is interesting, the invoke map
            // needs to have a specific instantiation for each canonical bit of code.
            foreach (GenericDictionaryNode dictionaryNode in GetCompiledGenericDictionaries())
            {
                MethodGenericDictionaryNode methodDictionary = dictionaryNode as MethodGenericDictionaryNode;
                if (methodDictionary == null)
                {
                    continue;
                }

                MethodDesc method = methodDictionary.OwningMethod;
                Debug.Assert(method.HasInstantiation && !method.IsCanonicalMethod(CanonicalFormKind.Any));

                MethodDesc canonicalMethod = method.GetCanonMethodTarget(CanonicalFormKind.Specific);

                if (canonicalToSpecificMethods.ContainsKey(canonicalMethod))
                {
                    // We only need to record 1 specific to canonical method mapping
                    continue;
                }

                canonicalToSpecificMethods.Add(canonicalMethod, method);
            }

            // Generate type definition mappings
            foreach (var type in factory.MetadataManager.GetTypesWithEETypes())
            {
                MetadataType definition = type.IsTypeDefinition ? type as MetadataType : null;
                if (definition == null)
                {
                    continue;
                }

                int token;
                if (loadedMetadata.AllTypeMappings.TryGetValue(definition, out token))
                {
                    typeMappings.Add(new MetadataMapping <MetadataType>(definition, token));
                }
            }

            foreach (var method in GetCompiledMethods())
            {
                if (!MethodCanBeInvokedViaReflection(factory, method))
                {
                    continue;
                }

                // If there is a possible canonical method, use that instead of a specific method (folds canonically equivalent methods away)
                if (method.GetCanonMethodTarget(CanonicalFormKind.Specific) != method)
                {
                    continue;
                }

                int token;
                if (loadedMetadata.MethodMappings.TryGetValue(method.GetTypicalMethodDefinition(), out token))
                {
                    MethodDesc invokeMapMethod = GetInvokeMapMethodForMethod(canonicalToSpecificMethods, method);

                    if (invokeMapMethod != null)
                    {
                        methodMappings.Add(new MetadataMapping <MethodDesc>(invokeMapMethod, token));
                    }
                }
                else if (!WillUseMetadataTokenToReferenceMethod(method) &&
                         _compilationModuleGroup.ContainsMethod(method.GetCanonMethodTarget(CanonicalFormKind.Specific)))
                {
                    MethodDesc invokeMapMethod = GetInvokeMapMethodForMethod(canonicalToSpecificMethods, method);

                    // For methods on types that are not in the current module, assume they must be reflectable
                    // and generate a non-metadata backed invoke table entry
                    // TODO, the above computation is overly generous with the set of methods that are placed into the method invoke map
                    // It includes methods which are not reflectable at all.
                    if (invokeMapMethod != null)
                    {
                        methodMappings.Add(new MetadataMapping <MethodDesc>(invokeMapMethod, 0));
                    }
                }
            }

            foreach (var eetypeGenerated in GetTypesWithEETypes())
            {
                if (eetypeGenerated.IsGenericDefinition)
                {
                    continue;
                }

                if (eetypeGenerated.HasInstantiation)
                {
                    // Collapsing of field map entries based on canonicalization, to avoid redundant equivalent entries

                    TypeDesc canonicalType = eetypeGenerated.ConvertToCanonForm(CanonicalFormKind.Specific);
                    if (canonicalType != eetypeGenerated && TypeGeneratesEEType(canonicalType))
                    {
                        continue;
                    }
                }

                foreach (FieldDesc field in eetypeGenerated.GetFields())
                {
                    int token;
                    if (loadedMetadata.FieldMappings.TryGetValue(field.GetTypicalFieldDefinition(), out token))
                    {
                        fieldMappings.Add(new MetadataMapping <FieldDesc>(field, token));
                    }
                    else if (!WillUseMetadataTokenToReferenceField(field))
                    {
                        // TODO, the above computation is overly generous with the set of fields that are placed into the field invoke map
                        // It includes fields which are not reflectable at all, and collapses static fields across generics

                        // TODO! enable this. Disabled due to cross module import of statics is not yet implemented
                        // fieldMappings.Add(new MetadataMapping<FieldDesc>(field, 0));
                    }
                }
            }
        }