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