diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs index a90145526cdc..7e55dae9989d 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs @@ -366,6 +366,7 @@ public static void wait_one () new Tests ().invoke_abort (); new Tests ().evaluate_method (); + test_async_debug_generics(); test_invalid_argument_assembly_get_type (); return 3; @@ -558,6 +559,17 @@ public static void ss7_3 () ss_nested_3 (); } + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void test_async_debug_generics () { + ExecuteAsync_Broken().Wait (); + } + + async static Task ExecuteAsync_Broken() + { + await Task.Delay(2); + return default; + } + [MethodImplAttribute (MethodImplOptions.NoInlining)] public static void ss_nested_1 (int i) { } diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs index e4d04451f458..7294c53a37ca 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs @@ -4444,5 +4444,14 @@ public void Hash () } } + [Test] + public void TestAsyncDebugGenerics () { + Event e = run_until ("test_async_debug_generics"); + e = step_in_await ("test_async_debug_generics", e); + e = step_in_await ("MoveNext", e); + e = step_in_await ("MoveNext", e); + e = step_in_await ("MoveNext", e); + e = step_in_await ("MoveNext", e); + } } // class DebuggerTests } // namespace diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index 9055c8f76b31..049785cc1ee2 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -5448,6 +5448,30 @@ get_object_id_for_debugger_method (MonoClass* async_builder_class) return method; } +static MonoClass * +get_class_to_get_builder_field(StackFrame *frame) +{ + MonoError error; + gpointer this_addr = get_this_addr (frame); + MonoClass *original_class = frame->method->klass; + MonoClass *ret; + if (!mono_class_is_valuetype(original_class) && mono_class_is_open_constructed_type (&original_class->byval_arg)) { + MonoObject *this_obj = *(MonoObject**)this_addr; + MonoGenericContext context; + MonoType *inflated_type; + + g_assert (this_obj); + context = mono_get_generic_context_from_stack_frame (frame->ji, this_obj->vtable); + inflated_type = mono_class_inflate_generic_type_checked (&original_class->byval_arg, &context, &error); + mono_error_assert_ok (&error); /* FIXME don't swallow the error */ + + ret = mono_class_from_mono_type (inflated_type); + mono_metadata_free_type (inflated_type); + return ret; + } + return original_class; +} + /* Return the address of the AsyncMethodBuilder struct belonging to the state machine method pointed to by FRAME */ static gpointer get_async_method_builder (StackFrame *frame) @@ -5456,15 +5480,17 @@ get_async_method_builder (StackFrame *frame) MonoClassField *builder_field; gpointer builder; guint8 *this_addr; + MonoClass* klass = frame->method->klass; - builder_field = mono_class_get_field_from_name (frame->method->klass, "<>t__builder"); + klass = get_class_to_get_builder_field(frame); + builder_field = mono_class_get_field_from_name_full (klass, "<>t__builder", NULL); g_assert (builder_field); this_addr = get_this_addr (frame); if (!this_addr) return NULL; - if (mono_class_is_valuetype (frame->method->klass)) { + if (mono_class_is_valuetype (klass)) { guint8 *vtaddr = *(guint8**)this_addr; builder = (char*)vtaddr + mono_field_get_offset (builder_field) - sizeof (MonoObject); } else { @@ -5497,7 +5523,7 @@ get_this_async_id (StackFrame *frame) if (!builder) return 0; - builder_field = mono_class_get_field_from_name (frame->method->klass, "<>t__builder"); + builder_field = mono_class_get_field_from_name (get_class_to_get_builder_field(frame), "<>t__builder"); g_assert (builder_field); tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id); @@ -5521,7 +5547,7 @@ get_this_async_id (StackFrame *frame) static gboolean set_set_notification_for_wait_completion_flag (StackFrame *frame) { - MonoClassField *builder_field = mono_class_get_field_from_name (frame->method->klass, "<>t__builder"); + MonoClassField *builder_field = mono_class_get_field_from_name (get_class_to_get_builder_field(frame), "<>t__builder"); g_assert (builder_field); gpointer builder = get_async_method_builder (frame); g_assert (builder); diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index 993d94dca7d5..03b709025402 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -805,8 +805,8 @@ get_generic_info_from_stack_frame (MonoJitInfo *ji, MonoContext *ctx) /* * generic_info is either a MonoMethodRuntimeGenericContext or a MonoVTable. */ -static MonoGenericContext -get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info) +MonoGenericContext +mono_get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info) { MonoGenericContext context = { NULL, NULL }; MonoClass *klass, *method_container_class; @@ -851,6 +851,7 @@ get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info) return context; } + static MonoMethod* get_method_from_stack_frame (MonoJitInfo *ji, gpointer generic_info) { @@ -860,7 +861,7 @@ get_method_from_stack_frame (MonoJitInfo *ji, gpointer generic_info) if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this) return jinfo_get_method (ji); - context = get_generic_context_from_stack_frame (ji, generic_info); + context = mono_get_generic_context_from_stack_frame (ji, generic_info); method = jinfo_get_method (ji); method = mono_method_get_declaring_generic_method (method); @@ -1386,7 +1387,7 @@ get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContex if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this) return catch_class; - context = get_generic_context_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, ctx)); + context = mono_get_generic_context_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, ctx)); /* FIXME: we shouldn't inflate but instead put the type in the rgctx and fetch it from there. It @@ -3473,7 +3474,7 @@ mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 reg MonoType *inflated_type; g_assert (rgctx || this_obj); - context = get_generic_context_from_stack_frame (jinfo, rgctx ? rgctx : this_obj->vtable); + context = mono_get_generic_context_from_stack_frame (jinfo, rgctx ? rgctx : this_obj->vtable); inflated_type = mono_class_inflate_generic_type_checked (&catch_class->byval_arg, &context, &error); mono_error_assert_ok (&error); /* FIXME don't swallow the error */ diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 40d2aa918d23..f6ba23cf84be 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2883,4 +2883,7 @@ gboolean MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal); #endif +MonoGenericContext +mono_get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info); + #endif /* __MONO_MINI_H__ */