diff options
author | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2018-07-31 19:04:02 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-31 19:04:02 +0300 |
commit | ebb3632553a4c8f1303c92fc03ce19b4879bb708 (patch) | |
tree | d1cc89bc265f5b18d9b012027332d1c319e1ce1a /src/ILCompiler.Compiler | |
parent | 7310d4bcf386371660c4bd99d9807fa296ec960d (diff) | |
parent | b7ea3897c635e746573a6ff50bf2f2a54be16126 (diff) |
Merge pull request #6158 from dotnet/master
Merge master to nmirror
Diffstat (limited to 'src/ILCompiler.Compiler')
7 files changed, 72 insertions, 14 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs index 6a307aac4..defedd0b7 100644 --- a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs +++ b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs @@ -419,7 +419,11 @@ namespace ILCompiler public void RootModuleMetadata(ModuleDesc module, string reason) { - _graph.AddRoot(_factory.ModuleMetadata(module), reason); + // RootModuleMetadata is kind of a hack - this is pretty much only used to force include + // type forwarders from assemblies metadata generator would normally not look at. + // This will go away when the temporary RD.XML parser goes away. + if (_factory.MetadataManager is UsageBasedMetadataManager) + _graph.AddRoot(_factory.ModuleMetadata(module), reason); } public void RootReadOnlyDataBlob(byte[] data, int alignment, string reason, string exportName) diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs index 1d2c7832d..6299c3fff 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs @@ -774,7 +774,7 @@ namespace ILCompiler.DependencyAnalysis // Final NewSlot methods cannot be overridden, and therefore can be placed in the sealed-vtable to reduce the size of the vtable // of this type and any type that inherits from it. - if (declMethod.CanMethodBeInSealedVTable() && !declType.IsArrayTypeWithoutGenericInterfaces() && !factory.IsCppCodegenTemporaryWorkaround) + if (declMethod.CanMethodBeInSealedVTable() && !declType.IsArrayTypeWithoutGenericInterfaces()) continue; if (!implMethod.IsAbstract) @@ -838,7 +838,12 @@ namespace ILCompiler.DependencyAnalysis SealedVTableNode sealedVTable = factory.SealedVTable(_type.ConvertToCanonForm(CanonicalFormKind.Specific)); if (sealedVTable.BuildSealedVTableSlots(factory, relocsOnly) && sealedVTable.NumSealedVTableEntries > 0) - objData.EmitReloc(sealedVTable, RelocType.IMAGE_REL_BASED_RELPTR32); + { + if (factory.Target.SupportsRelativePointers) + objData.EmitReloc(sealedVTable, RelocType.IMAGE_REL_BASED_RELPTR32); + else + objData.EmitPointerReloc(sealedVTable); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs index d6ecd195c..26b0c703d 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs @@ -912,6 +912,9 @@ namespace ILCompiler.DependencyAnalysis internal TypeMetadataNode TypeMetadata(MetadataType type) { + // These are only meaningful for UsageBasedMetadataManager. We should not have them + // in the dependency graph otherwise. + Debug.Assert(MetadataManager is UsageBasedMetadataManager); return _typesWithMetadata.GetOrAdd(type); } @@ -919,6 +922,9 @@ namespace ILCompiler.DependencyAnalysis internal MethodMetadataNode MethodMetadata(MethodDesc method) { + // These are only meaningful for UsageBasedMetadataManager. We should not have them + // in the dependency graph otherwise. + Debug.Assert(MetadataManager is UsageBasedMetadataManager); return _methodsWithMetadata.GetOrAdd(method); } @@ -926,6 +932,9 @@ namespace ILCompiler.DependencyAnalysis internal FieldMetadataNode FieldMetadata(FieldDesc field) { + // These are only meaningful for UsageBasedMetadataManager. We should not have them + // in the dependency graph otherwise. + Debug.Assert(MetadataManager is UsageBasedMetadataManager); return _fieldsWithMetadata.GetOrAdd(field); } @@ -933,6 +942,9 @@ namespace ILCompiler.DependencyAnalysis internal ModuleMetadataNode ModuleMetadata(ModuleDesc module) { + // These are only meaningful for UsageBasedMetadataManager. We should not have them + // in the dependency graph otherwise. + Debug.Assert(MetadataManager is UsageBasedMetadataManager); return _modulesWithMetadata.GetOrAdd(module); } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs index 942e14dc4..dac6d8dbc 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs @@ -90,10 +90,6 @@ namespace ILCompiler.DependencyAnalysis _sealedVTableEntries = new List<MethodDesc>(); - // Cpp codegen does not support sealed vtables - if (factory.IsCppCodegenTemporaryWorkaround) - return true; - IReadOnlyList<MethodDesc> virtualSlots = factory.VTable(declType).Slots; for (int i = 0; i < virtualSlots.Count; i++) @@ -153,7 +149,12 @@ namespace ILCompiler.DependencyAnalysis for (int i = 0; i < _sealedVTableEntries.Count; i++) { MethodDesc canonImplMethod = _sealedVTableEntries[i].GetCanonMethodTarget(CanonicalFormKind.Specific); - objData.EmitReloc(factory.MethodEntrypoint(canonImplMethod, _sealedVTableEntries[i].OwningType.IsValueType), RelocType.IMAGE_REL_BASED_RELPTR32); + IMethodNode relocTarget = factory.MethodEntrypoint(canonImplMethod, _sealedVTableEntries[i].OwningType.IsValueType); + + if (factory.Target.SupportsRelativePointers) + objData.EmitReloc(relocTarget, RelocType.IMAGE_REL_BASED_RELPTR32); + else + objData.EmitPointerReloc(relocTarget); } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataNode.cs index a8416afad..39ad01e9f 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataNode.cs @@ -51,6 +51,23 @@ namespace ILCompiler.DependencyAnalysis dependencies.Add(factory.MethodMetadata(_type.GetMethod("Invoke", null)), "Delegate invoke method metadata"); } + // If the user asked for complete metadata to be generated for all types that are getting metadata, ensure that. + var mdManager = (UsageBasedMetadataManager)factory.MetadataManager; + if ((mdManager._generationOptions & UsageBasedMetadataGenerationOptions.CompleteTypesOnly) != 0) + { + foreach (MethodDesc method in _type.GetMethods()) + { + if (!mdManager.IsReflectionBlocked(method)) + dependencies.Add(factory.MethodMetadata(method), "Complete metadata for type"); + } + + foreach (FieldDesc field in _type.GetFields()) + { + if (!mdManager.IsReflectionBlocked(field)) + dependencies.Add(factory.FieldMetadata(field), "Complete metadata for type"); + } + } + return dependencies; } diff --git a/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs index 3d13aa547..c6a71b2b4 100644 --- a/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Collections.Generic; using Internal.TypeSystem; @@ -23,6 +24,7 @@ namespace ILCompiler { private readonly CompilationModuleGroup _compilationModuleGroup; + internal readonly UsageBasedMetadataGenerationOptions _generationOptions; private readonly bool _hasPreciseFieldUsageInformation; private readonly List<ModuleDesc> _modulesWithMetadata = new List<ModuleDesc>(); @@ -36,12 +38,14 @@ namespace ILCompiler MetadataBlockingPolicy blockingPolicy, ManifestResourceBlockingPolicy resourceBlockingPolicy, string logFile, - StackTraceEmissionPolicy stackTracePolicy) + StackTraceEmissionPolicy stackTracePolicy, + UsageBasedMetadataGenerationOptions generationOptions) : base(typeSystemContext, blockingPolicy, resourceBlockingPolicy, logFile, stackTracePolicy) { // We use this to mark places that would behave differently if we tracked exact fields used. _hasPreciseFieldUsageInformation = false; _compilationModuleGroup = group; + _generationOptions = generationOptions; } protected override void Graph_NewMarkedNode(DependencyNodeCore<NodeFactory> obj) @@ -439,4 +443,21 @@ namespace ILCompiler } } } + + [Flags] + public enum UsageBasedMetadataGenerationOptions + { + None = 0, + + /// <summary> + /// Specifies that complete metadata should be generated for types. + /// </summary> + /// <remarks> + /// If this option is set, generated metadata will no longer be pay for play, + /// and a certain class of bugs will disappear (APIs returning "member doesn't + /// exist" at runtime, even though the member exists and we just didn't generate the metadata). + /// Reflection blocking still applies. + /// </remarks> + CompleteTypesOnly = 1, + } } diff --git a/src/ILCompiler.Compiler/src/Compiler/VirtualMethodCallHelper.cs b/src/ILCompiler.Compiler/src/Compiler/VirtualMethodCallHelper.cs index 8266ed8df..19da1f6ae 100644 --- a/src/ILCompiler.Compiler/src/Compiler/VirtualMethodCallHelper.cs +++ b/src/ILCompiler.Compiler/src/Compiler/VirtualMethodCallHelper.cs @@ -18,9 +18,7 @@ namespace ILCompiler /// </summary> public static int GetVirtualMethodSlot(NodeFactory factory, MethodDesc method, TypeDesc implType, bool countDictionarySlots = true) { - // CppCodegen does not yet support sealed vtables. - - if (method.CanMethodBeInSealedVTable() && !factory.IsCppCodegenTemporaryWorkaround) + if (method.CanMethodBeInSealedVTable()) { // If the method is a sealed newslot method, it will be put in the sealed vtable instead of the type's vtable. In this // case, the slot index return should be the index in the sealed vtable, plus the total number of vtable slots. @@ -71,7 +69,7 @@ namespace ILCompiler int numSealedVTableEntries = 0; for (int slot = 0; slot < virtualSlots.Count; slot++) { - if (virtualSlots[slot].CanMethodBeInSealedVTable() && !factory.IsCppCodegenTemporaryWorkaround) + if (virtualSlots[slot].CanMethodBeInSealedVTable()) { numSealedVTableEntries++; continue; @@ -133,7 +131,7 @@ namespace ILCompiler foreach (var vtableMethod in baseVirtualSlots) { // Methods in the sealed vtable should be excluded from the count - if (vtableMethod.CanMethodBeInSealedVTable() && !factory.IsCppCodegenTemporaryWorkaround) + if (vtableMethod.CanMethodBeInSealedVTable()) continue; baseSlots++; } |