// Ask the metadata manager
// if we have any dependencies due to presence of the EEType.
- factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type);
+ bool isFullType = factory.MaximallyConstructableType(_type) == this;
+ factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type, isFullType);
if (_type is MetadataType mdType)
ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencies, factory, mdType.Module);
DependencyList dependencyList = null;
// Ask the metadata manager if we have any dependencies due to the presence of the EEType.
- factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type);
+ factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type, isFullType: true);
return dependencyList;
}
_typesWithMetadata = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
- return new TypeMetadataNode(type);
+ return new TypeMetadataNode(type, includeCustomAttributes: true);
+ });
+
+ _typesWithMetadataWithoutCustomAttributes = new NodeCache<MetadataType, TypeMetadataNode>(type =>
+ {
+ return new TypeMetadataNode(type, includeCustomAttributes: false);
});
_methodsWithMetadata = new NodeCache<MethodDesc, MethodMetadataNode>(method =>
return _typesWithMetadata.GetOrAdd(type);
}
+ private NodeCache<MetadataType, TypeMetadataNode> _typesWithMetadataWithoutCustomAttributes;
+
+ internal TypeMetadataNode TypeMetadataWithoutCustomAttributes(MetadataType type)
+ {
+ // These are only meaningful for UsageBasedMetadataManager. We should not have them
+ // in the dependency graph otherwise.
+ Debug.Assert(MetadataManager is UsageBasedMetadataManager);
+ return _typesWithMetadataWithoutCustomAttributes.GetOrAdd(type);
+ }
+
private NodeCache<MethodDesc, MethodMetadataNode> _methodsWithMetadata;
internal MethodMetadataNode MethodMetadata(MethodDesc method)
internal sealed class TypeMetadataNode : DependencyNodeCore<NodeFactory>
{
private readonly MetadataType _type;
+ private readonly bool _includeCustomAttributes;
- public TypeMetadataNode(MetadataType type)
+ public TypeMetadataNode(MetadataType type, bool includeCustomAttributes)
{
Debug.Assert(type.IsTypeDefinition);
_type = type;
+ _includeCustomAttributes = includeCustomAttributes;
}
public MetadataType Type => _type;
{
DependencyList dependencies = new DependencyList();
- CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));
+ if (_includeCustomAttributes)
+ CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));
DefType containingType = _type.ContainingType;
if (containingType != null)
- dependencies.Add(factory.TypeMetadata((MetadataType)containingType), "Containing type of a reflectable type");
+ {
+ TypeMetadataNode metadataNode = _includeCustomAttributes
+ ? factory.TypeMetadata((MetadataType)containingType)
+ : factory.TypeMetadataWithoutCustomAttributes((MetadataType)containingType);
+ dependencies.Add(metadataNode, "Containing type of a reflectable type");
+ }
else
+ {
dependencies.Add(factory.ModuleMetadata(_type.Module), "Containing module of a reflectable type");
+ }
var mdManager = (UsageBasedMetadataManager)factory.MetadataManager;
/// Decomposes a constructed type into individual <see cref="TypeMetadataNode"/> units that will be needed to
/// express the constructed type in metadata.
/// </summary>
- public static void GetMetadataDependencies(ref DependencyList dependencies, NodeFactory nodeFactory, TypeDesc type, string reason)
+ public static void GetMetadataDependencies(ref DependencyList dependencies, NodeFactory nodeFactory, TypeDesc type, string reason, bool isFullType = true)
{
MetadataManager mdManager = nodeFactory.MetadataManager;
case TypeFlags.SzArray:
case TypeFlags.ByRef:
case TypeFlags.Pointer:
- GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason);
+ GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason, isFullType);
break;
case TypeFlags.FunctionPointer:
var pointerType = (FunctionPointerType)type;
- GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason);
+ GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason, isFullType);
foreach (TypeDesc paramType in pointerType.Signature)
- GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason);
+ GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason, isFullType);
break;
case TypeFlags.SignatureMethodVariable:
default:
Debug.Assert(type.IsDefType);
- TypeDesc typeDefinition = type.GetTypeDefinition();
+ var typeDefinition = (MetadataType)type.GetTypeDefinition();
if (typeDefinition != type)
{
- if (mdManager.CanGenerateMetadata((MetadataType)typeDefinition))
- {
- dependencies ??= new DependencyList();
- dependencies.Add(nodeFactory.TypeMetadata((MetadataType)typeDefinition), reason);
- }
-
foreach (TypeDesc typeArg in type.Instantiation)
{
- GetMetadataDependencies(ref dependencies, nodeFactory, typeArg, reason);
+ GetMetadataDependencies(ref dependencies, nodeFactory, typeArg, reason, isFullType);
}
}
- else
+
+ if (mdManager.CanGenerateMetadata(typeDefinition))
{
- if (mdManager.CanGenerateMetadata((MetadataType)type))
- {
- dependencies ??= new DependencyList();
- dependencies.Add(nodeFactory.TypeMetadata((MetadataType)type), reason);
- }
+ dependencies ??= new DependencyList();
+ TypeMetadataNode node = isFullType
+ ? nodeFactory.TypeMetadata(typeDefinition)
+ : nodeFactory.TypeMetadataWithoutCustomAttributes(typeDefinition);
+ dependencies.Add(node, reason);
}
break;
}
protected override string GetName(NodeFactory factory)
{
- return "Reflectable type: " + _type.ToString();
+ return $"Reflectable type: {_type}{(!_includeCustomAttributes ? " (No custom attributes)" : "")}";
}
protected override void OnMarked(NodeFactory factory)
/// <summary>
/// This method is an extension point that can provide additional metadata-based dependencies to generated EETypes.
/// </summary>
- public virtual void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
+ public virtual void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
{
MetadataCategory category = GetMetadataCategory(type);
if ((category & MetadataCategory.Description) != 0)
{
- GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type);
+ GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type, isFullType);
}
}
// MetadataManagers can override this to provide additional dependencies caused by using a module
}
- protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
+ protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
{
// MetadataManagers can override this to provide additional dependencies caused by the emission of metadata
// (E.g. dependencies caused by the type having custom attributes applied to it: making sure we compile the attribute constructor
}
}
- protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
+ protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
{
- TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type");
+ TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type", isFullType);
if (type.IsDelegate)
{
return false;
}
- public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
+ public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
{
- base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type);
+ base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type, isFullType);
DataflowAnalyzedTypeDefinitionNode.GetDependencies(ref dependencies, factory, FlowAnnotations, type);
}
public bool GeneratesMetadata(MetadataType typeDef)
{
- return _factory.TypeMetadata(typeDef).Marked;
+ return _factory.TypeMetadata(typeDef).Marked || _factory.TypeMetadataWithoutCustomAttributes(typeDef).Marked;
}
public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle)
TestStaticVirtualMethodOptimizations.Run();
TestTypeEquals.Run();
TestBranchesInGenericCodeRemoval.Run();
+ TestLimitedMetadataBlobs.Run();
return 100;
}
}
}
+ class TestLimitedMetadataBlobs
+ {
+ class MyAttribute : Attribute
+ {
+ public MyAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type t) { }
+ }
+
+ class ShouldNotBeNeeded
+ {
+ }
+
+ [My(typeof(ShouldNotBeNeeded))]
+ interface INeverImplemented
+ {
+ void Never();
+ }
+
+ static INeverImplemented s_instance;
+#if !DEBUG
+ static Type s_type;
+#endif
+
+ internal static void Run()
+ {
+ Console.WriteLine("Testing generation of limited metadata blobs");
+
+ // Force a reference to the interface from a dispatch cell
+ if (s_instance != null)
+ s_instance.Never();
+
+ // Following is for release only since it relies on optimizing the typeof into an unconstructed
+ // MethodTable.
+#if !DEBUG
+ // Force another reference from an LDTOKEN
+ if (s_type == typeof(INeverImplemented))
+ s_type = typeof(object);
+#endif
+
+ ThrowIfPresent(typeof(TestLimitedMetadataBlobs), nameof(ShouldNotBeNeeded));
+ ThrowIfPresent(typeof(TestLimitedMetadataBlobs), nameof(MyAttribute));
+ ThrowIfNotPresent(typeof(TestLimitedMetadataBlobs), nameof(INeverImplemented));
+ }
+ }
+
+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
Justification = "That's the point")]
private static Type GetTypeSecretly(Type testType, string typeName) => testType.GetNestedType(typeName, BindingFlags.NonPublic | BindingFlags.Public);