Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -625,8 +625,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact

// Ask the metadata manager
// if we have any dependencies due to presence of the EEType.
bool isFullType = factory.MaximallyConstructableType(_type) == this;
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type, isFullType);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type);

if (_type is MetadataType mdType)
ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencies, factory, mdType.Module);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
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, isFullType: true);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type);

return dependencyList;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -458,12 +458,7 @@ private void CreateNodeCaches()

_typesWithMetadata = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: true);
});

_typesWithMetadataWithoutCustomAttributes = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: false);
return new TypeMetadataNode(type);
});

_methodsWithMetadata = new NodeCache<MethodDesc, MethodMetadataNode>(method =>
Expand DownExpand Up@@ -1161,16 +1156,6 @@ internal TypeMetadataNode TypeMetadata(MetadataType type)
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)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,13 +24,11 @@ namespace ILCompiler.DependencyAnalysis
internal sealed class TypeMetadataNode : DependencyNodeCore<NodeFactory>
{
private readonly MetadataType _type;
private readonly bool _includeCustomAttributes;

public TypeMetadataNode(MetadataType type, bool includeCustomAttributes)
public TypeMetadataNode(MetadataType type)
{
Debug.Assert(type.IsTypeDefinition);
_type = type;
_includeCustomAttributes = includeCustomAttributes;
}

public MetadataType Type => _type;
Expand All@@ -39,21 +37,13 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
{
DependencyList dependencies = new DependencyList();

if (_includeCustomAttributes)
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));

DefType containingType = _type.ContainingType;
if (containingType != null)
{
TypeMetadataNode metadataNode = _includeCustomAttributes
? factory.TypeMetadata((MetadataType)containingType)
: factory.TypeMetadataWithoutCustomAttributes((MetadataType)containingType);
dependencies.Add(metadataNode, "Containing type of a reflectable type");
}
dependencies.Add(factory.TypeMetadata((MetadataType)containingType), "Containing type of a reflectable type");
else
{
dependencies.Add(factory.ModuleMetadata(_type.Module), "Containing module of a reflectable type");
}

var mdManager = (UsageBasedMetadataManager)factory.MetadataManager;

Expand DownExpand Up@@ -110,7 +100,7 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
/// 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, bool isFullType = true)
public static void GetMetadataDependencies(ref DependencyList dependencies, NodeFactory nodeFactory, TypeDesc type, string reason)
{
MetadataManager mdManager = nodeFactory.MetadataManager;

Expand All@@ -120,13 +110,13 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
case TypeFlags.SzArray:
case TypeFlags.ByRef:
case TypeFlags.Pointer:
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason);
break;
case TypeFlags.FunctionPointer:
var pointerType = (FunctionPointerType)type;
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason);
foreach (TypeDesc paramType in pointerType.Signature)
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason);
break;

case TypeFlags.SignatureMethodVariable:
Expand All@@ -136,30 +126,35 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
default:
Debug.Assert(type.IsDefType);

var typeDefinition = (MetadataType)type.GetTypeDefinition();
TypeDesc typeDefinition = 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, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, typeArg, reason);
}
}

if (mdManager.CanGenerateMetadata(typeDefinition))
else
{
dependencies ??= new DependencyList();
TypeMetadataNode node = isFullType
? nodeFactory.TypeMetadata(typeDefinition)
: nodeFactory.TypeMetadataWithoutCustomAttributes(typeDefinition);
dependencies.Add(node, reason);
if (mdManager.CanGenerateMetadata((MetadataType)type))
{
dependencies ??= new DependencyList();
dependencies.Add(nodeFactory.TypeMetadata((MetadataType)type), reason);
}
}
break;
}
}

protected override string GetName(NodeFactory factory)
{
return $"Reflectable type: {_type}{(!_includeCustomAttributes ? " (No custom attributes)" : "")}";
return "Reflectable type: " + _type.ToString();
}

protected override void OnMarked(NodeFactory factory)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,13 +478,13 @@ protected virtual void GetMetadataDependenciesDueToReflectability(ref Dependency
/// <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, bool isFullType)
public virtual void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
MetadataCategory category = GetMetadataCategory(type);

if ((category & MetadataCategory.Description) != 0)
{
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type, isFullType);
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type);
}
}

Expand All@@ -493,7 +493,7 @@ internal virtual void GetDependenciesDueToModuleUse(ref DependencyList dependenc
// MetadataManagers can override this to provide additional dependencies caused by using a module
}

protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
// 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
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -271,9 +271,9 @@ internal override void GetDependenciesDueToModuleUse(ref DependencyList dependen
}
}

protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type", isFullType);
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type");

if (type.IsDelegate)
{
Expand DownExpand Up@@ -385,9 +385,9 @@ private static bool IsTrimmableAssembly(ModuleDesc assembly)
return false;
}

public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type, isFullType);
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type);

DataflowAnalyzedTypeDefinitionNode.GetDependencies(ref dependencies, factory, FlowAnnotations, type);
}
Expand DownExpand Up@@ -970,7 +970,7 @@ public bool GeneratesMetadata(MethodDesc methodDef)

public bool GeneratesMetadata(MetadataType typeDef)
{
return _factory.TypeMetadata(typeDef).Marked || _factory.TypeMetadataWithoutCustomAttributes(typeDef).Marked;
return _factory.TypeMetadata(typeDef).Marked;
}

public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle)
Expand Down
30 changes: 30 additions & 0 deletions src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -67,6 +67,7 @@ private static int Main()
TestByRefTypeLoad.Run();
TestGenericLdtoken.Run();
TestAbstractGenericLdtoken.Run();
TestTypeHandlesVisibleFromIDynamicInterfaceCastable.Run();

//
// Mostly functionality tests
Expand DownExpand Up@@ -2457,6 +2458,35 @@ public static void Run()
}
}

class TestTypeHandlesVisibleFromIDynamicInterfaceCastable
{
class MyAttribute : Attribute { }

[My]
interface IUnusedInterface { }

class Foo : IDynamicInterfaceCastable
{
public RuntimeTypeHandle GetInterfaceImplementation(RuntimeTypeHandle interfaceType) => throw new NotImplementedException();

public bool IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)
{
Type t = Type.GetTypeFromHandle(interfaceType);
if (t.GetCustomAttribute<MyAttribute>() == null)
throw new Exception();

return true;
}
}

public static void Run()
{
object myObject = new Foo();
if (myObject is not IUnusedInterface)
throw new Exception();
}
}

class TestEntryPoint
{
public static void Run()
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,7 +21,6 @@ public static int Run()
TestStaticVirtualMethodOptimizations.Run();
TestTypeEquals.Run();
TestBranchesInGenericCodeRemoval.Run();
TestLimitedMetadataBlobs.Run();

return 100;
}
Expand DownExpand Up@@ -379,51 +378,6 @@ public static void Run()
}
}

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);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -625,8 +625,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact

// Ask the metadata manager
// if we have any dependencies due to presence of the EEType.
bool isFullType = factory.MaximallyConstructableType(_type) == this;
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type, isFullType);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type);

if (_type is MetadataType mdType)
ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencies, factory, mdType.Module);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
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, isFullType: true);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type);

return dependencyList;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -458,12 +458,7 @@ private void CreateNodeCaches()

_typesWithMetadata = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: true);
});

_typesWithMetadataWithoutCustomAttributes = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: false);
return new TypeMetadataNode(type);
});

_methodsWithMetadata = new NodeCache<MethodDesc, MethodMetadataNode>(method =>
Expand DownExpand Up@@ -1161,16 +1156,6 @@ internal TypeMetadataNode TypeMetadata(MetadataType type)
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)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,13 +24,11 @@ namespace ILCompiler.DependencyAnalysis
internal sealed class TypeMetadataNode : DependencyNodeCore<NodeFactory>
{
private readonly MetadataType _type;
private readonly bool _includeCustomAttributes;

public TypeMetadataNode(MetadataType type, bool includeCustomAttributes)
public TypeMetadataNode(MetadataType type)
{
Debug.Assert(type.IsTypeDefinition);
_type = type;
_includeCustomAttributes = includeCustomAttributes;
}

public MetadataType Type => _type;
Expand All@@ -39,21 +37,13 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
{
DependencyList dependencies = new DependencyList();

if (_includeCustomAttributes)
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));

DefType containingType = _type.ContainingType;
if (containingType != null)
{
TypeMetadataNode metadataNode = _includeCustomAttributes
? factory.TypeMetadata((MetadataType)containingType)
: factory.TypeMetadataWithoutCustomAttributes((MetadataType)containingType);
dependencies.Add(metadataNode, "Containing type of a reflectable type");
}
dependencies.Add(factory.TypeMetadata((MetadataType)containingType), "Containing type of a reflectable type");
else
{
dependencies.Add(factory.ModuleMetadata(_type.Module), "Containing module of a reflectable type");
}

var mdManager = (UsageBasedMetadataManager)factory.MetadataManager;

Expand DownExpand Up@@ -110,7 +100,7 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
/// 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, bool isFullType = true)
public static void GetMetadataDependencies(ref DependencyList dependencies, NodeFactory nodeFactory, TypeDesc type, string reason)
{
MetadataManager mdManager = nodeFactory.MetadataManager;

Expand All@@ -120,13 +110,13 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
case TypeFlags.SzArray:
case TypeFlags.ByRef:
case TypeFlags.Pointer:
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason);
break;
case TypeFlags.FunctionPointer:
var pointerType = (FunctionPointerType)type;
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason);
foreach (TypeDesc paramType in pointerType.Signature)
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason);
break;

case TypeFlags.SignatureMethodVariable:
Expand All@@ -136,30 +126,35 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
default:
Debug.Assert(type.IsDefType);

var typeDefinition = (MetadataType)type.GetTypeDefinition();
TypeDesc typeDefinition = 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, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, typeArg, reason);
}
}

if (mdManager.CanGenerateMetadata(typeDefinition))
else
{
dependencies ??= new DependencyList();
TypeMetadataNode node = isFullType
? nodeFactory.TypeMetadata(typeDefinition)
: nodeFactory.TypeMetadataWithoutCustomAttributes(typeDefinition);
dependencies.Add(node, reason);
if (mdManager.CanGenerateMetadata((MetadataType)type))
{
dependencies ??= new DependencyList();
dependencies.Add(nodeFactory.TypeMetadata((MetadataType)type), reason);
}
}
break;
}
}

protected override string GetName(NodeFactory factory)
{
return $"Reflectable type: {_type}{(!_includeCustomAttributes ? " (No custom attributes)" : "")}";
return "Reflectable type: " + _type.ToString();
}

protected override void OnMarked(NodeFactory factory)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,13 +478,13 @@ protected virtual void GetMetadataDependenciesDueToReflectability(ref Dependency
/// <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, bool isFullType)
public virtual void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
MetadataCategory category = GetMetadataCategory(type);

if ((category & MetadataCategory.Description) != 0)
{
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type, isFullType);
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type);
}
}

Expand All@@ -493,7 +493,7 @@ internal virtual void GetDependenciesDueToModuleUse(ref DependencyList dependenc
// MetadataManagers can override this to provide additional dependencies caused by using a module
}

protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
// 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
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -271,9 +271,9 @@ internal override void GetDependenciesDueToModuleUse(ref DependencyList dependen
}
}

protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type", isFullType);
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type");

if (type.IsDelegate)
{
Expand DownExpand Up@@ -385,9 +385,9 @@ private static bool IsTrimmableAssembly(ModuleDesc assembly)
return false;
}

public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type, isFullType);
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type);

DataflowAnalyzedTypeDefinitionNode.GetDependencies(ref dependencies, factory, FlowAnnotations, type);
}
Expand DownExpand Up@@ -970,7 +970,7 @@ public bool GeneratesMetadata(MethodDesc methodDef)

public bool GeneratesMetadata(MetadataType typeDef)
{
return _factory.TypeMetadata(typeDef).Marked || _factory.TypeMetadataWithoutCustomAttributes(typeDef).Marked;
return _factory.TypeMetadata(typeDef).Marked;
}

public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle)
Expand Down
30 changes: 30 additions & 0 deletions src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -67,6 +67,7 @@ private static int Main()
TestByRefTypeLoad.Run();
TestGenericLdtoken.Run();
TestAbstractGenericLdtoken.Run();
TestTypeHandlesVisibleFromIDynamicInterfaceCastable.Run();

//
// Mostly functionality tests
Expand DownExpand Up@@ -2457,6 +2458,35 @@ public static void Run()
}
}

class TestTypeHandlesVisibleFromIDynamicInterfaceCastable
{
class MyAttribute : Attribute { }

[My]
interface IUnusedInterface { }

class Foo : IDynamicInterfaceCastable
{
public RuntimeTypeHandle GetInterfaceImplementation(RuntimeTypeHandle interfaceType) => throw new NotImplementedException();

public bool IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)
{
Type t = Type.GetTypeFromHandle(interfaceType);
if (t.GetCustomAttribute<MyAttribute>() == null)
throw new Exception();

return true;
}
}

public static void Run()
{
object myObject = new Foo();
if (myObject is not IUnusedInterface)
throw new Exception();
}
}

class TestEntryPoint
{
public static void Run()
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,7 +21,6 @@ public static int Run()
TestStaticVirtualMethodOptimizations.Run();
TestTypeEquals.Run();
TestBranchesInGenericCodeRemoval.Run();
TestLimitedMetadataBlobs.Run();

return 100;
}
Expand DownExpand Up@@ -379,51 +378,6 @@ public static void Run()
}
}

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);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -625,8 +625,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact

// Ask the metadata manager
// if we have any dependencies due to presence of the EEType.
bool isFullType = factory.MaximallyConstructableType(_type) == this;
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type, isFullType);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type);

if (_type is MetadataType mdType)
ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencies, factory, mdType.Module);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
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, isFullType: true);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type);

return dependencyList;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -458,12 +458,7 @@ private void CreateNodeCaches()

_typesWithMetadata = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: true);
});

_typesWithMetadataWithoutCustomAttributes = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: false);
return new TypeMetadataNode(type);
});

_methodsWithMetadata = new NodeCache<MethodDesc, MethodMetadataNode>(method =>
Expand DownExpand Up@@ -1161,16 +1156,6 @@ internal TypeMetadataNode TypeMetadata(MetadataType type)
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)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,13 +24,11 @@ namespace ILCompiler.DependencyAnalysis
internal sealed class TypeMetadataNode : DependencyNodeCore<NodeFactory>
{
private readonly MetadataType _type;
private readonly bool _includeCustomAttributes;

public TypeMetadataNode(MetadataType type, bool includeCustomAttributes)
public TypeMetadataNode(MetadataType type)
{
Debug.Assert(type.IsTypeDefinition);
_type = type;
_includeCustomAttributes = includeCustomAttributes;
}

public MetadataType Type => _type;
Expand All@@ -39,21 +37,13 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
{
DependencyList dependencies = new DependencyList();

if (_includeCustomAttributes)
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));

DefType containingType = _type.ContainingType;
if (containingType != null)
{
TypeMetadataNode metadataNode = _includeCustomAttributes
? factory.TypeMetadata((MetadataType)containingType)
: factory.TypeMetadataWithoutCustomAttributes((MetadataType)containingType);
dependencies.Add(metadataNode, "Containing type of a reflectable type");
}
dependencies.Add(factory.TypeMetadata((MetadataType)containingType), "Containing type of a reflectable type");
else
{
dependencies.Add(factory.ModuleMetadata(_type.Module), "Containing module of a reflectable type");
}

var mdManager = (UsageBasedMetadataManager)factory.MetadataManager;

Expand DownExpand Up@@ -110,7 +100,7 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
/// 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, bool isFullType = true)
public static void GetMetadataDependencies(ref DependencyList dependencies, NodeFactory nodeFactory, TypeDesc type, string reason)
{
MetadataManager mdManager = nodeFactory.MetadataManager;

Expand All@@ -120,13 +110,13 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
case TypeFlags.SzArray:
case TypeFlags.ByRef:
case TypeFlags.Pointer:
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason);
break;
case TypeFlags.FunctionPointer:
var pointerType = (FunctionPointerType)type;
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason);
foreach (TypeDesc paramType in pointerType.Signature)
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason);
break;

case TypeFlags.SignatureMethodVariable:
Expand All@@ -136,30 +126,35 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
default:
Debug.Assert(type.IsDefType);

var typeDefinition = (MetadataType)type.GetTypeDefinition();
TypeDesc typeDefinition = 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, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, typeArg, reason);
}
}

if (mdManager.CanGenerateMetadata(typeDefinition))
else
{
dependencies ??= new DependencyList();
TypeMetadataNode node = isFullType
? nodeFactory.TypeMetadata(typeDefinition)
: nodeFactory.TypeMetadataWithoutCustomAttributes(typeDefinition);
dependencies.Add(node, reason);
if (mdManager.CanGenerateMetadata((MetadataType)type))
{
dependencies ??= new DependencyList();
dependencies.Add(nodeFactory.TypeMetadata((MetadataType)type), reason);
}
}
break;
}
}

protected override string GetName(NodeFactory factory)
{
return $"Reflectable type: {_type}{(!_includeCustomAttributes ? " (No custom attributes)" : "")}";
return "Reflectable type: " + _type.ToString();
}

protected override void OnMarked(NodeFactory factory)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,13 +478,13 @@ protected virtual void GetMetadataDependenciesDueToReflectability(ref Dependency
/// <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, bool isFullType)
public virtual void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
MetadataCategory category = GetMetadataCategory(type);

if ((category & MetadataCategory.Description) != 0)
{
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type, isFullType);
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type);
}
}

Expand All@@ -493,7 +493,7 @@ internal virtual void GetDependenciesDueToModuleUse(ref DependencyList dependenc
// MetadataManagers can override this to provide additional dependencies caused by using a module
}

protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
// 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
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -271,9 +271,9 @@ internal override void GetDependenciesDueToModuleUse(ref DependencyList dependen
}
}

protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type", isFullType);
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type");

if (type.IsDelegate)
{
Expand DownExpand Up@@ -385,9 +385,9 @@ private static bool IsTrimmableAssembly(ModuleDesc assembly)
return false;
}

public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type, isFullType);
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type);

DataflowAnalyzedTypeDefinitionNode.GetDependencies(ref dependencies, factory, FlowAnnotations, type);
}
Expand DownExpand Up@@ -970,7 +970,7 @@ public bool GeneratesMetadata(MethodDesc methodDef)

public bool GeneratesMetadata(MetadataType typeDef)
{
return _factory.TypeMetadata(typeDef).Marked || _factory.TypeMetadataWithoutCustomAttributes(typeDef).Marked;
return _factory.TypeMetadata(typeDef).Marked;
}

public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle)
Expand Down
30 changes: 30 additions & 0 deletions src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -67,6 +67,7 @@ private static int Main()
TestByRefTypeLoad.Run();
TestGenericLdtoken.Run();
TestAbstractGenericLdtoken.Run();
TestTypeHandlesVisibleFromIDynamicInterfaceCastable.Run();

//
// Mostly functionality tests
Expand DownExpand Up@@ -2457,6 +2458,35 @@ public static void Run()
}
}

class TestTypeHandlesVisibleFromIDynamicInterfaceCastable
{
class MyAttribute : Attribute { }

[My]
interface IUnusedInterface { }

class Foo : IDynamicInterfaceCastable
{
public RuntimeTypeHandle GetInterfaceImplementation(RuntimeTypeHandle interfaceType) => throw new NotImplementedException();

public bool IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)
{
Type t = Type.GetTypeFromHandle(interfaceType);
if (t.GetCustomAttribute<MyAttribute>() == null)
throw new Exception();

return true;
}
}

public static void Run()
{
object myObject = new Foo();
if (myObject is not IUnusedInterface)
throw new Exception();
}
}

class TestEntryPoint
{
public static void Run()
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,7 +21,6 @@ public static int Run()
TestStaticVirtualMethodOptimizations.Run();
TestTypeEquals.Run();
TestBranchesInGenericCodeRemoval.Run();
TestLimitedMetadataBlobs.Run();

return 100;
}
Expand DownExpand Up@@ -379,51 +378,6 @@ public static void Run()
}
}

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);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -625,8 +625,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact

// Ask the metadata manager
// if we have any dependencies due to presence of the EEType.
bool isFullType = factory.MaximallyConstructableType(_type) == this;
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type, isFullType);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type);

if (_type is MetadataType mdType)
ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencies, factory, mdType.Module);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
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, isFullType: true);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type);

return dependencyList;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -458,12 +458,7 @@ private void CreateNodeCaches()

_typesWithMetadata = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: true);
});

_typesWithMetadataWithoutCustomAttributes = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: false);
return new TypeMetadataNode(type);
});

_methodsWithMetadata = new NodeCache<MethodDesc, MethodMetadataNode>(method =>
Expand DownExpand Up@@ -1161,16 +1156,6 @@ internal TypeMetadataNode TypeMetadata(MetadataType type)
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)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,13 +24,11 @@ namespace ILCompiler.DependencyAnalysis
internal sealed class TypeMetadataNode : DependencyNodeCore<NodeFactory>
{
private readonly MetadataType _type;
private readonly bool _includeCustomAttributes;

public TypeMetadataNode(MetadataType type, bool includeCustomAttributes)
public TypeMetadataNode(MetadataType type)
{
Debug.Assert(type.IsTypeDefinition);
_type = type;
_includeCustomAttributes = includeCustomAttributes;
}

public MetadataType Type => _type;
Expand All@@ -39,21 +37,13 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
{
DependencyList dependencies = new DependencyList();

if (_includeCustomAttributes)
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));

DefType containingType = _type.ContainingType;
if (containingType != null)
{
TypeMetadataNode metadataNode = _includeCustomAttributes
? factory.TypeMetadata((MetadataType)containingType)
: factory.TypeMetadataWithoutCustomAttributes((MetadataType)containingType);
dependencies.Add(metadataNode, "Containing type of a reflectable type");
}
dependencies.Add(factory.TypeMetadata((MetadataType)containingType), "Containing type of a reflectable type");
else
{
dependencies.Add(factory.ModuleMetadata(_type.Module), "Containing module of a reflectable type");
}

var mdManager = (UsageBasedMetadataManager)factory.MetadataManager;

Expand DownExpand Up@@ -110,7 +100,7 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
/// 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, bool isFullType = true)
public static void GetMetadataDependencies(ref DependencyList dependencies, NodeFactory nodeFactory, TypeDesc type, string reason)
{
MetadataManager mdManager = nodeFactory.MetadataManager;

Expand All@@ -120,13 +110,13 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
case TypeFlags.SzArray:
case TypeFlags.ByRef:
case TypeFlags.Pointer:
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason);
break;
case TypeFlags.FunctionPointer:
var pointerType = (FunctionPointerType)type;
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason);
foreach (TypeDesc paramType in pointerType.Signature)
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason);
break;

case TypeFlags.SignatureMethodVariable:
Expand All@@ -136,30 +126,35 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
default:
Debug.Assert(type.IsDefType);

var typeDefinition = (MetadataType)type.GetTypeDefinition();
TypeDesc typeDefinition = 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, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, typeArg, reason);
}
}

if (mdManager.CanGenerateMetadata(typeDefinition))
else
{
dependencies ??= new DependencyList();
TypeMetadataNode node = isFullType
? nodeFactory.TypeMetadata(typeDefinition)
: nodeFactory.TypeMetadataWithoutCustomAttributes(typeDefinition);
dependencies.Add(node, reason);
if (mdManager.CanGenerateMetadata((MetadataType)type))
{
dependencies ??= new DependencyList();
dependencies.Add(nodeFactory.TypeMetadata((MetadataType)type), reason);
}
}
break;
}
}

protected override string GetName(NodeFactory factory)
{
return $"Reflectable type: {_type}{(!_includeCustomAttributes ? " (No custom attributes)" : "")}";
return "Reflectable type: " + _type.ToString();
}

protected override void OnMarked(NodeFactory factory)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,13 +478,13 @@ protected virtual void GetMetadataDependenciesDueToReflectability(ref Dependency
/// <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, bool isFullType)
public virtual void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
MetadataCategory category = GetMetadataCategory(type);

if ((category & MetadataCategory.Description) != 0)
{
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type, isFullType);
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type);
}
}

Expand All@@ -493,7 +493,7 @@ internal virtual void GetDependenciesDueToModuleUse(ref DependencyList dependenc
// MetadataManagers can override this to provide additional dependencies caused by using a module
}

protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
// 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
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -271,9 +271,9 @@ internal override void GetDependenciesDueToModuleUse(ref DependencyList dependen
}
}

protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type", isFullType);
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type");

if (type.IsDelegate)
{
Expand DownExpand Up@@ -385,9 +385,9 @@ private static bool IsTrimmableAssembly(ModuleDesc assembly)
return false;
}

public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type, isFullType);
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type);

DataflowAnalyzedTypeDefinitionNode.GetDependencies(ref dependencies, factory, FlowAnnotations, type);
}
Expand DownExpand Up@@ -970,7 +970,7 @@ public bool GeneratesMetadata(MethodDesc methodDef)

public bool GeneratesMetadata(MetadataType typeDef)
{
return _factory.TypeMetadata(typeDef).Marked || _factory.TypeMetadataWithoutCustomAttributes(typeDef).Marked;
return _factory.TypeMetadata(typeDef).Marked;
}

public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle)
Expand Down
30 changes: 30 additions & 0 deletions src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -67,6 +67,7 @@ private static int Main()
TestByRefTypeLoad.Run();
TestGenericLdtoken.Run();
TestAbstractGenericLdtoken.Run();
TestTypeHandlesVisibleFromIDynamicInterfaceCastable.Run();

//
// Mostly functionality tests
Expand DownExpand Up@@ -2457,6 +2458,35 @@ public static void Run()
}
}

class TestTypeHandlesVisibleFromIDynamicInterfaceCastable
{
class MyAttribute : Attribute { }

[My]
interface IUnusedInterface { }

class Foo : IDynamicInterfaceCastable
{
public RuntimeTypeHandle GetInterfaceImplementation(RuntimeTypeHandle interfaceType) => throw new NotImplementedException();

public bool IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)
{
Type t = Type.GetTypeFromHandle(interfaceType);
if (t.GetCustomAttribute<MyAttribute>() == null)
throw new Exception();

return true;
}
}

public static void Run()
{
object myObject = new Foo();
if (myObject is not IUnusedInterface)
throw new Exception();
}
}

class TestEntryPoint
{
public static void Run()
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,7 +21,6 @@ public static int Run()
TestStaticVirtualMethodOptimizations.Run();
TestTypeEquals.Run();
TestBranchesInGenericCodeRemoval.Run();
TestLimitedMetadataBlobs.Run();

return 100;
}
Expand DownExpand Up@@ -379,51 +378,6 @@ public static void Run()
}
}

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);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -625,8 +625,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact

// Ask the metadata manager
// if we have any dependencies due to presence of the EEType.
bool isFullType = factory.MaximallyConstructableType(_type) == this;
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type, isFullType);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type);

if (_type is MetadataType mdType)
ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencies, factory, mdType.Module);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
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, isFullType: true);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type);

return dependencyList;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -458,12 +458,7 @@ private void CreateNodeCaches()

_typesWithMetadata = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: true);
});

_typesWithMetadataWithoutCustomAttributes = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: false);
return new TypeMetadataNode(type);
});

_methodsWithMetadata = new NodeCache<MethodDesc, MethodMetadataNode>(method =>
Expand DownExpand Up@@ -1161,16 +1156,6 @@ internal TypeMetadataNode TypeMetadata(MetadataType type)
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)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,13 +24,11 @@ namespace ILCompiler.DependencyAnalysis
internal sealed class TypeMetadataNode : DependencyNodeCore<NodeFactory>
{
private readonly MetadataType _type;
private readonly bool _includeCustomAttributes;

public TypeMetadataNode(MetadataType type, bool includeCustomAttributes)
public TypeMetadataNode(MetadataType type)
{
Debug.Assert(type.IsTypeDefinition);
_type = type;
_includeCustomAttributes = includeCustomAttributes;
}

public MetadataType Type => _type;
Expand All@@ -39,21 +37,13 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
{
DependencyList dependencies = new DependencyList();

if (_includeCustomAttributes)
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));

DefType containingType = _type.ContainingType;
if (containingType != null)
{
TypeMetadataNode metadataNode = _includeCustomAttributes
? factory.TypeMetadata((MetadataType)containingType)
: factory.TypeMetadataWithoutCustomAttributes((MetadataType)containingType);
dependencies.Add(metadataNode, "Containing type of a reflectable type");
}
dependencies.Add(factory.TypeMetadata((MetadataType)containingType), "Containing type of a reflectable type");
else
{
dependencies.Add(factory.ModuleMetadata(_type.Module), "Containing module of a reflectable type");
}

var mdManager = (UsageBasedMetadataManager)factory.MetadataManager;

Expand DownExpand Up@@ -110,7 +100,7 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
/// 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, bool isFullType = true)
public static void GetMetadataDependencies(ref DependencyList dependencies, NodeFactory nodeFactory, TypeDesc type, string reason)
{
MetadataManager mdManager = nodeFactory.MetadataManager;

Expand All@@ -120,13 +110,13 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
case TypeFlags.SzArray:
case TypeFlags.ByRef:
case TypeFlags.Pointer:
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason);
break;
case TypeFlags.FunctionPointer:
var pointerType = (FunctionPointerType)type;
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason);
foreach (TypeDesc paramType in pointerType.Signature)
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason);
break;

case TypeFlags.SignatureMethodVariable:
Expand All@@ -136,30 +126,35 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
default:
Debug.Assert(type.IsDefType);

var typeDefinition = (MetadataType)type.GetTypeDefinition();
TypeDesc typeDefinition = 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, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, typeArg, reason);
}
}

if (mdManager.CanGenerateMetadata(typeDefinition))
else
{
dependencies ??= new DependencyList();
TypeMetadataNode node = isFullType
? nodeFactory.TypeMetadata(typeDefinition)
: nodeFactory.TypeMetadataWithoutCustomAttributes(typeDefinition);
dependencies.Add(node, reason);
if (mdManager.CanGenerateMetadata((MetadataType)type))
{
dependencies ??= new DependencyList();
dependencies.Add(nodeFactory.TypeMetadata((MetadataType)type), reason);
}
}
break;
}
}

protected override string GetName(NodeFactory factory)
{
return $"Reflectable type: {_type}{(!_includeCustomAttributes ? " (No custom attributes)" : "")}";
return "Reflectable type: " + _type.ToString();
}

protected override void OnMarked(NodeFactory factory)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,13 +478,13 @@ protected virtual void GetMetadataDependenciesDueToReflectability(ref Dependency
/// <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, bool isFullType)
public virtual void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
MetadataCategory category = GetMetadataCategory(type);

if ((category & MetadataCategory.Description) != 0)
{
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type, isFullType);
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type);
}
}

Expand All@@ -493,7 +493,7 @@ internal virtual void GetDependenciesDueToModuleUse(ref DependencyList dependenc
// MetadataManagers can override this to provide additional dependencies caused by using a module
}

protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
// 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
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -271,9 +271,9 @@ internal override void GetDependenciesDueToModuleUse(ref DependencyList dependen
}
}

protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type", isFullType);
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type");

if (type.IsDelegate)
{
Expand DownExpand Up@@ -385,9 +385,9 @@ private static bool IsTrimmableAssembly(ModuleDesc assembly)
return false;
}

public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type, isFullType);
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type);

DataflowAnalyzedTypeDefinitionNode.GetDependencies(ref dependencies, factory, FlowAnnotations, type);
}
Expand DownExpand Up@@ -970,7 +970,7 @@ public bool GeneratesMetadata(MethodDesc methodDef)

public bool GeneratesMetadata(MetadataType typeDef)
{
return _factory.TypeMetadata(typeDef).Marked || _factory.TypeMetadataWithoutCustomAttributes(typeDef).Marked;
return _factory.TypeMetadata(typeDef).Marked;
}

public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle)
Expand Down
30 changes: 30 additions & 0 deletions src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -67,6 +67,7 @@ private static int Main()
TestByRefTypeLoad.Run();
TestGenericLdtoken.Run();
TestAbstractGenericLdtoken.Run();
TestTypeHandlesVisibleFromIDynamicInterfaceCastable.Run();

//
// Mostly functionality tests
Expand DownExpand Up@@ -2457,6 +2458,35 @@ public static void Run()
}
}

class TestTypeHandlesVisibleFromIDynamicInterfaceCastable
{
class MyAttribute : Attribute { }

[My]
interface IUnusedInterface { }

class Foo : IDynamicInterfaceCastable
{
public RuntimeTypeHandle GetInterfaceImplementation(RuntimeTypeHandle interfaceType) => throw new NotImplementedException();

public bool IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)
{
Type t = Type.GetTypeFromHandle(interfaceType);
if (t.GetCustomAttribute<MyAttribute>() == null)
throw new Exception();

return true;
}
}

public static void Run()
{
object myObject = new Foo();
if (myObject is not IUnusedInterface)
throw new Exception();
}
}

class TestEntryPoint
{
public static void Run()
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,7 +21,6 @@ public static int Run()
TestStaticVirtualMethodOptimizations.Run();
TestTypeEquals.Run();
TestBranchesInGenericCodeRemoval.Run();
TestLimitedMetadataBlobs.Run();

return 100;
}
Expand DownExpand Up@@ -379,51 +378,6 @@ public static void Run()
}
}

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);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -625,8 +625,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact

// Ask the metadata manager
// if we have any dependencies due to presence of the EEType.
bool isFullType = factory.MaximallyConstructableType(_type) == this;
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type, isFullType);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type);

if (_type is MetadataType mdType)
ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencies, factory, mdType.Module);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
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, isFullType: true);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type);

return dependencyList;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -458,12 +458,7 @@ private void CreateNodeCaches()

_typesWithMetadata = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: true);
});

_typesWithMetadataWithoutCustomAttributes = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: false);
return new TypeMetadataNode(type);
});

_methodsWithMetadata = new NodeCache<MethodDesc, MethodMetadataNode>(method =>
Expand DownExpand Up@@ -1161,16 +1156,6 @@ internal TypeMetadataNode TypeMetadata(MetadataType type)
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)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,13 +24,11 @@ namespace ILCompiler.DependencyAnalysis
internal sealed class TypeMetadataNode : DependencyNodeCore<NodeFactory>
{
private readonly MetadataType _type;
private readonly bool _includeCustomAttributes;

public TypeMetadataNode(MetadataType type, bool includeCustomAttributes)
public TypeMetadataNode(MetadataType type)
{
Debug.Assert(type.IsTypeDefinition);
_type = type;
_includeCustomAttributes = includeCustomAttributes;
}

public MetadataType Type => _type;
Expand All@@ -39,21 +37,13 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
{
DependencyList dependencies = new DependencyList();

if (_includeCustomAttributes)
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));

DefType containingType = _type.ContainingType;
if (containingType != null)
{
TypeMetadataNode metadataNode = _includeCustomAttributes
? factory.TypeMetadata((MetadataType)containingType)
: factory.TypeMetadataWithoutCustomAttributes((MetadataType)containingType);
dependencies.Add(metadataNode, "Containing type of a reflectable type");
}
dependencies.Add(factory.TypeMetadata((MetadataType)containingType), "Containing type of a reflectable type");
else
{
dependencies.Add(factory.ModuleMetadata(_type.Module), "Containing module of a reflectable type");
}

var mdManager = (UsageBasedMetadataManager)factory.MetadataManager;

Expand DownExpand Up@@ -110,7 +100,7 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
/// 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, bool isFullType = true)
public static void GetMetadataDependencies(ref DependencyList dependencies, NodeFactory nodeFactory, TypeDesc type, string reason)
{
MetadataManager mdManager = nodeFactory.MetadataManager;

Expand All@@ -120,13 +110,13 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
case TypeFlags.SzArray:
case TypeFlags.ByRef:
case TypeFlags.Pointer:
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason);
break;
case TypeFlags.FunctionPointer:
var pointerType = (FunctionPointerType)type;
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason);
foreach (TypeDesc paramType in pointerType.Signature)
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason);
break;

case TypeFlags.SignatureMethodVariable:
Expand All@@ -136,30 +126,35 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
default:
Debug.Assert(type.IsDefType);

var typeDefinition = (MetadataType)type.GetTypeDefinition();
TypeDesc typeDefinition = 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, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, typeArg, reason);
}
}

if (mdManager.CanGenerateMetadata(typeDefinition))
else
{
dependencies ??= new DependencyList();
TypeMetadataNode node = isFullType
? nodeFactory.TypeMetadata(typeDefinition)
: nodeFactory.TypeMetadataWithoutCustomAttributes(typeDefinition);
dependencies.Add(node, reason);
if (mdManager.CanGenerateMetadata((MetadataType)type))
{
dependencies ??= new DependencyList();
dependencies.Add(nodeFactory.TypeMetadata((MetadataType)type), reason);
}
}
break;
}
}

protected override string GetName(NodeFactory factory)
{
return $"Reflectable type: {_type}{(!_includeCustomAttributes ? " (No custom attributes)" : "")}";
return "Reflectable type: " + _type.ToString();
}

protected override void OnMarked(NodeFactory factory)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,13 +478,13 @@ protected virtual void GetMetadataDependenciesDueToReflectability(ref Dependency
/// <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, bool isFullType)
public virtual void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
MetadataCategory category = GetMetadataCategory(type);

if ((category & MetadataCategory.Description) != 0)
{
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type, isFullType);
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type);
}
}

Expand All@@ -493,7 +493,7 @@ internal virtual void GetDependenciesDueToModuleUse(ref DependencyList dependenc
// MetadataManagers can override this to provide additional dependencies caused by using a module
}

protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
// 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
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -271,9 +271,9 @@ internal override void GetDependenciesDueToModuleUse(ref DependencyList dependen
}
}

protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type", isFullType);
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type");

if (type.IsDelegate)
{
Expand DownExpand Up@@ -385,9 +385,9 @@ private static bool IsTrimmableAssembly(ModuleDesc assembly)
return false;
}

public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type, isFullType);
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type);

DataflowAnalyzedTypeDefinitionNode.GetDependencies(ref dependencies, factory, FlowAnnotations, type);
}
Expand DownExpand Up@@ -970,7 +970,7 @@ public bool GeneratesMetadata(MethodDesc methodDef)

public bool GeneratesMetadata(MetadataType typeDef)
{
return _factory.TypeMetadata(typeDef).Marked || _factory.TypeMetadataWithoutCustomAttributes(typeDef).Marked;
return _factory.TypeMetadata(typeDef).Marked;
}

public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle)
Expand Down
30 changes: 30 additions & 0 deletions src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -67,6 +67,7 @@ private static int Main()
TestByRefTypeLoad.Run();
TestGenericLdtoken.Run();
TestAbstractGenericLdtoken.Run();
TestTypeHandlesVisibleFromIDynamicInterfaceCastable.Run();

//
// Mostly functionality tests
Expand DownExpand Up@@ -2457,6 +2458,35 @@ public static void Run()
}
}

class TestTypeHandlesVisibleFromIDynamicInterfaceCastable
{
class MyAttribute : Attribute { }

[My]
interface IUnusedInterface { }

class Foo : IDynamicInterfaceCastable
{
public RuntimeTypeHandle GetInterfaceImplementation(RuntimeTypeHandle interfaceType) => throw new NotImplementedException();

public bool IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)
{
Type t = Type.GetTypeFromHandle(interfaceType);
if (t.GetCustomAttribute<MyAttribute>() == null)
throw new Exception();

return true;
}
}

public static void Run()
{
object myObject = new Foo();
if (myObject is not IUnusedInterface)
throw new Exception();
}
}

class TestEntryPoint
{
public static void Run()
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,7 +21,6 @@ public static int Run()
TestStaticVirtualMethodOptimizations.Run();
TestTypeEquals.Run();
TestBranchesInGenericCodeRemoval.Run();
TestLimitedMetadataBlobs.Run();

return 100;
}
Expand DownExpand Up@@ -379,51 +378,6 @@ public static void Run()
}
}

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);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -625,8 +625,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact

// Ask the metadata manager
// if we have any dependencies due to presence of the EEType.
bool isFullType = factory.MaximallyConstructableType(_type) == this;
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type, isFullType);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type);

if (_type is MetadataType mdType)
ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencies, factory, mdType.Module);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
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, isFullType: true);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type);

return dependencyList;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -458,12 +458,7 @@ private void CreateNodeCaches()

_typesWithMetadata = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: true);
});

_typesWithMetadataWithoutCustomAttributes = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: false);
return new TypeMetadataNode(type);
});

_methodsWithMetadata = new NodeCache<MethodDesc, MethodMetadataNode>(method =>
Expand DownExpand Up@@ -1161,16 +1156,6 @@ internal TypeMetadataNode TypeMetadata(MetadataType type)
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)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,13 +24,11 @@ namespace ILCompiler.DependencyAnalysis
internal sealed class TypeMetadataNode : DependencyNodeCore<NodeFactory>
{
private readonly MetadataType _type;
private readonly bool _includeCustomAttributes;

public TypeMetadataNode(MetadataType type, bool includeCustomAttributes)
public TypeMetadataNode(MetadataType type)
{
Debug.Assert(type.IsTypeDefinition);
_type = type;
_includeCustomAttributes = includeCustomAttributes;
}

public MetadataType Type => _type;
Expand All@@ -39,21 +37,13 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
{
DependencyList dependencies = new DependencyList();

if (_includeCustomAttributes)
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));

DefType containingType = _type.ContainingType;
if (containingType != null)
{
TypeMetadataNode metadataNode = _includeCustomAttributes
? factory.TypeMetadata((MetadataType)containingType)
: factory.TypeMetadataWithoutCustomAttributes((MetadataType)containingType);
dependencies.Add(metadataNode, "Containing type of a reflectable type");
}
dependencies.Add(factory.TypeMetadata((MetadataType)containingType), "Containing type of a reflectable type");
else
{
dependencies.Add(factory.ModuleMetadata(_type.Module), "Containing module of a reflectable type");
}

var mdManager = (UsageBasedMetadataManager)factory.MetadataManager;

Expand DownExpand Up@@ -110,7 +100,7 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
/// 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, bool isFullType = true)
public static void GetMetadataDependencies(ref DependencyList dependencies, NodeFactory nodeFactory, TypeDesc type, string reason)
{
MetadataManager mdManager = nodeFactory.MetadataManager;

Expand All@@ -120,13 +110,13 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
case TypeFlags.SzArray:
case TypeFlags.ByRef:
case TypeFlags.Pointer:
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason);
break;
case TypeFlags.FunctionPointer:
var pointerType = (FunctionPointerType)type;
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason);
foreach (TypeDesc paramType in pointerType.Signature)
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason);
break;

case TypeFlags.SignatureMethodVariable:
Expand All@@ -136,30 +126,35 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
default:
Debug.Assert(type.IsDefType);

var typeDefinition = (MetadataType)type.GetTypeDefinition();
TypeDesc typeDefinition = 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, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, typeArg, reason);
}
}

if (mdManager.CanGenerateMetadata(typeDefinition))
else
{
dependencies ??= new DependencyList();
TypeMetadataNode node = isFullType
? nodeFactory.TypeMetadata(typeDefinition)
: nodeFactory.TypeMetadataWithoutCustomAttributes(typeDefinition);
dependencies.Add(node, reason);
if (mdManager.CanGenerateMetadata((MetadataType)type))
{
dependencies ??= new DependencyList();
dependencies.Add(nodeFactory.TypeMetadata((MetadataType)type), reason);
}
}
break;
}
}

protected override string GetName(NodeFactory factory)
{
return $"Reflectable type: {_type}{(!_includeCustomAttributes ? " (No custom attributes)" : "")}";
return "Reflectable type: " + _type.ToString();
}

protected override void OnMarked(NodeFactory factory)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,13 +478,13 @@ protected virtual void GetMetadataDependenciesDueToReflectability(ref Dependency
/// <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, bool isFullType)
public virtual void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
MetadataCategory category = GetMetadataCategory(type);

if ((category & MetadataCategory.Description) != 0)
{
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type, isFullType);
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type);
}
}

Expand All@@ -493,7 +493,7 @@ internal virtual void GetDependenciesDueToModuleUse(ref DependencyList dependenc
// MetadataManagers can override this to provide additional dependencies caused by using a module
}

protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
// 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
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -271,9 +271,9 @@ internal override void GetDependenciesDueToModuleUse(ref DependencyList dependen
}
}

protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type", isFullType);
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type");

if (type.IsDelegate)
{
Expand DownExpand Up@@ -385,9 +385,9 @@ private static bool IsTrimmableAssembly(ModuleDesc assembly)
return false;
}

public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type, isFullType);
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type);

DataflowAnalyzedTypeDefinitionNode.GetDependencies(ref dependencies, factory, FlowAnnotations, type);
}
Expand DownExpand Up@@ -970,7 +970,7 @@ public bool GeneratesMetadata(MethodDesc methodDef)

public bool GeneratesMetadata(MetadataType typeDef)
{
return _factory.TypeMetadata(typeDef).Marked || _factory.TypeMetadataWithoutCustomAttributes(typeDef).Marked;
return _factory.TypeMetadata(typeDef).Marked;
}

public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle)
Expand Down
30 changes: 30 additions & 0 deletions src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -67,6 +67,7 @@ private static int Main()
TestByRefTypeLoad.Run();
TestGenericLdtoken.Run();
TestAbstractGenericLdtoken.Run();
TestTypeHandlesVisibleFromIDynamicInterfaceCastable.Run();

//
// Mostly functionality tests
Expand DownExpand Up@@ -2457,6 +2458,35 @@ public static void Run()
}
}

class TestTypeHandlesVisibleFromIDynamicInterfaceCastable
{
class MyAttribute : Attribute { }

[My]
interface IUnusedInterface { }

class Foo : IDynamicInterfaceCastable
{
public RuntimeTypeHandle GetInterfaceImplementation(RuntimeTypeHandle interfaceType) => throw new NotImplementedException();

public bool IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)
{
Type t = Type.GetTypeFromHandle(interfaceType);
if (t.GetCustomAttribute<MyAttribute>() == null)
throw new Exception();

return true;
}
}

public static void Run()
{
object myObject = new Foo();
if (myObject is not IUnusedInterface)
throw new Exception();
}
}

class TestEntryPoint
{
public static void Run()
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,7 +21,6 @@ public static int Run()
TestStaticVirtualMethodOptimizations.Run();
TestTypeEquals.Run();
TestBranchesInGenericCodeRemoval.Run();
TestLimitedMetadataBlobs.Run();

return 100;
}
Expand DownExpand Up@@ -379,51 +378,6 @@ public static void Run()
}
}

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);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -625,8 +625,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact

// Ask the metadata manager
// if we have any dependencies due to presence of the EEType.
bool isFullType = factory.MaximallyConstructableType(_type) == this;
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type, isFullType);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type);

if (_type is MetadataType mdType)
ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencies, factory, mdType.Module);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
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, isFullType: true);
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type);

return dependencyList;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -458,12 +458,7 @@ private void CreateNodeCaches()

_typesWithMetadata = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: true);
});

_typesWithMetadataWithoutCustomAttributes = new NodeCache<MetadataType, TypeMetadataNode>(type =>
{
return new TypeMetadataNode(type, includeCustomAttributes: false);
return new TypeMetadataNode(type);
});

_methodsWithMetadata = new NodeCache<MethodDesc, MethodMetadataNode>(method =>
Expand DownExpand Up@@ -1161,16 +1156,6 @@ internal TypeMetadataNode TypeMetadata(MetadataType type)
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)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,13 +24,11 @@ namespace ILCompiler.DependencyAnalysis
internal sealed class TypeMetadataNode : DependencyNodeCore<NodeFactory>
{
private readonly MetadataType _type;
private readonly bool _includeCustomAttributes;

public TypeMetadataNode(MetadataType type, bool includeCustomAttributes)
public TypeMetadataNode(MetadataType type)
{
Debug.Assert(type.IsTypeDefinition);
_type = type;
_includeCustomAttributes = includeCustomAttributes;
}

public MetadataType Type => _type;
Expand All@@ -39,21 +37,13 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
{
DependencyList dependencies = new DependencyList();

if (_includeCustomAttributes)
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));
CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type));

DefType containingType = _type.ContainingType;
if (containingType != null)
{
TypeMetadataNode metadataNode = _includeCustomAttributes
? factory.TypeMetadata((MetadataType)containingType)
: factory.TypeMetadataWithoutCustomAttributes((MetadataType)containingType);
dependencies.Add(metadataNode, "Containing type of a reflectable type");
}
dependencies.Add(factory.TypeMetadata((MetadataType)containingType), "Containing type of a reflectable type");
else
{
dependencies.Add(factory.ModuleMetadata(_type.Module), "Containing module of a reflectable type");
}

var mdManager = (UsageBasedMetadataManager)factory.MetadataManager;

Expand DownExpand Up@@ -110,7 +100,7 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
/// 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, bool isFullType = true)
public static void GetMetadataDependencies(ref DependencyList dependencies, NodeFactory nodeFactory, TypeDesc type, string reason)
{
MetadataManager mdManager = nodeFactory.MetadataManager;

Expand All@@ -120,13 +110,13 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
case TypeFlags.SzArray:
case TypeFlags.ByRef:
case TypeFlags.Pointer:
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason);
break;
case TypeFlags.FunctionPointer:
var pointerType = (FunctionPointerType)type;
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason);
foreach (TypeDesc paramType in pointerType.Signature)
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason);
break;

case TypeFlags.SignatureMethodVariable:
Expand All@@ -136,30 +126,35 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
default:
Debug.Assert(type.IsDefType);

var typeDefinition = (MetadataType)type.GetTypeDefinition();
TypeDesc typeDefinition = 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, isFullType);
GetMetadataDependencies(ref dependencies, nodeFactory, typeArg, reason);
}
}

if (mdManager.CanGenerateMetadata(typeDefinition))
else
{
dependencies ??= new DependencyList();
TypeMetadataNode node = isFullType
? nodeFactory.TypeMetadata(typeDefinition)
: nodeFactory.TypeMetadataWithoutCustomAttributes(typeDefinition);
dependencies.Add(node, reason);
if (mdManager.CanGenerateMetadata((MetadataType)type))
{
dependencies ??= new DependencyList();
dependencies.Add(nodeFactory.TypeMetadata((MetadataType)type), reason);
}
}
break;
}
}

protected override string GetName(NodeFactory factory)
{
return $"Reflectable type: {_type}{(!_includeCustomAttributes ? " (No custom attributes)" : "")}";
return "Reflectable type: " + _type.ToString();
}

protected override void OnMarked(NodeFactory factory)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,13 +478,13 @@ protected virtual void GetMetadataDependenciesDueToReflectability(ref Dependency
/// <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, bool isFullType)
public virtual void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
MetadataCategory category = GetMetadataCategory(type);

if ((category & MetadataCategory.Description) != 0)
{
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type, isFullType);
GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type);
}
}

Expand All@@ -493,7 +493,7 @@ internal virtual void GetDependenciesDueToModuleUse(ref DependencyList dependenc
// MetadataManagers can override this to provide additional dependencies caused by using a module
}

protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
// 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
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -271,9 +271,9 @@ internal override void GetDependenciesDueToModuleUse(ref DependencyList dependen
}
}

protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type", isFullType);
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type");

if (type.IsDelegate)
{
Expand DownExpand Up@@ -385,9 +385,9 @@ private static bool IsTrimmableAssembly(ModuleDesc assembly)
return false;
}

public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, bool isFullType)
public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type, isFullType);
base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type);

DataflowAnalyzedTypeDefinitionNode.GetDependencies(ref dependencies, factory, FlowAnnotations, type);
}
Expand DownExpand Up@@ -970,7 +970,7 @@ public bool GeneratesMetadata(MethodDesc methodDef)

public bool GeneratesMetadata(MetadataType typeDef)
{
return _factory.TypeMetadata(typeDef).Marked || _factory.TypeMetadataWithoutCustomAttributes(typeDef).Marked;
return _factory.TypeMetadata(typeDef).Marked;
}

public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle)
Expand Down
30 changes: 30 additions & 0 deletions src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -67,6 +67,7 @@ private static int Main()
TestByRefTypeLoad.Run();
TestGenericLdtoken.Run();
TestAbstractGenericLdtoken.Run();
TestTypeHandlesVisibleFromIDynamicInterfaceCastable.Run();

//
// Mostly functionality tests
Expand DownExpand Up@@ -2457,6 +2458,35 @@ public static void Run()
}
}

class TestTypeHandlesVisibleFromIDynamicInterfaceCastable
{
class MyAttribute : Attribute { }

[My]
interface IUnusedInterface { }

class Foo : IDynamicInterfaceCastable
{
public RuntimeTypeHandle GetInterfaceImplementation(RuntimeTypeHandle interfaceType) => throw new NotImplementedException();

public bool IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)
{
Type t = Type.GetTypeFromHandle(interfaceType);
if (t.GetCustomAttribute<MyAttribute>() == null)
throw new Exception();

return true;
}
}

public static void Run()
{
object myObject = new Foo();
if (myObject is not IUnusedInterface)
throw new Exception();
}
}

class TestEntryPoint
{
public static void Run()
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,7 +21,6 @@ public static int Run()
TestStaticVirtualMethodOptimizations.Run();
TestTypeEquals.Run();
TestBranchesInGenericCodeRemoval.Run();
TestLimitedMetadataBlobs.Run();

return 100;
}
Expand DownExpand Up@@ -379,51 +378,6 @@ public static void Run()
}
}

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);
Expand Down