Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>2017-12-29 23:11:16 +0300
committerJan Kotas <jkotas@microsoft.com>2017-12-29 23:11:16 +0300
commitab4222fba0dddecc122b3a5d0437b8c7b6bfee60 (patch)
tree796587af5deed41c43fb9712c94f844b885fcb89
parentb01af15177f8b2124d10c31a17a1502d6613eda9 (diff)
Ensure reflection has access to instance methods on byref-like types (#5165)
* Ensure reflection has access to instance methods on byref-like types Adding the test uncovered a subtle issue. When rooting a virtual method for reflection, we should root the virtual method use of the slot defining method (not e.g. the `ToString` method on the byref-like type - we don't have virtual method use information for that). * Disable part that doesn't work on Unix
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/Compilation.cs6
-rw-r--r--src/ILCompiler/src/RdXmlRootProvider.cs5
-rw-r--r--tests/src/Simple/Reflection/Reflection.cs45
3 files changed, 50 insertions, 6 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
index 0c2ba2453..d686a0d7b 100644
--- a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
@@ -400,8 +400,10 @@ namespace ILCompiler
{
Debug.Assert(method.IsVirtual);
- if (!_factory.VTable(method.OwningType).HasFixedSlots)
- _graph.AddRoot(_factory.VirtualMethodUse(method), reason);
+ // Virtual method use is tracked on the slot defining method only.
+ MethodDesc slotDefiningMethod = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method);
+ if (!_factory.VTable(slotDefiningMethod.OwningType).HasFixedSlots)
+ _graph.AddRoot(_factory.VirtualMethodUse(slotDefiningMethod), reason);
if (method.IsAbstract)
{
diff --git a/src/ILCompiler/src/RdXmlRootProvider.cs b/src/ILCompiler/src/RdXmlRootProvider.cs
index 8698f1d5f..d55f87720 100644
--- a/src/ILCompiler/src/RdXmlRootProvider.cs
+++ b/src/ILCompiler/src/RdXmlRootProvider.cs
@@ -181,10 +181,7 @@ namespace ILCompiler
// Virtual methods should be rooted as if they were called virtually
if (method.IsVirtual)
- {
- MethodDesc slotMethod = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method);
- rootProvider.RootVirtualMethodForReflection(slotMethod, "RD.XML root");
- }
+ rootProvider.RootVirtualMethodForReflection(method, "RD.XML root");
if (!method.IsAbstract)
rootProvider.AddCompilationRoot(method, "RD.XML root");
diff --git a/tests/src/Simple/Reflection/Reflection.cs b/tests/src/Simple/Reflection/Reflection.cs
index 189090b3a..f24a855a8 100644
--- a/tests/src/Simple/Reflection/Reflection.cs
+++ b/tests/src/Simple/Reflection/Reflection.cs
@@ -28,6 +28,7 @@ internal class ReflectionTest
#if !OPTIMIZED_MODE_WITHOUT_SCANNER
TestContainment.Run();
TestInterfaceMethod.Run();
+ TestByRefLikeTypeMethod.Run();
#endif
TestAttributeInheritance.Run();
TestStringConstructor.Run();
@@ -324,6 +325,50 @@ internal class ReflectionTest
}
}
+ class TestByRefLikeTypeMethod
+ {
+ ref struct ByRefLike
+ {
+ public readonly int Value;
+
+ public ByRefLike(int value)
+ {
+ Value = value;
+ }
+
+ public override string ToString()
+ {
+ return Value.ToString();
+ }
+ }
+
+ delegate string ToStringDelegate(ref ByRefLike thisObj);
+
+ public static void Run()
+ {
+ Console.WriteLine(nameof(TestByRefLikeTypeMethod));
+
+ // Ensure things we reflect on are in the static callgraph
+ if (string.Empty.Length > 0)
+ {
+ default(ByRefLike).ToString();
+ ToStringDelegate s = null;
+ s = s.Invoke;
+ }
+
+ Type byRefLikeType = GetTestType(nameof(TestByRefLikeTypeMethod), nameof(ByRefLike));
+ MethodInfo toStringMethod = byRefLikeType.GetMethod("ToString");
+ /*var toString = (ToStringDelegate)*/toStringMethod.CreateDelegate(typeof(ToStringDelegate));
+
+ // Doesn't work on Unix: https://github.com/dotnet/corert/issues/4379
+#if false
+ ByRefLike foo = new ByRefLike(123);
+ if (toString(ref foo) != "123")
+ throw new Exception();
+#endif
+ }
+ }
+
class TestInterfaceMethod
{
interface IFoo