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
13 changes: 13 additions & 0 deletions src/coreclr/src/tools/Common/Compiler/TypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,19 @@ public static bool IsArrayAddressMethod(this MethodDesc method)
return arrayMethod != null && arrayMethod.Kind == ArrayMethodKind.Address;
}


/// <summary>
/// Returns true if '<paramref name="method"/>' is one of the special methods on multidimensional array types (set, get, address).
/// </summary>
public static bool IsArrayMethod(this MethodDesc method)
{
var arrayMethod = method as ArrayMethod;
return arrayMethod != null && (arrayMethod.Kind == ArrayMethodKind.Address ||
arrayMethod.Kind == ArrayMethodKind.Get ||
arrayMethod.Kind == ArrayMethodKind.Set ||
arrayMethod.Kind == ArrayMethodKind.Ctor);
}

/// <summary>
/// Gets a value indicating whether this type has any generic virtual methods.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;

using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
Expand Down Expand Up @@ -441,11 +442,18 @@ public void EmitMethodSignature(

// Owner type is needed for type specs to instantiating stubs or generics with signature variables still present
if (!method.Method.OwningType.IsDefType &&
((flags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_InstantiatingStub) != 0 || method.Method.OwningType.ContainsSignatureVariables())
|| method.Method.IsArrayAddressMethod())
((flags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_InstantiatingStub) != 0 || method.Method.OwningType.ContainsSignatureVariables()))
{
flags |= (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_OwnerType;
}
else if (method.Method.IsArrayMethod())
{
var memberRefMethod = method.Token.Module.GetMethod(MetadataTokens.EntityHandle((int)method.Token.Token));
if (memberRefMethod.OwningType != method.Method.OwningType)
{
flags |= (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_OwnerType;
}
}

EmitUInt(flags);
if ((flags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_OwnerType) != 0)
Expand Down
6 changes: 0 additions & 6 deletions src/coreclr/tests/issues.targets
Original file line number Diff line number Diff line change
Expand Up @@ -920,9 +920,6 @@
<ExcludeList Include="$(XunitTestBinBase)/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded/*">
<Issue>https://github.com/dotnet/runtime/issues/38096</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/JIT/Generics/Arrays/TypeParameters/MultiDim/**/*">
<Issue>https://github.com/dotnet/runtime/issues/38260</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/JIT/Methodical/tailcall_v4/hijacking/*">
<Issue>https://github.com/dotnet/runtime/issues/7597</Issue>
</ExcludeList>
Expand Down Expand Up @@ -959,9 +956,6 @@
<ExcludeList Include="$(XunitTestBinBase)/Loader/binding/tracing/BinderTracingTest.Basic/*">
<Issue>https://github.com/dotnet/runtime/issues/38290</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Loader/classloader/regressions/Dev12_518401/dev12_518401/dev12_518401/*">
<Issue>https://github.com/dotnet/runtime/issues/38260</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/tracing/tracevalidation/tracelogging/tracelogging/*">
<Issue>https://github.com/dotnet/runtime/issues/32728</Issue>
</ExcludeList>
Expand Down
141 changes: 141 additions & 0 deletions src/tests/readytorun/crossgen2/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,145 @@ private static bool GenericLdtokenTest()
return true;
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static bool CheckArrayVal<T>(ref T refVal, T testValue) where T:IEquatable<T>
{
return refVal.Equals(testValue);
}

struct SomeLargeStruct : IEquatable<SomeLargeStruct>
{
public SomeLargeStruct(int _xVal)
{
x = _xVal;
y = 0;
z = 0;
w = 0;
}
public int x;
public int y;
public int z;
public int w;

public bool Equals(SomeLargeStruct other)
{
return (x == other.x) && (y == other.y) && (z == other.z) && (w == other.w);
}
public override bool Equals(object other)
{
return Equals((SomeLargeStruct)other);
}

public override int GetHashCode() { return x; }
}

class SomeClass : IEquatable<SomeClass>
{
public SomeClass(int _xVal)
{
x = _xVal;
y = 0;
z = 0;
w = 0;
}
public int x;
public int y;
public int z;
public int w;

public bool Equals(SomeClass other)
{
return (x == other.x) && (y == other.y) && (z == other.z) && (w == other.w);
}
public override bool Equals(object other)
{
return Equals((SomeClass)other);
}

public override int GetHashCode() { return x; }
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static bool DoLargeStructMDArrayTest(SomeLargeStruct testValue)
{
SomeLargeStruct[,] array = new SomeLargeStruct[2,2];
array[0,0] = testValue;
if (!CheckArrayVal(ref array[0,0], testValue))
{
return false;
}
if (!testValue.Equals(array[0,0]))
{
return false;
}

return true;
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static bool DoGenericArrayTest<T> (T testValue) where T:IEquatable<T>
{
T[,] array = new T[2,2];
array[0,0] = testValue;
if (!CheckArrayVal(ref array[0,0], testValue))
{
return false;
}
if (!testValue.Equals(array[0,0]))
{
return false;
}

return true;
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static bool TestGenericMDArrayBehavior()
{
if (!DoGenericArrayTest<int>(42))
{
return false;
}

if (!DoGenericArrayTest<SomeClass>(new SomeClass(42)))
{
return false;
}

SomeLargeStruct testStruct = new SomeLargeStruct(42);
if (!DoGenericArrayTest<SomeLargeStruct>(testStruct))
{
return false;
}

if (!DoLargeStructMDArrayTest(testStruct))
{
return false;
}

return true;
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static bool ArrayLdtokenTests()
{
// We're testing that mapping from ldtoken to RuntimeMethodHandle works for various ways that
// ldtokens can be referenced (either via a generic token, or not.
// (there are slightly different codepaths in crossgen for this)
// Incorrect encoding will trigger a BadImageFormatException
RuntimeMethodHandle rmhCtor1 = default(RuntimeMethodHandle);
RuntimeMethodHandle rmhCtor2 = default(RuntimeMethodHandle);
RuntimeMethodHandle rmhSet = default(RuntimeMethodHandle);
RuntimeMethodHandle rmhGet = default(RuntimeMethodHandle);
RuntimeMethodHandle rmhAddress = default(RuntimeMethodHandle);
HelperGenericILCode<string>.LdTokenArrayMethods(ref rmhCtor1, ref rmhCtor2, ref rmhSet, ref rmhGet, ref rmhAddress);
HelperGenericILCode<object>.LdTokenArrayMethods(ref rmhCtor1, ref rmhCtor2, ref rmhSet, ref rmhGet, ref rmhAddress);
HelperILCode.LdTokenArrayMethodsInt(ref rmhCtor1, ref rmhCtor2, ref rmhSet, ref rmhGet, ref rmhAddress);
HelperILCode.LdTokenArrayMethodsString(ref rmhCtor1, ref rmhCtor2, ref rmhSet, ref rmhGet, ref rmhAddress);

return true;
}

public static int Main(string[] args)
{
_passedTests = new List<string>();
Expand Down Expand Up @@ -1691,6 +1830,8 @@ public static int Main(string[] args)
RunTest("ExplicitlySizedStructTest", ExplicitlySizedStructTest());
RunTest("ExplicitlySizedClassTest", ExplicitlySizedClassTest());
RunTest("GenericLdtokenTest", GenericLdtokenTest());
RunTest("ArrayLdtokenTests", ArrayLdtokenTests());
RunTest("TestGenericMDArrayBehavior", TestGenericMDArrayBehavior());

File.Delete(TextFileName);

Expand Down
88 changes: 88 additions & 0 deletions src/tests/readytorun/crossgen2/helperildll.il
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,55 @@
ret
}

.method public hidebysig static void LdTokenArrayMethodsInt(valuetype[mscorlib]System.RuntimeMethodHandle& ctor, valuetype[mscorlib]System.RuntimeMethodHandle& ctor2, valuetype[mscorlib]System.RuntimeMethodHandle& set, valuetype[mscorlib]System.RuntimeMethodHandle& get, valuetype[mscorlib]System.RuntimeMethodHandle& address)
{
ldarg 0
ldtoken method instance void int32[,]::.ctor(int32, int32, int32, int32)
stobj valuetype[mscorlib]System.RuntimeMethodHandle

ldarg 1
ldtoken method instance void int32[,]::.ctor(int32, int32)
stobj valuetype[mscorlib]System.RuntimeMethodHandle

ldarg 2
ldtoken method instance void int32[,]::Set(int32, int32, int32)
stobj valuetype[mscorlib]System.RuntimeMethodHandle

ldarg 3
ldtoken method instance int32 int32[,]::Get(int32, int32)
stobj valuetype[mscorlib]System.RuntimeMethodHandle

ldarg 4
ldtoken method instance int32& int32[,]::Address(int32, int32)
stobj valuetype[mscorlib]System.RuntimeMethodHandle
ret
}

.method public hidebysig static void LdTokenArrayMethodsString(valuetype[mscorlib]System.RuntimeMethodHandle& ctor, valuetype[mscorlib]System.RuntimeMethodHandle& ctor2, valuetype[mscorlib]System.RuntimeMethodHandle& set, valuetype[mscorlib]System.RuntimeMethodHandle& get, valuetype[mscorlib]System.RuntimeMethodHandle& address)
{
ldarg 0
ldtoken method instance void string[,]::.ctor(int32, int32, int32, int32)
stobj valuetype[mscorlib]System.RuntimeMethodHandle

ldarg 1
ldtoken method instance void string[,]::.ctor(int32, int32)
stobj valuetype[mscorlib]System.RuntimeMethodHandle

ldarg 2
ldtoken method instance void string[,]::Set(int32, int32, string)
stobj valuetype[mscorlib]System.RuntimeMethodHandle

ldarg 3
ldtoken method instance string string[,]::Get(int32, int32)
stobj valuetype[mscorlib]System.RuntimeMethodHandle

ldarg 4
ldtoken method instance string& string[,]::Address(int32, int32)
stobj valuetype[mscorlib]System.RuntimeMethodHandle
ret
}


.method public hidebysig static valuetype[mscorlib]System.RuntimeMethodHandle ForceStuffToBeCompiled() cil managed noinlining
{
call valuetype[mscorlib]System.RuntimeMethodHandle class HelperGenericILCode`1<object>::GetGenericFunctionMethodHandle<valuetype [helperdll]GenericStructForLdtoken`1<string>>()
Expand All @@ -50,6 +99,22 @@
call valuetype[mscorlib]System.RuntimeMethodHandle HelperILCode::GetGenericFunctionMethodHandle<string>()
ret
}
.method public hidebysig static void ForceStuffToBeCompiled3(valuetype[mscorlib]System.RuntimeMethodHandle& ctor, valuetype[mscorlib]System.RuntimeMethodHandle& ctor2, valuetype[mscorlib]System.RuntimeMethodHandle& set, valuetype[mscorlib]System.RuntimeMethodHandle& get, valuetype[mscorlib]System.RuntimeMethodHandle& address) cil managed noinlining
{
ldarg 0
ldarg 1
ldarg 2
ldarg 3
ldarg 4
call void class HelperGenericILCode`1<object>::LdTokenArrayMethods(valuetype[mscorlib]System.RuntimeMethodHandle&, valuetype[mscorlib]System.RuntimeMethodHandle&, valuetype[mscorlib]System.RuntimeMethodHandle&, valuetype[mscorlib]System.RuntimeMethodHandle&, valuetype[mscorlib]System.RuntimeMethodHandle&)
ldarg 0
ldarg 1
ldarg 2
ldarg 3
ldarg 4
call void class HelperGenericILCode`1<int32>::LdTokenArrayMethods(valuetype[mscorlib]System.RuntimeMethodHandle& ctor, valuetype[mscorlib]System.RuntimeMethodHandle& ctor2, valuetype[mscorlib]System.RuntimeMethodHandle& set, valuetype[mscorlib]System.RuntimeMethodHandle& get, valuetype[mscorlib]System.RuntimeMethodHandle& address)
ret
}
}

.class auto ansi public beforefieldinit HelperGenericILCode`1<T>
Expand All @@ -66,4 +131,27 @@
ldtoken method instance int32 valuetype [helperdll]GenericStructForLdtoken`1<!0>::GenericFunction<!!0>(!0, !!0, string, int32)
ret
}
.method public hidebysig static void LdTokenArrayMethods(valuetype[mscorlib]System.RuntimeMethodHandle& ctor, valuetype[mscorlib]System.RuntimeMethodHandle& ctor2, valuetype[mscorlib]System.RuntimeMethodHandle& set, valuetype[mscorlib]System.RuntimeMethodHandle& get, valuetype[mscorlib]System.RuntimeMethodHandle& address)
{
ldarg 0
ldtoken method instance void !0[,]::.ctor(int32, int32, int32, int32)
stobj valuetype[mscorlib]System.RuntimeMethodHandle

ldarg 1
ldtoken method instance void !0[,]::.ctor(int32, int32)
stobj valuetype[mscorlib]System.RuntimeMethodHandle

ldarg 2
ldtoken method instance void !0[,]::Set(int32, int32, !0)
stobj valuetype[mscorlib]System.RuntimeMethodHandle

ldarg 3
ldtoken method instance !0 !0[,]::Get(int32, int32)
stobj valuetype[mscorlib]System.RuntimeMethodHandle

ldarg 4
ldtoken method instance !0& !0[,]::Address(int32, int32)
stobj valuetype[mscorlib]System.RuntimeMethodHandle
ret
}
}