Beispiel #1
0
        public override IEnumerable <DependencyListEntry> GetStaticDependencies(NodeFactory context)
        {
            // TODO: https://github.com/dotnet/corert/issues/3224
            // Reflection invoke stub handling is here because in the current reflection model we reflection-enable
            // all methods that are compiled. Ideally the list of reflection enabled methods should be known before
            // we even start the compilation process (with the invocation stubs being compilation roots like any other).
            // The existing model has it's problems: e.g. the invocability of the method depends on inliner decisions.
            if (context.MetadataManager.IsReflectionInvokable(_method) && _method.IsAbstract)
            {
                DependencyList dependencies = new DependencyList();

                if (context.MetadataManager.HasReflectionInvokeStubForInvokableMethod(_method) && !_method.IsCanonicalMethod(CanonicalFormKind.Any))
                {
                    MethodDesc invokeStub      = context.MetadataManager.GetReflectionInvokeStub(_method);
                    MethodDesc canonInvokeStub = invokeStub.GetCanonMethodTarget(CanonicalFormKind.Specific);
                    if (invokeStub != canonInvokeStub)
                    {
                        dependencies.Add(new DependencyListEntry(context.MetadataManager.DynamicInvokeTemplateData, "Reflection invoke template data"));
                        context.MetadataManager.DynamicInvokeTemplateData.AddDependenciesDueToInvokeTemplatePresence(ref dependencies, context, canonInvokeStub);
                    }
                    else
                    {
                        dependencies.Add(new DependencyListEntry(context.MethodEntrypoint(invokeStub), "Reflection invoke"));
                    }
                }

                dependencies.AddRange(ReflectionVirtualInvokeMapNode.GetVirtualInvokeMapDependencies(context, _method));

                return(dependencies);
            }

            return(Array.Empty <DependencyListEntry>());
        }
        public static void AddDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
        {
            if (factory.MetadataManager.IsReflectionInvokable(method))
            {
                if (dependencies == null)
                {
                    dependencies = new DependencyList();
                }

                dependencies.Add(factory.MaximallyConstructableType(method.OwningType), "Reflection invoke");

                if (factory.MetadataManager.HasReflectionInvokeStubForInvokableMethod(method) &&
                    ((factory.Target.Abi != TargetAbi.ProjectN) || ProjectNDependencyBehavior.EnableFullAnalysis || !method.IsCanonicalMethod(CanonicalFormKind.Any)))
                {
                    MethodDesc canonInvokeStub = factory.MetadataManager.GetCanonicalReflectionInvokeStub(method);
                    if (canonInvokeStub.IsSharedByGenericInstantiations)
                    {
                        dependencies.Add(new DependencyListEntry(factory.MetadataManager.DynamicInvokeTemplateData, "Reflection invoke template data"));
                        factory.MetadataManager.DynamicInvokeTemplateData.AddDependenciesDueToInvokeTemplatePresence(ref dependencies, factory, canonInvokeStub);
                    }
                    else
                    {
                        dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(canonInvokeStub), "Reflection invoke"));
                    }
                }

                bool skipUnboxingStubDependency = false;
                if ((factory.Target.Abi == TargetAbi.ProjectN) && !ProjectNDependencyBehavior.EnableFullAnalysis)
                {
                    // ProjectN compilation currently computes the presence of these stubs independent from dependency analysis here
                    // TODO: fix that issue and remove this odd treatment of unboxing stubs
                    if (!method.HasInstantiation && method.OwningType.IsValueType && method.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any) && !method.Signature.IsStatic)
                    {
                        skipUnboxingStubDependency = true;
                    }
                }

                if (method.OwningType.IsValueType && !method.Signature.IsStatic && !skipUnboxingStubDependency)
                {
                    dependencies.Add(new DependencyListEntry(factory.ExactCallableAddress(method, isUnboxingStub: true), "Reflection unboxing stub"));
                }

                // If the method is defined in a different module than this one, a metadata token isn't known for performing the reference
                // Use a name/sig reference instead.
                if (!factory.MetadataManager.WillUseMetadataTokenToReferenceMethod(method))
                {
                    dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())),
                                                             "Non metadata-local method reference"));
                }

                if (method.HasInstantiation && method.IsCanonicalMethod(CanonicalFormKind.Universal))
                {
                    dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method)),
                                                             "UniversalCanon signature of method"));
                }

                ReflectionVirtualInvokeMapNode.GetVirtualInvokeMapDependencies(ref dependencies, factory, method);
            }
        }
        public static void AddDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
        {
            Debug.Assert(factory.MetadataManager.IsReflectionInvokable(method));

            if (dependencies == null)
            {
                dependencies = new DependencyList();
            }

            dependencies.Add(factory.MaximallyConstructableType(method.OwningType), "Reflection invoke");

            if (factory.MetadataManager.HasReflectionInvokeStubForInvokableMethod(method))
            {
                MethodDesc canonInvokeStub = factory.MetadataManager.GetCanonicalReflectionInvokeStub(method);
                if (canonInvokeStub.IsSharedByGenericInstantiations)
                {
                    dependencies.Add(new DependencyListEntry(factory.DynamicInvokeTemplate(canonInvokeStub), "Reflection invoke"));
                }
                else
                {
                    dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(canonInvokeStub), "Reflection invoke"));
                }
            }

            if (method.OwningType.IsValueType && !method.Signature.IsStatic)
            {
                dependencies.Add(new DependencyListEntry(factory.ExactCallableAddress(method, isUnboxingStub: true), "Reflection unboxing stub"));
            }

            // If the method is defined in a different module than this one, a metadata token isn't known for performing the reference
            // Use a name/sig reference instead.
            if (!factory.MetadataManager.WillUseMetadataTokenToReferenceMethod(method))
            {
                dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())),
                                                         "Non metadata-local method reference"));
            }

            if (method.HasInstantiation)
            {
                bool useUnboxingStub = method.OwningType.IsValueType && !method.Signature.IsStatic;

                if (method.IsCanonicalMethod(CanonicalFormKind.Universal))
                {
                    dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method)),
                                                             "UniversalCanon signature of method"));
                }
                else if (!method.GetCanonMethodTarget(CanonicalFormKind.Specific).RequiresInstArg() || method.IsAbstract)
                {
                    foreach (var instArg in method.Instantiation)
                    {
                        dependencies.Add(factory.NecessaryTypeSymbol(instArg), "Reflectable generic method inst arg");
                    }
                }
            }

            ReflectionVirtualInvokeMapNode.GetVirtualInvokeMapDependencies(ref dependencies, factory, method);
        }
Beispiel #4
0
        public override IEnumerable <DependencyListEntry> GetStaticDependencies(NodeFactory factory)
        {
            List <DependencyListEntry> dependencies = new List <DependencyListEntry>();

            // Reflection invoke stub handling is here because in the current reflection model we reflection-enable
            // all methods that are compiled. Ideally the list of reflection enabled methods should be known before
            // we even start the compilation process (with the invocation stubs being compilation roots like any other).
            // The existing model has it's problems: e.g. the invocability of the method depends on inliner decisions.
            if (factory.MetadataManager.IsReflectionInvokable(_decl) && _decl.IsAbstract)
            {
                if (factory.MetadataManager.HasReflectionInvokeStubForInvokableMethod(_decl) && !_decl.IsCanonicalMethod(CanonicalFormKind.Any))
                {
                    MethodDesc invokeStub      = factory.MetadataManager.GetReflectionInvokeStub(_decl);
                    MethodDesc canonInvokeStub = invokeStub.GetCanonMethodTarget(CanonicalFormKind.Specific);
                    if (invokeStub != canonInvokeStub)
                    {
                        dependencies.Add(new DependencyListEntry(factory.FatFunctionPointer(invokeStub), "Reflection invoke"));
                    }
                    else
                    {
                        dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(invokeStub), "Reflection invoke"));
                    }
                }

                dependencies.AddRange(ReflectionVirtualInvokeMapNode.GetVirtualInvokeMapDependencies(factory, _decl));
            }

            MethodDesc canonDecl = _decl.GetCanonMethodTarget(CanonicalFormKind.Specific);

            if (canonDecl != _decl)
            {
                dependencies.Add(new DependencyListEntry(factory.VirtualMethodUse(canonDecl), "Canonical method"));
            }

            dependencies.Add(new DependencyListEntry(factory.VTable(_decl.OwningType), "VTable of a VirtualMethodUse"));

            return(dependencies);
        }
Beispiel #5
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            // This node does not trigger generation of other nodes.
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this }));
            }

            // Ensure the native layout blob has been saved
            factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory);

            var writer           = new NativeWriter();
            var typeMapHashTable = new VertexHashtable();

            Section hashTableSection = writer.NewSection();

            hashTableSection.Place(typeMapHashTable);

            // Get a list of all methods that have a method body and metadata from the metadata manager.
            foreach (var mappingEntry in factory.MetadataManager.GetMethodMapping(factory))
            {
                MethodDesc method = mappingEntry.Entity;

                // The current format requires us to have an EEType for the owning type. We might want to lift this.
                if (!factory.MetadataManager.TypeGeneratesEEType(method.OwningType))
                {
                    continue;
                }

                // We have a method body, we have a metadata token, but we can't get an invoke stub. Bail.
                if (!factory.MetadataManager.IsReflectionInvokable(method))
                {
                    continue;
                }

                InvokeTableFlags flags = 0;

                if (method.HasInstantiation)
                {
                    flags |= InvokeTableFlags.IsGenericMethod;
                }

                if (method.GetCanonMethodTarget(CanonicalFormKind.Specific).RequiresInstArg())
                {
                    flags |= InvokeTableFlags.RequiresInstArg;
                }

                if (method.IsDefaultConstructor)
                {
                    flags |= InvokeTableFlags.IsDefaultConstructor;
                }

                if (ReflectionVirtualInvokeMapNode.NeedsVirtualInvokeInfo(method))
                {
                    flags |= InvokeTableFlags.HasVirtualInvoke;
                }

                if (!method.IsAbstract)
                {
                    flags |= InvokeTableFlags.HasEntrypoint;
                }

                if (mappingEntry.MetadataHandle != 0)
                {
                    flags |= InvokeTableFlags.HasMetadataHandle;
                }

                if (!factory.MetadataManager.HasReflectionInvokeStubForInvokableMethod(method))
                {
                    flags |= InvokeTableFlags.NeedsParameterInterpretation;
                }

                if (method.IsCanonicalMethod(CanonicalFormKind.Universal))
                {
                    flags |= InvokeTableFlags.IsUniversalCanonicalEntry;
                }

                // TODO: native signature for P/Invokes and NativeCallable methods
                if (method.IsRawPInvoke() || method.IsNativeCallable)
                {
                    continue;
                }

                // Grammar of an entry in the hash table:
                // Flags + DeclaringType + MetadataHandle/NameAndSig + Entrypoint + DynamicInvokeMethod + [NumGenericArgs + GenericArgs]

                Vertex vertex = writer.GetUnsignedConstant((uint)flags);

                if ((flags & InvokeTableFlags.HasMetadataHandle) != 0)
                {
                    // Only store the offset portion of the metadata handle to get better integer compression
                    vertex = writer.GetTuple(vertex,
                                             writer.GetUnsignedConstant((uint)(mappingEntry.MetadataHandle & MetadataManager.MetadataOffsetMask)));
                }
                else
                {
                    var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()));
                    vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset));
                }

                // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
                IEETypeNode owningTypeSymbol = factory.NecessaryTypeSymbol(method.OwningType);
                vertex = writer.GetTuple(vertex,
                                         writer.GetUnsignedConstant(_externalReferences.GetIndex(owningTypeSymbol)));

                if ((flags & InvokeTableFlags.HasEntrypoint) != 0)
                {
                    bool useUnboxingStub = method.OwningType.IsValueType && !method.Signature.IsStatic;
                    vertex = writer.GetTuple(vertex,
                                             writer.GetUnsignedConstant(_externalReferences.GetIndex(
                                                                            factory.MethodEntrypoint(method.GetCanonMethodTarget(CanonicalFormKind.Specific), useUnboxingStub))));
                }

                if ((flags & InvokeTableFlags.NeedsParameterInterpretation) == 0)
                {
                    MethodDesc canonInvokeStubMethod = factory.MetadataManager.GetCanonicalReflectionInvokeStub(method);
                    if (canonInvokeStubMethod.IsSharedByGenericInstantiations)
                    {
                        vertex = writer.GetTuple(vertex,
                                                 writer.GetUnsignedConstant(((uint)factory.MetadataManager.DynamicInvokeTemplateData.GetIdForMethod(canonInvokeStubMethod) << 1) | 1));
                    }
                    else
                    {
                        vertex = writer.GetTuple(vertex,
                                                 writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(canonInvokeStubMethod)) << 1));
                    }
                }

                if ((flags & InvokeTableFlags.IsGenericMethod) != 0)
                {
                    if ((flags & InvokeTableFlags.IsUniversalCanonicalEntry) != 0)
                    {
                        var nameAndSigGenericMethod = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method));
                        vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)nameAndSigGenericMethod.SavedVertex.VertexOffset));
                    }
                    else if ((flags & InvokeTableFlags.RequiresInstArg) == 0 || (flags & InvokeTableFlags.HasEntrypoint) == 0)
                    {
                        VertexSequence args = new VertexSequence();
                        for (int i = 0; i < method.Instantiation.Length; i++)
                        {
                            uint argId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(method.Instantiation[i]));
                            args.Append(writer.GetUnsignedConstant(argId));
                        }
                        vertex = writer.GetTuple(vertex, args);
                    }
                    else
                    {
                        uint dictionaryId = _externalReferences.GetIndex(factory.MethodGenericDictionary(method));
                        vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(dictionaryId));
                    }
                }

                int hashCode = method.GetCanonMethodTarget(CanonicalFormKind.Specific).OwningType.GetHashCode();
                typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex));
            }

            byte[] hashTableBytes = writer.Save();

            _endSymbol.SetSymbolOffset(hashTableBytes.Length);

            return(new ObjectData(hashTableBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }));
        }
        public static void AddDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
        {
            // TODO: https://github.com/dotnet/corert/issues/3224
            // Reflection invoke stub handling is here because in the current reflection model we reflection-enable
            // all methods that are compiled. Ideally the list of reflection enabled methods should be known before
            // we even start the compilation process (with the invocation stubs being compilation roots like any other).
            // The existing model has it's problems: e.g. the invocability of the method depends on inliner decisions.
            if (factory.MetadataManager.IsReflectionInvokable(method))
            {
                if (dependencies == null)
                {
                    dependencies = new DependencyList();
                }

                if (factory.MetadataManager.HasReflectionInvokeStubForInvokableMethod(method) &&
                    ((factory.Target.Abi != TargetAbi.ProjectN) || !method.IsCanonicalMethod(CanonicalFormKind.Any)))
                {
                    MethodDesc canonInvokeStub = factory.MetadataManager.GetCanonicalReflectionInvokeStub(method);
                    if (canonInvokeStub.IsSharedByGenericInstantiations)
                    {
                        dependencies.Add(new DependencyListEntry(factory.MetadataManager.DynamicInvokeTemplateData, "Reflection invoke template data"));
                        factory.MetadataManager.DynamicInvokeTemplateData.AddDependenciesDueToInvokeTemplatePresence(ref dependencies, factory, canonInvokeStub);
                    }
                    else
                    {
                        dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(canonInvokeStub), "Reflection invoke"));
                    }
                }

                bool skipUnboxingStubDependency = false;
                if (factory.Target.Abi == TargetAbi.ProjectN)
                {
                    // ProjectN compilation currently computes the presence of these stubs independent from dependency analysis here
                    // TODO: fix that issue and remove this odd treatment of unboxing stubs
                    if (!method.HasInstantiation && method.OwningType.IsValueType && method.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any) && !method.Signature.IsStatic)
                    {
                        skipUnboxingStubDependency = true;
                    }
                }

                if (method.OwningType.IsValueType && !method.Signature.IsStatic && !skipUnboxingStubDependency)
                {
                    dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(method, unboxingStub: true), "Reflection unboxing stub"));
                }

                // If the method is defined in a different module than this one, a metadata token isn't known for performing the reference
                // Use a name/sig reference instead.
                if (!factory.MetadataManager.WillUseMetadataTokenToReferenceMethod(method))
                {
                    dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())),
                                                             "Non metadata-local method reference"));
                }

                if (method.HasInstantiation && method.IsCanonicalMethod(CanonicalFormKind.Universal))
                {
                    dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method)),
                                                             "UniversalCanon signature of method"));
                }

                ReflectionVirtualInvokeMapNode.GetVirtualInvokeMapDependencies(ref dependencies, factory, method);
            }
        }
Beispiel #7
0
        public static void AddDependenciesDueToMethodCodePresence(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
        {
            // Reflection invoke stub handling is here because in the current reflection model we reflection-enable
            // all methods that are compiled. Ideally the list of reflection enabled methods should be known before
            // we even start the compilation process (with the invocation stubs being compilation roots like any other).
            // The existing model has it's problems: e.g. the invocability of the method depends on inliner decisions.
            if (factory.MetadataManager.IsReflectionInvokable(method))
            {
                if (dependencies == null)
                {
                    dependencies = new DependencyList();
                }

                if (factory.MetadataManager.HasReflectionInvokeStubForInvokableMethod(method) && !method.IsCanonicalMethod(CanonicalFormKind.Any) /* Shared generics handled in the shadow concrete method node */)
                {
                    MethodDesc invokeStub      = factory.MetadataManager.GetReflectionInvokeStub(method);
                    MethodDesc canonInvokeStub = invokeStub.GetCanonMethodTarget(CanonicalFormKind.Specific);
                    if (invokeStub != canonInvokeStub)
                    {
                        dependencies.Add(new DependencyListEntry(factory.FatFunctionPointer(invokeStub), "Reflection invoke"));
                    }
                    else
                    {
                        dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(invokeStub), "Reflection invoke"));
                    }
                }

                bool skipUnboxingStubDependency = false;
                if (factory.Target.Abi == TargetAbi.ProjectN)
                {
                    // ProjectN compilation currently computes the presence of these stubs independent from dependency analysis here
                    // TODO: fix that issue and remove this odd treatment of unboxing stubs
                    if (!method.HasInstantiation && method.OwningType.IsValueType && method.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any) && !method.Signature.IsStatic)
                    {
                        skipUnboxingStubDependency = true;
                    }
                }

                if (method.OwningType.IsValueType && !method.Signature.IsStatic && !skipUnboxingStubDependency)
                {
                    dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(method, unboxingStub: true), "Reflection unboxing stub"));
                }

                dependencies.AddRange(ReflectionVirtualInvokeMapNode.GetVirtualInvokeMapDependencies(factory, method));
            }

            if (method.HasInstantiation)
            {
                var exactMethodInstantiationDependencies = ExactMethodInstantiationsNode.GetExactMethodInstantiationDependenciesForMethod(factory, method);
                if (exactMethodInstantiationDependencies != null)
                {
                    dependencies = dependencies ?? new DependencyList();
                    dependencies.AddRange(exactMethodInstantiationDependencies);
                }

                if (method.IsVirtual)
                {
                    // Generic virtual methods dependency tracking
                    dependencies = dependencies ?? new DependencyList();
                    dependencies.Add(new DependencyListEntry(factory.GVMDependencies(method), "GVM Dependencies Support"));
                }

                var templateMethodDependencies = GenericMethodsTemplateMap.GetTemplateMethodDependencies(factory, method);
                if (templateMethodDependencies != null)
                {
                    dependencies = dependencies ?? new DependencyList();
                    dependencies.AddRange(templateMethodDependencies);
                }
            }
            else
            {
                TypeDesc owningTemplateType = method.OwningType;

                // Unboxing and Instantiating stubs use a different type as their template
                if (factory.TypeSystemContext.IsSpecialUnboxingThunk(method))
                {
                    owningTemplateType = factory.TypeSystemContext.GetTargetOfSpecialUnboxingThunk(method).OwningType;
                }

                var templateTypeDepedencies = GenericTypesTemplateMap.GetTemplateTypeDependencies(factory, owningTemplateType);
                if (templateTypeDepedencies != null)
                {
                    dependencies = dependencies ?? new DependencyList();
                    dependencies.AddRange(templateTypeDepedencies);
                }
            }
        }