diff options
author | Fadi Hanna <fadim@microsoft.com> | 2016-08-03 18:00:49 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-08-03 18:00:49 -0700 |
commit | 693fff99049bc7d63459b2c444237ca532036b47 (patch) | |
tree | b6c9b7fdc517276f1480f6a9deb23c506ffc8fdd /tests/src/readytorun | |
parent | d18ddfda61efdfe4521d2dce816fa01021bf26a8 (diff) | |
download | coreclr-693fff99049bc7d63459b2c444237ca532036b47.tar.gz coreclr-693fff99049bc7d63459b2c444237ca532036b47.tar.bz2 coreclr-693fff99049bc7d63459b2c444237ca532036b47.zip |
Adding Support for FieldDescSlot generic dictionary entries for R2R generic code. (#6200)
This enables generic code with ldtoken instructions for fields on generic types to be compiled into R2R.
This change makes newer versions of the runtime compatible with older version R2R images,
but not vice-versa. Therefore, the major version is increased to 2 with this change.
This change adds more encodings to a R2R image without changing the format of any previously encoded
entity, and is backwards compatible.
Diffstat (limited to 'tests/src/readytorun')
-rw-r--r-- | tests/src/readytorun/fieldgetter.il | 215 | ||||
-rw-r--r-- | tests/src/readytorun/fieldgetter.ilproj | 36 | ||||
-rw-r--r-- | tests/src/readytorun/main.cs | 40 | ||||
-rw-r--r-- | tests/src/readytorun/mainv1.csproj | 3 | ||||
-rw-r--r-- | tests/src/readytorun/mainv2.csproj | 3 | ||||
-rw-r--r-- | tests/src/readytorun/test.cs | 26 |
6 files changed, 323 insertions, 0 deletions
diff --git a/tests/src/readytorun/fieldgetter.il b/tests/src/readytorun/fieldgetter.il new file mode 100644 index 0000000000..c2eff200af --- /dev/null +++ b/tests/src/readytorun/fieldgetter.il @@ -0,0 +1,215 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.assembly extern System.Console { } +.assembly extern mscorlib { } +.assembly extern test { } + +.assembly fieldgetter { } +.module fieldgetter.dll + +//========================================================================================== + +.class public auto ansi beforefieldinit Gen`1<T> + extends [mscorlib]System.Object +{ + .field public int32 m_Field1 + .field public string m_Field2 + .field public !T m_Field3 + .field public static class [mscorlib]System.Collections.Generic.List`1<!T> m_Field4 + .field public static valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<!T,int32> m_Field5 + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method Gen`1::.ctor +} // end of class Gen`1 + +.class interface public abstract auto ansi IFieldGetter +{ + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field1() cil managed + { + } // end of method IFieldGetter::GetGenT_Field1 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field2() cil managed + { + } // end of method IFieldGetter::GetGenT_Field2 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field3() cil managed + { + } // end of method IFieldGetter::GetGenT_Field3 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field4() cil managed + { + } // end of method IFieldGetter::GetGenT_Field4 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field5() cil managed + { + } // end of method IFieldGetter::GetGenT_Field5 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field1() cil managed + { + } // end of method IFieldGetter::GetGenDllT_Field1 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field2() cil managed + { + } // end of method IFieldGetter::GetGenDllT_Field2 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field3() cil managed + { + } // end of method IFieldGetter::GetGenDllT_Field3 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field4() cil managed + { + } // end of method IFieldGetter::GetGenDllT_Field4 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field5() cil managed + { + } // end of method IFieldGetter::GetGenDllT_Field5 + +} // end of class IFieldGetter + +.class public auto ansi beforefieldinit FieldGetter`1<T> + extends [mscorlib]System.Object + implements IFieldGetter +{ + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field1() cil managed + { + ldtoken field int32 class Gen`1<!0>::m_Field1 + ldtoken class Gen`1<!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenT_Field1 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field2() cil managed + { + ldtoken field string class Gen`1<!0>::m_Field2 + ldtoken class Gen`1<!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenT_Field2 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field3() cil managed + { + ldtoken field !0 class Gen`1<!0>::m_Field3 + ldtoken class Gen`1<!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenT_Field3 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field4() cil managed + { + ldtoken field class [mscorlib]System.Collections.Generic.List`1<!0> class Gen`1<!0>::m_Field4 + ldtoken class Gen`1<!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenT_Field4 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field5() cil managed + { + ldtoken field valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<!0,int32> class Gen`1<!0>::m_Field5 + ldtoken class Gen`1<!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenT_Field5 + + + + + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field1() cil managed + { + ldtoken field string class [test]MyGeneric`2<!0,!0>::m_Field1 + ldtoken class [test]MyGeneric`2<!0,!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenDllT_Field1 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field2() cil managed + { + ldtoken field !0 class [test]MyGeneric`2<!0,!0>::m_Field2 + ldtoken class [test]MyGeneric`2<!0,!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenDllT_Field2 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field3() cil managed + { + ldtoken field class [mscorlib]System.Collections.Generic.List`1<!0> class [test]MyGeneric`2<!0,!0>::m_Field3 + ldtoken class [test]MyGeneric`2<!0,!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenDllT_Field3 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field4() cil managed + { + ldtoken field valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<!0,int32> class [test]MyGeneric`2<!0,!0>::m_Field4 + ldtoken class [test]MyGeneric`2<!0,!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenDllT_Field4 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field5() cil managed + { + ldtoken field int32 class [test]MyGeneric`2<!0,!0>::m_Field5 + ldtoken class [test]MyGeneric`2<!0,!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenDllT_Field5 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method FieldGetter`1::.ctor + +} // end of class FieldGetter`1 + diff --git a/tests/src/readytorun/fieldgetter.ilproj b/tests/src/readytorun/fieldgetter.ilproj new file mode 100644 index 0000000000..0f6f6875fb --- /dev/null +++ b/tests/src/readytorun/fieldgetter.ilproj @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <AssemblyName>fieldgetter</AssemblyName> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp> + <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib> + <OutputType>Library</OutputType> + <CLRTestKind>SharedLibrary</CLRTestKind> + </PropertyGroup> + + <ItemGroup> + <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> + <Visible>False</Visible> + </CodeAnalysisDependentAssemblyPaths> + </ItemGroup> + + <ItemGroup> + <Compile Include="fieldgetter.il" /> + </ItemGroup> + + <ItemGroup> + <None Include="app.config" /> + </ItemGroup> + + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project> diff --git a/tests/src/readytorun/main.cs b/tests/src/readytorun/main.cs index b01702f7da..cce03b4586 100644 --- a/tests/src/readytorun/main.cs +++ b/tests/src/readytorun/main.cs @@ -379,6 +379,44 @@ class Program Func<string, object> idClosed = "World".OpenClosedDelegateTarget; Assert.AreEqual(idClosed("hey"), "World, hey"); } + + static void GenericLdtokenFieldsTest() + { + Func<FieldInfo, string> FieldFullName = (fi) => fi.FieldType + " " + fi.DeclaringType.ToString() + "::" + fi.Name; + + IFieldGetter getter1 = new FieldGetter<string>(); + IFieldGetter getter2 = new FieldGetter<object>(); + IFieldGetter getter3 = new FieldGetter<int>(); + + foreach (var instArg in new Type[]{typeof(String), typeof(object), typeof(int)}) + { + IFieldGetter getter = (IFieldGetter)Activator.CreateInstance(typeof(FieldGetter<>).MakeGenericType(instArg)); + + string expectedField1 = "System.Int32 Gen`1[???]::m_Field1".Replace("???", instArg.ToString()); + string expectedField2 = "System.String Gen`1[???]::m_Field2".Replace("???", instArg.ToString()); + string expectedField3 = "??? Gen`1[???]::m_Field3".Replace("???", instArg.ToString()); + string expectedField4 = "System.Collections.Generic.List`1[???] Gen`1[???]::m_Field4".Replace("???", instArg.ToString()); + string expectedField5 = "System.Collections.Generic.KeyValuePair`2[???,System.Int32] Gen`1[???]::m_Field5".Replace("???", instArg.ToString()); + + string expectedDllField1 = "System.String MyGeneric`2[???,???]::m_Field1".Replace("???", instArg.ToString()); + string expectedDllField2 = "??? MyGeneric`2[???,???]::m_Field2".Replace("???", instArg.ToString()); + string expectedDllField3 = "System.Collections.Generic.List`1[???] MyGeneric`2[???,???]::m_Field3".Replace("???", instArg.ToString()); + string expectedDllField4 = "System.Collections.Generic.KeyValuePair`2[???,System.Int32] MyGeneric`2[???,???]::m_Field4".Replace("???", instArg.ToString()); + string expectedDllField5 = "System.Int32 MyGeneric`2[???,???]::m_Field5".Replace("???", instArg.ToString()); + + Assert.AreEqual(expectedField1, FieldFullName(getter.GetGenT_Field1())); + Assert.AreEqual(expectedField2, FieldFullName(getter.GetGenT_Field2())); + Assert.AreEqual(expectedField3, FieldFullName(getter.GetGenT_Field3())); + Assert.AreEqual(expectedField4, FieldFullName(getter.GetGenT_Field4())); + Assert.AreEqual(expectedField5, FieldFullName(getter.GetGenT_Field5())); + + Assert.AreEqual(expectedDllField1, FieldFullName(getter.GetGenDllT_Field1())); + Assert.AreEqual(expectedDllField2, FieldFullName(getter.GetGenDllT_Field2())); + Assert.AreEqual(expectedDllField3, FieldFullName(getter.GetGenDllT_Field3())); + Assert.AreEqual(expectedDllField4, FieldFullName(getter.GetGenDllT_Field4())); + Assert.AreEqual(expectedDllField5, FieldFullName(getter.GetGenDllT_Field5())); + } + } static void RunAllTests() { @@ -430,6 +468,8 @@ class Program TestRangeCheckElimination(); TestOpenClosedDelegate(); + + GenericLdtokenFieldsTest(); } static int Main() diff --git a/tests/src/readytorun/mainv1.csproj b/tests/src/readytorun/mainv1.csproj index 8da9bc2276..855c3578a6 100644 --- a/tests/src/readytorun/mainv1.csproj +++ b/tests/src/readytorun/mainv1.csproj @@ -27,6 +27,7 @@ </CodeAnalysisDependentAssemblyPaths> </ItemGroup> <ItemGroup> + <ProjectReference Include="fieldgetter.ilproj" /> <ProjectReference Include="testv1\test.csproj"> <Project>{F74F55A1-DFCF-4C7C-B462-E96E1D0BB667}</Project> </ProjectReference> @@ -47,6 +48,7 @@ $(CLRTestBatchPreCommands) DEL test.dll COPY /Y ..\testv1\test\test.dll test.dll %Core_Root%\crossgen /readytorun /platform_assemblies_paths %Core_Root%%3B%25CD% /out test.ni.dll test.dll +%Core_Root%\crossgen /readytorun /platform_assemblies_paths %Core_Root%%3B%25CD% /out fieldgetter.ni.dll fieldgetter.dll %Core_Root%\crossgen /readytorun /platform_assemblies_paths %Core_Root%%3B%25CD% /out mainv1.ni.exe mainv1.exe ]]></CLRTestBatchPreCommands> <BashCLRTestPreCommands><![CDATA[ @@ -54,6 +56,7 @@ $(BashCLRTestPreCommands) rm -f test.dll cp ../testv1/test/test.dll test.dll $CORE_ROOT/crossgen -readytorun -platform_assemblies_paths $CORE_ROOT:`pwd` -out test.ni.dll test.dll +$CORE_ROOT/crossgen -readytorun -platform_assemblies_paths $CORE_ROOT:`pwd` -out fieldgetter.ni.dll fieldgetter.dll $CORE_ROOT/crossgen -readytorun -platform_assemblies_paths $CORE_ROOT:`pwd` -out mainv1.ni.exe mainv1.exe ]]></BashCLRTestPreCommands> </PropertyGroup> diff --git a/tests/src/readytorun/mainv2.csproj b/tests/src/readytorun/mainv2.csproj index 19f16b308f..52a3720483 100644 --- a/tests/src/readytorun/mainv2.csproj +++ b/tests/src/readytorun/mainv2.csproj @@ -27,6 +27,7 @@ </CodeAnalysisDependentAssemblyPaths> </ItemGroup> <ItemGroup> + <ProjectReference Include="fieldgetter.ilproj" /> <ProjectReference Include="testv1\test.csproj" /> </ItemGroup> <ItemGroup> @@ -45,6 +46,7 @@ $(CLRTestBatchPreCommands) DEL test.dll COPY /Y ..\testv1\test\test.dll test.dll %Core_Root%\crossgen /readytorun /platform_assemblies_paths %Core_Root%%3B%25CD% /out mainv2.ni.exe mainv2.exe +%Core_Root%\crossgen /readytorun /platform_assemblies_paths %Core_Root%%3B%25CD% /out fieldgetter.ni.dll fieldgetter.dll DEL test.dll COPY /Y ..\testv2\test\test.dll test.dll %Core_Root%\crossgen /readytorun /platform_assemblies_paths %Core_Root%%3B%25CD% /out test.ni.dll test.dll @@ -54,6 +56,7 @@ $(BashCLRTestPreCommands) rm -f test.dll cp ../testv1/test/test.dll test.dll $CORE_ROOT/crossgen -readytorun -platform_assemblies_paths $CORE_ROOT:`pwd` -out mainv2.ni.exe mainv2.exe +$CORE_ROOT/crossgen -readytorun -platform_assemblies_paths $CORE_ROOT:`pwd` -out fieldgetter.ni.dll fieldgetter.dll rm -f test.dll cp ../testv2/test/test.dll test.dll $CORE_ROOT/crossgen -readytorun -platform_assemblies_paths $CORE_ROOT:`pwd` -out test.ni.dll test.dll diff --git a/tests/src/readytorun/test.cs b/tests/src/readytorun/test.cs index 39afbd218e..40199b41e8 100644 --- a/tests/src/readytorun/test.cs +++ b/tests/src/readytorun/test.cs @@ -225,6 +225,32 @@ public struct MyStruct : IDisposable public class MyGeneric<T,U> { +#if V2 + public object m_unused1; + public string m_Field1; + + public object m_unused2; + public T m_Field2; + + public object m_unused3; + public List<T> m_Field3; + + static public object m_unused4; + static public KeyValuePair<T, int> m_Field4; + + static public object m_unused5; + static public int m_Field5; + + public object m_unused6; + static public object m_unused7; +#else + public string m_Field1; + public T m_Field2; + public List<T> m_Field3; + static public KeyValuePair<T, int> m_Field4; + static public int m_Field5; +#endif + [ThreadStatic] public static Object ThreadStatic; public MyGeneric() |