Skip to content

Commit a73abd2

Browse files
Differentiate MethodTables that are/aren't visible to reflection
Fixes #112029
1 parent 69facbc commit a73abd2

File tree

7 files changed

+87
-20
lines changed

7 files changed

+87
-20
lines changed

src/coreclr/tools/Common/Compiler/DevirtualizationManager.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ protected virtual MethodDesc ResolveVirtualMethod(MethodDesc declMethod, DefType
202202
}
203203

204204
#if !READYTORUN
205+
public virtual bool IsGenericDefinitionMethodTableReflectionVisible(TypeDesc type) => true;
206+
205207
/// <summary>
206208
/// Gets a value indicating whether it might be possible to obtain a constructed type data structure for the given type
207209
/// in this compilation (i.e. is it possible to reference a constructed MethodTable symbol for this).

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ public static bool CreationAllowed(TypeDesc type)
121121

122122
default:
123123
// Generic definition EETypes can't be allocated
124-
if (type.IsGenericDefinition)
125-
return false;
124+
//if (type.IsGenericDefinition)
125+
// return false;
126126

127127
// Full MethodTable of System.Canon should never be used.
128128
if (type.IsCanonicalDefinitionType(CanonicalFormKind.Any))

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,8 @@ protected void OutputGenericInstantiationDetails(NodeFactory factory, ref Object
11351135
{
11361136
if (!_type.IsTypeDefinition)
11371137
{
1138-
IEETypeNode typeDefNode = factory.NecessaryTypeSymbol(_type.GetTypeDefinition());
1138+
IEETypeNode typeDefNode = factory.MaximallyConstructableType(_type) == this ?
1139+
factory.ConstructedTypeSymbol(_type.GetTypeDefinition()) : factory.NecessaryTypeSymbol(_type.GetTypeDefinition());
11391140
if (factory.Target.SupportsRelativePointers)
11401141
objData.EmitReloc(typeDefNode, RelocType.IMAGE_REL_BASED_RELPTR32);
11411142
else
@@ -1312,7 +1313,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
13121313
// If the whole program view contains a reference to a preallocated RuntimeType
13131314
// instance for this type, generate a reference to it.
13141315
// Otherwise, generate as zero to save size.
1315-
if (!_type.Type.IsCanonicalSubtype(CanonicalFormKind.Any)
1316+
if (!relocsOnly
1317+
&& !_type.Type.IsCanonicalSubtype(CanonicalFormKind.Any)
13161318
&& _type.GetFrozenRuntimeTypeNode(factory) is { Marked: true } runtimeTypeObject)
13171319
{
13181320
builder.EmitPointerReloc(runtimeTypeObject);

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,23 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using Internal.Runtime;
5+
using Internal.Text;
56
using Internal.TypeSystem;
67

78
using Debug = System.Diagnostics.Debug;
89

910
namespace ILCompiler.DependencyAnalysis
1011
{
11-
internal sealed class GenericDefinitionEETypeNode : EETypeNode
12+
internal abstract class GenericDefinitionEETypeNode : EETypeNode
1213
{
1314
public GenericDefinitionEETypeNode(NodeFactory factory, TypeDesc type) : base(factory, type)
1415
{
1516
Debug.Assert(type.IsGenericDefinition);
1617
}
1718

18-
public override bool ShouldSkipEmittingObjectNode(NodeFactory factory)
19+
public override ISymbolNode NodeForLinkage(NodeFactory factory)
1920
{
20-
return false;
21-
}
22-
23-
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
24-
{
25-
DependencyList dependencyList = null;
26-
27-
// Ask the metadata manager if we have any dependencies due to the presence of the EEType.
28-
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type);
29-
30-
return dependencyList;
21+
return factory.NecessaryTypeSymbol(_type);
3122
}
3223

3324
protected override ObjectData GetDehydratableData(NodeFactory factory, bool relocsOnly = false)
@@ -63,7 +54,57 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo
6354

6455
return dataBuilder.ToObjectData();
6556
}
57+
}
58+
59+
internal sealed class ReflectionInvisibleGenericDefinitionEETypeNode : GenericDefinitionEETypeNode
60+
{
61+
public ReflectionInvisibleGenericDefinitionEETypeNode(NodeFactory factory, TypeDesc type) : base(factory, type)
62+
{
63+
}
64+
65+
public override bool ShouldSkipEmittingObjectNode(NodeFactory factory)
66+
{
67+
return factory.ConstructedTypeSymbol(_type).Marked;
68+
}
69+
70+
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
71+
{
72+
return new DependencyList();
73+
}
74+
75+
public override int ClassCode => -287423988;
76+
}
77+
78+
internal sealed class ReflectionVisibleGenericDefinitionEETypeNode : GenericDefinitionEETypeNode
79+
{
80+
public ReflectionVisibleGenericDefinitionEETypeNode(NodeFactory factory, TypeDesc type) : base(factory, type)
81+
{
82+
}
83+
84+
public override bool ShouldSkipEmittingObjectNode(NodeFactory factory)
85+
{
86+
return false;
87+
}
88+
89+
protected override FrozenRuntimeTypeNode GetFrozenRuntimeTypeNode(NodeFactory factory)
90+
{
91+
return factory.SerializedConstructedRuntimeTypeObject(_type);
92+
}
93+
94+
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler) + " reflection visible";
95+
96+
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
97+
{
98+
var dependencyList = new DependencyList();
99+
100+
dependencyList.Add(factory.NecessaryTypeSymbol(_type), "Reflection invisible type for a visible type");
101+
102+
// Ask the metadata manager if we have any dependencies due to the presence of the EEType.
103+
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type);
104+
105+
return dependencyList;
106+
}
66107

67-
public override int ClassCode => -160325006;
108+
public override int ClassCode => 983279111;
68109
}
69110
}

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ private IEETypeNode CreateNecessaryTypeNode(TypeDesc type)
591591
{
592592
if (type.IsGenericDefinition)
593593
{
594-
return new GenericDefinitionEETypeNode(this, type);
594+
return new ReflectionInvisibleGenericDefinitionEETypeNode(this, type);
595595
}
596596
else if (type.IsCanonicalDefinitionType(CanonicalFormKind.Any))
597597
{
@@ -620,7 +620,11 @@ private IEETypeNode CreateConstructedTypeNode(TypeDesc type)
620620

621621
if (_compilationModuleGroup.ContainsType(type))
622622
{
623-
if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
623+
if (type.IsGenericDefinition)
624+
{
625+
return new ReflectionVisibleGenericDefinitionEETypeNode(this, type);
626+
}
627+
else if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
624628
{
625629
return new CanonicalEETypeNode(this, type);
626630
}

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ public override DictionaryLayoutNode GetLayout(TypeSystemEntity methodOrType)
436436
private sealed class ScannedDevirtualizationManager : DevirtualizationManager
437437
{
438438
private HashSet<TypeDesc> _constructedMethodTables = new HashSet<TypeDesc>();
439+
private HashSet<TypeDesc> _reflectionVisibleGenericDefinitionMethodTables = new HashSet<TypeDesc>();
439440
private HashSet<TypeDesc> _canonConstructedMethodTables = new HashSet<TypeDesc>();
440441
private HashSet<TypeDesc> _canonConstructedTypes = new HashSet<TypeDesc>();
441442
private HashSet<TypeDesc> _unsealedTypes = new HashSet<TypeDesc>();
@@ -456,6 +457,11 @@ public ScannedDevirtualizationManager(NodeFactory factory, ImmutableArray<Depend
456457
_generatedVirtualMethods.Add(virtualMethodBody.Method);
457458
}
458459

460+
if (node is ReflectionVisibleGenericDefinitionEETypeNode reflectionVisibleMT)
461+
{
462+
_reflectionVisibleGenericDefinitionMethodTables.Add(reflectionVisibleMT.Type);
463+
}
464+
459465
TypeDesc type = node switch
460466
{
461467
ConstructedEETypeNode eetypeNode => eetypeNode.Type,
@@ -736,6 +742,12 @@ public override bool CanReferenceConstructedTypeOrCanonicalFormOfType(TypeDesc t
736742
return _constructedMethodTables.Contains(type) || _canonConstructedMethodTables.Contains(type);
737743
}
738744

745+
public override bool IsGenericDefinitionMethodTableReflectionVisible(TypeDesc type)
746+
{
747+
Debug.Assert(type.IsGenericDefinition);
748+
return _reflectionVisibleGenericDefinitionMethodTables.Contains(type);
749+
}
750+
739751
public override TypeDesc[] GetImplementingClasses(TypeDesc type)
740752
{
741753
if (_disqualifiedTypes.Contains(type))

src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ public override IEETypeNode NecessaryTypeSymbolIfPossible(TypeDesc type)
7777
if (canPotentiallyConstruct)
7878
return _nodeFactory.MaximallyConstructableType(type);
7979

80+
if (type.IsGenericDefinition && NodeFactory.DevirtualizationManager.IsGenericDefinitionMethodTableReflectionVisible(type))
81+
return _nodeFactory.ConstructedTypeSymbol(type);
82+
8083
return _nodeFactory.NecessaryTypeSymbol(type);
8184
}
8285

@@ -87,6 +90,9 @@ public FrozenRuntimeTypeNode NecessaryRuntimeTypeIfPossible(TypeDesc type)
8790
if (canPotentiallyConstruct)
8891
return _nodeFactory.SerializedMaximallyConstructableRuntimeTypeObject(type);
8992

93+
if (type.IsGenericDefinition && NodeFactory.DevirtualizationManager.IsGenericDefinitionMethodTableReflectionVisible(type))
94+
return _nodeFactory.SerializedConstructedRuntimeTypeObject(type);
95+
9096
return _nodeFactory.SerializedNecessaryRuntimeTypeObject(type);
9197
}
9298

0 commit comments

Comments
 (0)