From 518c76ff21c28ff0643d8bed74dcbd1b6757d06d Mon Sep 17 00:00:00 2001 From: Thays Grazia Date: Thu, 10 Mar 2022 17:35:27 -0300 Subject: [release/6.0] [mono] Fix stacktrace from DIM (#65509) * Backport of #60770 and #64566 * Fixing missing end line --- src/mono/mono/metadata/object.c | 2 + src/mono/mono/mini/mini-exceptions.c | 13 +- .../regressions/github60486.cs | 190 +++++++++++++++++++++ .../regressions/github60486.csproj | 11 ++ 4 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github60486.cs create mode 100644 src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github60486.csproj diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index cbabe1f08fb..57b2f8374ea 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -1519,6 +1519,8 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, gpointer* imt, GSList *extra_ * add_imt_builder_entry anyway. */ method = mono_class_get_method_by_index (mono_class_get_generic_class (iface)->container_class, method_slot_in_interface); + if (m_method_is_static (method)) + continue; if (mono_method_get_imt_slot (method) != slot_num) { vt_slot ++; continue; diff --git a/src/mono/mono/mini/mini-exceptions.c b/src/mono/mono/mini/mini-exceptions.c index eea17726ba2..ce9c8799f20 100644 --- a/src/mono/mono/mini/mini-exceptions.c +++ b/src/mono/mono/mini/mini-exceptions.c @@ -827,7 +827,7 @@ mono_get_generic_info_from_stack_frame (MonoJitInfo *ji, MonoContext *ctx) } method = jinfo_get_method (ji); - if (mono_method_get_context (method)->method_inst) { + if (mono_method_get_context (method)->method_inst || mini_method_is_default_method (method)) { /* A MonoMethodRuntimeGenericContext* */ return info; } else if ((method->flags & METHOD_ATTRIBUTE_STATIC) || m_class_is_valuetype (method->klass)) { @@ -855,12 +855,13 @@ mono_get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_inf method = jinfo_get_method (ji); g_assert (method->is_inflated); - if (mono_method_get_context (method)->method_inst) { + if (mono_method_get_context (method)->method_inst || mini_method_is_default_method (method)) { MonoMethodRuntimeGenericContext *mrgctx = (MonoMethodRuntimeGenericContext *)generic_info; klass = mrgctx->class_vtable->klass; context.method_inst = mrgctx->method_inst; - g_assert (context.method_inst); + if (!mini_method_is_default_method (method)) + g_assert (context.method_inst); } else { MonoVTable *vtable = (MonoVTable *)generic_info; @@ -873,6 +874,12 @@ mono_get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_inf else method_container_class = method->klass; + if (mini_method_is_default_method (method)) { + if (mono_class_is_ginst (klass) || mono_class_is_gtd (klass)) + context.class_inst = mini_class_get_context (klass)->class_inst; + return context; + } + /* class might refer to a subclass of method's class */ while (!(klass == method->klass || (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->container_class == method_container_class))) { klass = m_class_get_parent (klass); diff --git a/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github60486.cs b/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github60486.cs new file mode 100644 index 00000000000..fa751c14ee8 --- /dev/null +++ b/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github60486.cs @@ -0,0 +1,190 @@ +using System; +using System.Runtime.CompilerServices; + +public interface IPublisher +{ + event Action OnPublish; +} + +public interface TestItf1 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + void TestMethod1(IPublisher publisher, StackFrame[] expectedFrames) + { + StackFrame.Validate(Environment.StackTrace, expectedFrames); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + void TestMethod2(IPublisher publisher, StackFrame[] expectedFrames) + { + TestMethod3(this, publisher, expectedFrames); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + protected static void TestMethod3(TestItf1 subscriber, IPublisher publisher, StackFrame[] expectedFrames) + { + StackFrame.Validate(Environment.StackTrace, expectedFrames); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + void TestMethod4(IPublisher publisher, StackFrame[] expectedFrames) + { + TestMethod3(this, publisher, expectedFrames); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + void TestMethod5(IPublisher publisher, StackFrame[] expectedFrames) + { + TestMethod3(this, publisher, expectedFrames); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + void TestMethod10(IPublisher publisher, StackFrame[] expectedFrames) + { + TestMethod3(this, publisher, expectedFrames); + } + + void TestMethod11(IPublisher publisher, StackFrame[] expectedFrames); +} + +public interface TestItf2 : TestItf1 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + void TestItf1.TestMethod5(IPublisher publisher, StackFrame[] expectedFrames) + { + TestMethod3(this, publisher, expectedFrames); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + void TestItf1.TestMethod10(IPublisher publisher, StackFrame[] expectedFrames) + { + TestMethod3(this, publisher, expectedFrames); + } +} + +public interface TestItf3 : TestItf1 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + void TestMethod6(IPublisher publisher, StackFrame[] expectedFrames) + { + TestMethod3(this, publisher, expectedFrames); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + void TestMethod7(IPublisher publisher, StackFrame[] expectedFrames) + { + TestMethod8(this, publisher, expectedFrames); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + protected static void TestMethod8(TestItf1 subscriber, IPublisher publisher, StackFrame[] expectedFrames) + { + StackFrame.Validate(Environment.StackTrace, expectedFrames); + } + + void TestMethod9(IPublisher publisher, StackFrame[] expectedFrames); +} + +public interface TestItf4 : TestItf3 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + void TestItf3.TestMethod9(IPublisher publisher, StackFrame[] expectedFrames) + { + TestMethod8(this, publisher, expectedFrames); + } +} + +public class ProgramBase : TestItf4 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + public void TestMethod10(IPublisher publisher, StackFrame[] expectedFrames) + { + TestItf1.TestMethod3(this, publisher, expectedFrames); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public void TestMethod11(IPublisher publisher, StackFrame[] expectedFrames) + { + TestItf1.TestMethod3(this, publisher, expectedFrames); + } +} + +public class Program : ProgramBase, TestItf2 +{ + static int Main(string[] args) + { + new Program().Start(); + return 100; + } + + public void Start() + { + var t1 = this as TestItf1; + t1.TestMethod1(null, new[] { new StackFrame("TestItf1`1", "TestMethod1") }); + t1.TestMethod2(null, new[] { new StackFrame("TestItf1`1", "TestMethod3"), new StackFrame("TestItf1`1", "TestMethod2") }); + t1.TestMethod4(null, new[] { new StackFrame("TestItf1`1", "TestMethod3"), new StackFrame("Program", "TestMethod4") }); + t1.TestMethod5(null, new[] { new StackFrame("TestItf1`1", "TestMethod3"), new StackFrame(new[] { "TestItf2`1", "TestItf1" }, "TestMethod5") }); + + var t3 = this as TestItf3; + t3.TestMethod6(null, new[] { new StackFrame("TestItf1`1", "TestMethod3"), new StackFrame("TestItf3`1", "TestMethod6") }); + t3.TestMethod7(null, new[] { new StackFrame("TestItf3`1", "TestMethod8"), new StackFrame("TestItf3`1", "TestMethod7") }); + t3.TestMethod9(null, new[] { new StackFrame("TestItf3`1", "TestMethod8"), new StackFrame(new[] { "TestItf4`1", "TestItf3" }, "TestMethod9") }); + + t1.TestMethod10(null, new[] { new StackFrame("TestItf1`1", "TestMethod3"), new StackFrame("ProgramBase`1", "TestMethod10") }); + t1.TestMethod11(null, new[] { new StackFrame("TestItf1`1", "TestMethod3"), new StackFrame("ProgramBase`1", "TestMethod11") }); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public void TestMethod4(IPublisher publisher, StackFrame[] expectedFrames) + { + TestItf1.TestMethod3(this, publisher, expectedFrames); + } +} + +public class InputData +{ + public int i; +} + +public class StackFrame +{ + public string [] ClassName { get; set; } + public string MethodName { get; set; } = string.Empty; + + public StackFrame(string [] className, string methodName) + { + ClassName = className; + MethodName = methodName; + } + + public StackFrame(string className, string methodName) + { + ClassName = new string[] { className }; + MethodName = methodName; + } + + public static void Validate(string testStack, StackFrame[] expectedFrames) + { + int index = 1; + + string[] lines = testStack.Split( + new string[] { Environment.NewLine }, + StringSplitOptions.None + ); + + //Console.WriteLine(testStack); + + foreach (var frame in expectedFrames) + { + var line = lines[index++].Trim(); + + + if (!line.StartsWith($"at {frame.ClassName[0]}") || !line.Contains($".{frame.MethodName}") || (frame.ClassName.Length > 1 && !line.Contains($".{frame.ClassName[1]}"))) + { + Console.WriteLine($"Expected {frame.ClassName}.{frame.MethodName} but got {line}"); + Console.WriteLine(testStack); + Environment.Exit(1); + } + } + } +} \ No newline at end of file diff --git a/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github60486.csproj b/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github60486.csproj new file mode 100644 index 00000000000..aab61d4e449 --- /dev/null +++ b/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github60486.csproj @@ -0,0 +1,11 @@ + + + true + Exe + BuildAndRun + 0 + + + + + -- cgit v1.2.3