Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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 number Diff line number Diff line change
Expand Up @@ -1252,9 +1252,20 @@ protected void OutputGenericInstantiationDetails(NodeFactory factory, ref Object
else
objData.EmitPointerReloc(typeDefNode);

ISymbolNode compositionNode = _type.Instantiation.Length > 1
? factory.GenericComposition(_type.Instantiation)
: factory.NecessaryTypeSymbol(_type.Instantiation[0]);
ISymbolNode compositionNode;

if (this == factory.MaximallyConstructableType(_type))
{
compositionNode = _type.Instantiation.Length > 1
? factory.ConstructedGenericComposition(_type.Instantiation)
: factory.MaximallyConstructableType(_type.Instantiation[0]);
}
else
{
compositionNode = _type.Instantiation.Length > 1
? factory.GenericComposition(_type.Instantiation)
: factory.NecessaryTypeSymbol(_type.Instantiation[0]);
}

if (factory.Target.SupportsRelativePointers)
objData.EmitReloc(compositionNode, RelocType.IMAGE_REL_BASED_RELPTR32);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ namespace ILCompiler.DependencyAnalysis
/// </summary>
public class GenericCompositionNode : ObjectNode, ISymbolDefinitionNode
{
private Instantiation _details;
private readonly Instantiation _details;
private readonly bool _constructed;

internal GenericCompositionNode(Instantiation details)
internal GenericCompositionNode(Instantiation details, bool constructed)
{
_details = details;
_constructed = constructed;
}

public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => !_constructed && factory.ConstructedGenericComposition(_details).Marked;

public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append("__GenericInstance"u8);
Expand Down Expand Up @@ -62,10 +66,12 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)

foreach (var typeArg in _details)
{
IEETypeNode node = _constructed ? factory.MaximallyConstructableType(typeArg) : factory.NecessaryTypeSymbol(typeArg);

if (useRelativePointers)
builder.EmitReloc(factory.NecessaryTypeSymbol(typeArg), RelocType.IMAGE_REL_BASED_RELPTR32);
builder.EmitReloc(node, RelocType.IMAGE_REL_BASED_RELPTR32);
else
builder.EmitPointerReloc(factory.NecessaryTypeSymbol(typeArg));
builder.EmitPointerReloc(node);
}

return builder.ToObjectData();
Expand All @@ -81,6 +87,10 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer
if (compare != 0)
return compare;

compare = _constructed.CompareTo(otherComposition._constructed);
if (compare != 0)
return compare;

for (int i = 0; i < _details.Length; i++)
{
compare = comparer.Compare(_details[i], otherComposition._details[i]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,12 @@ private void CreateNodeCaches()

_genericCompositions = new NodeCache<Instantiation, GenericCompositionNode>((Instantiation details) =>
{
return new GenericCompositionNode(details);
return new GenericCompositionNode(details, constructed: false);
});

_constructedGenericCompositions = new NodeCache<Instantiation, GenericCompositionNode>((Instantiation details) =>
{
return new GenericCompositionNode(details, constructed: true);
});

_genericVariances = new NodeCache<GenericVarianceDetails, GenericVarianceNode>((GenericVarianceDetails details) =>
Expand Down Expand Up @@ -847,6 +852,13 @@ internal ISymbolNode GenericComposition(Instantiation details)
return _genericCompositions.GetOrAdd(details);
}

private NodeCache<Instantiation, GenericCompositionNode> _constructedGenericCompositions;

internal ISymbolNode ConstructedGenericComposition(Instantiation details)
{
return _constructedGenericCompositions.GetOrAdd(details);
}

private NodeCache<GenericVarianceDetails, GenericVarianceNode> _genericVariances;

internal ISymbolNode GenericVariance(GenericVarianceDetails details)
Expand Down
43 changes: 42 additions & 1 deletion src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ private static int Main()
TestAbstractGenericLdtoken.Run();
TestTypeHandlesVisibleFromIDynamicInterfaceCastable.Run();
TestCompilerGeneratedCode.Run();
Test105034Regression.Run();


//
// Mostly functionality tests
Expand Down Expand Up @@ -713,6 +715,45 @@ public static void Run()
}
}

class Test105034Regression
{
interface IFactory
{
object Make();
}

interface IOption<T> where T : new() { }

class OptionFactory<T> : IFactory where T : class, new()
{
public object Make() => new T();
}

class Gen<T> { }

struct Atom { }

static Type Register<T>() => typeof(T).GetGenericArguments()[0];
static IFactory Activate(Type t) => (IFactory)Activator.CreateInstance(typeof(OptionFactory<>).MakeGenericType(t));

public static void Run()
{
Console.WriteLine(nameof(Test105034Regression));

Wrap<Atom>();

static void Wrap<T>()
{

Type t = Register();
static Type Register() => Register<IOption<Gen<T>>>();

var f = Activate(t);
f.Make();
}
}
}

class TestCreateDelegate
{
internal class Greeter
Expand Down Expand Up @@ -2485,7 +2526,7 @@ class TestMdArrayLoad2
{
class Atom { }

public static object MakeMdArray<T>() => new T[1,1,1];
public static object MakeMdArray<T>() => new T[1, 1, 1];

public static void Run()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,40 +268,13 @@ public static void Run()
if (!o.ToString().Contains(nameof(Marker1)))
throw new Exception();
}

// ...but not nullable...
{
Array arr = new Nullable<NeverAllocated2>[1];
arr.GetValue(0);
ThrowIfPresent(typeof(TestArrayElementTypeOperations), nameof(Marker2));
}


// ...or reference type element types
{
Array arr = new NeverAllocated3[1];
arr.GetValue(0);
ThrowIfPresent(typeof(TestArrayElementTypeOperations), nameof(Marker3));
}
}

class Marker1 { }
struct NeverAllocated1
{
public override string ToString() => typeof(Marker1).ToString();
}

class Marker2 { }
struct NeverAllocated2
{
public override string ToString() => typeof(Marker2).ToString();
}

class Marker3 { }
class NeverAllocated3
{
public override string ToString() => typeof(Marker3).ToString();
}
}

class TestStaticVirtualMethodOptimizations
Expand Down