Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[debugger] Assert when async debug a generic method #17727

Merged
merged 7 commits into from
Nov 13, 2019
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
12 changes: 12 additions & 0 deletions mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,7 @@ public static void wait_one ()
if_property_stepping();
fixed_size_array();
test_new_exception_filter();
test_async_debug_generics();
return 3;
}

Expand Down Expand Up @@ -903,6 +904,17 @@ public static void ss7_3 ()
}
}

[MethodImplAttribute (MethodImplOptions.NoInlining)]
public static void test_async_debug_generics () {
ExecuteAsync_Broken<object>().Wait ();
}

async static Task<T> ExecuteAsync_Broken<T>()
{
await Task.Delay(2);
return default;
}

[MethodImplAttribute (MethodImplOptions.NoInlining)]
public static void inspect_enumerator_in_generic_struct() {
TestEnumeratorInsideGenericStruct<String, String> generic_struct = new TestEnumeratorInsideGenericStruct<String, String>(new KeyValuePair<string, string>("0", "f1"));
Expand Down
10 changes: 10 additions & 0 deletions mcs/class/Mono.Debugger.Soft/Test/dtest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5152,6 +5152,16 @@ public void Bug59649 ()
vm = null;
}

[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);
}

#endif
} // class DebuggerTests
} // namespace
35 changes: 31 additions & 4 deletions mono/mini/debugger-agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -4526,6 +4526,31 @@ get_object_id_for_debugger_method (MonoClass* async_builder_class)
return method;
}

static MonoClass *
get_class_to_get_builder_field(DbgEngineStackFrame *frame)
{
ERROR_DECL (error);
gpointer this_addr = get_this_addr (frame);
MonoClass *original_class = frame->method->klass;
MonoClass *ret;
if (!m_class_is_valuetype (original_class) && mono_class_is_open_constructed_type (m_class_get_byval_arg (original_class))) {
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 (m_class_get_byval_arg (original_class), &context, error);
mono_error_assert_ok (error); /* FIXME don't swallow the error */

ret = mono_class_from_mono_type_internal (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 (DbgEngineStackFrame *frame)
Expand All @@ -4534,15 +4559,17 @@ get_async_method_builder (DbgEngineStackFrame *frame)
MonoClassField *builder_field;
gpointer builder;
gpointer this_addr;
MonoClass* klass = frame->method->klass;

builder_field = mono_class_get_field_from_name_full (frame->method->klass, "<>t__builder", NULL);
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 (m_class_is_valuetype (frame->method->klass)) {
if (m_class_is_valuetype (klass)) {
builder = mono_vtype_get_field_addr (*(guint8**)this_addr, builder_field);
} else {
this_obj = *(MonoObject**)this_addr;
Expand Down Expand Up @@ -4574,7 +4601,7 @@ get_this_async_id (DbgEngineStackFrame *frame)
if (!builder)
return 0;

builder_field = mono_class_get_field_from_name_full (frame->method->klass, "<>t__builder", NULL);
builder_field = mono_class_get_field_from_name_full (get_class_to_get_builder_field(frame), "<>t__builder", NULL);
g_assert (builder_field);

tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id);
Expand All @@ -4598,7 +4625,7 @@ get_this_async_id (DbgEngineStackFrame *frame)
static gboolean
set_set_notification_for_wait_completion_flag (DbgEngineStackFrame *frame)
{
MonoClassField *builder_field = mono_class_get_field_from_name_full (frame->method->klass, "<>t__builder", NULL);
MonoClassField *builder_field = mono_class_get_field_from_name_full (get_class_to_get_builder_field(frame), "<>t__builder", NULL);
g_assert (builder_field);
gpointer builder = get_async_method_builder (frame);
g_assert (builder);
Expand Down
12 changes: 7 additions & 5 deletions mono/mini/mini-exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
#include "mini.h"
#include "trace.h"
#include "debugger-agent.h"
#include "debugger-engine.h"
#include "seq-points.h"
#include "llvm-runtime.h"
#include "mini-llvm.h"
Expand Down Expand Up @@ -842,8 +843,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;
Expand Down Expand Up @@ -888,6 +889,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)
{
Expand All @@ -897,7 +899,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);
Expand Down Expand Up @@ -1948,7 +1950,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
Expand Down Expand Up @@ -4019,7 +4021,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 (m_class_get_byval_arg (catch_class), &context, error);
mono_error_assert_ok (error); /* FIXME don't swallow the error */

Expand Down
3 changes: 3 additions & 0 deletions mono/mini/mini.h
Original file line number Diff line number Diff line change
Expand Up @@ -2907,4 +2907,7 @@ mini_safepoints_enabled (void)
gpointer
mono_arch_load_function (MonoJitICallId jit_icall_id);

MonoGenericContext
mono_get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info);

#endif /* __MONO_MINI_H__ */