[wasm][debugger] Improve accessing locals (#32701)
authormonojenkins <jo.shields+jenkins@xamarin.com>
Mon, 24 Feb 2020 21:17:30 +0000 (16:17 -0500)
committerGitHub <noreply@github.com>
Mon, 24 Feb 2020 21:17:30 +0000 (22:17 +0100)
This fixes various issues in accessing locals on the stack.

Co-authored-by: Ankit Jain <radical@gmail.com>
src/mono/mono/mini/mini-wasm-debugger.c

index 32dedb8..43dc402 100644 (file)
@@ -595,7 +595,8 @@ mono_wasm_enum_frames (void)
 typedef struct {
        int cur_frame;
        int target_frame;
-       int variable;
+       int len;
+       int *pos;
 } FrameDescData;
 
 static gboolean describe_value(MonoType * type, gpointer addr)
@@ -766,100 +767,41 @@ describe_array_values (guint64 objectId)
        return TRUE;
 }
 
-static gboolean
-describe_async_method_locals (MonoStackFrameInfo *info, MonoContext *ctx, gpointer ud)
+static void
+describe_async_method_locals (InterpFrame *frame, MonoMethod *method)
 {
        //Async methods are special in the way that local variables can be lifted to generated class fields 
-       FrameDescData *data = (FrameDescData*)ud;
-
-       //skip wrappers
-       if (info->type != FRAME_TYPE_MANAGED && info->type != FRAME_TYPE_INTERP) {
-               return FALSE;
-       }
-
-       if (data->cur_frame < data->target_frame) {
-               ++data->cur_frame;
-               return FALSE;
-       }
-
-       InterpFrame *frame = (InterpFrame*)info->interp_frame;
-       g_assert (frame);
-       MonoMethod *method = frame->imethod->method;
-       g_assert (method);
        gpointer addr = NULL;
        if (mono_debug_lookup_method_async_debug_info (method)) {
                addr = mini_get_interp_callbacks ()->frame_get_this (frame);
                MonoObject *obj = *(MonoObject**)addr;
                describe_object_properties(get_object_id(obj), TRUE);           
        }
-       return TRUE;
 }
 
-static gboolean
-describe_this (MonoStackFrameInfo *info, MonoContext *ctx, gpointer ud)
+static void
+describe_this (InterpFrame *frame, MonoMethod *method)
 {
-       //Async methods are special in the way that local variables can be lifted to generated class fields 
-       FrameDescData *data = (FrameDescData*)ud;
-
-       //skip wrappers
-       if (info->type != FRAME_TYPE_MANAGED && info->type != FRAME_TYPE_INTERP) {
-               return FALSE;
-       }
-
-       if (data->cur_frame < data->target_frame) {
-               ++data->cur_frame;
-               return FALSE;
-       }
-
-       InterpFrame *frame = (InterpFrame*)info->interp_frame;
-       g_assert (frame);
-       MonoMethod *method = frame->imethod->method;
-       g_assert (method);
        gpointer addr = NULL;
        if (mono_method_signature_internal (method)->hasthis) {
                addr = mini_get_interp_callbacks ()->frame_get_this (frame);
                MonoObject *obj = *(MonoObject**)addr;
+               char *class_name = mono_class_full_name (obj->vtable->klass);
+
                mono_wasm_add_properties_var("this");
-               GString *class_name;
-               class_name = g_string_new ("");
-               if (*(m_class_get_name_space (obj->vtable->klass))) {
-                       g_string_append (class_name, m_class_get_name_space (obj->vtable->klass));
-                       g_string_append_c (class_name, '.');
-               }
-               g_string_append (class_name, m_class_get_name (obj->vtable->klass));
-               mono_wasm_add_obj_var (class_name->str, get_object_id(obj));
-               g_string_free(class_name, FALSE);
+               mono_wasm_add_obj_var (class_name, get_object_id(obj));
+               g_free (class_name);
        }
-       return TRUE;
 }
 
-
 static gboolean
-describe_variable (MonoStackFrameInfo *info, MonoContext *ctx, gpointer ud)
+describe_variable (InterpFrame *frame, MonoMethod *method, int pos)
 {
        ERROR_DECL (error);
        MonoMethodHeader *header = NULL;
 
-       FrameDescData *data = (FrameDescData*)ud;
-
-       //skip wrappers
-       if (info->type != FRAME_TYPE_MANAGED && info->type != FRAME_TYPE_INTERP) {
-               return FALSE;
-       }
-
-       if (data->cur_frame < data->target_frame) {
-               ++data->cur_frame;
-               return FALSE;
-       }
-
-       InterpFrame *frame = (InterpFrame*)info->interp_frame;
-       g_assert (frame);
-       MonoMethod *method = frame->imethod->method;
-       g_assert (method);
-
        MonoType *type = NULL;
        gpointer addr = NULL;
-       int pos = data->variable;
        if (pos < 0) {
                pos = -pos - 1;
                type = mono_method_signature_internal (method)->params [pos];
@@ -881,21 +823,48 @@ describe_variable (MonoStackFrameInfo *info, MonoContext *ctx, gpointer ud)
        return TRUE;
 }
 
+static gboolean
+describe_variables_on_frame (MonoStackFrameInfo *info, MonoContext *ctx, gpointer ud)
+{
+       FrameDescData *data = (FrameDescData*)ud;
+
+       //skip wrappers
+       if (info->type != FRAME_TYPE_MANAGED && info->type != FRAME_TYPE_INTERP) {
+               return FALSE;
+       }
+
+       if (data->cur_frame < data->target_frame) {
+               ++data->cur_frame;
+               return FALSE;
+       }
+
+       InterpFrame *frame = (InterpFrame*)info->interp_frame;
+       g_assert (frame);
+       MonoMethod *method = frame->imethod->method;
+       g_assert (method);
+
+       for (int i = 0; i < data->len; i++)
+       {
+               describe_variable (frame, method, data->pos[i]);
+       }
+
+       describe_async_method_locals (frame, method);
+       describe_this (frame, method);
+
+       return TRUE;
+}
+
 //FIXME this doesn't support getting the return value pseudo-var
 EMSCRIPTEN_KEEPALIVE void
 mono_wasm_get_var_info (int scope, int* pos, int len)
 {
        FrameDescData data;
-       data.cur_frame = 0;
        data.target_frame = scope;
-       for (int i = 0; i < len; i++)
-       {
-               DEBUG_PRINTF (2, "getting var %d of scope %d - %d\n", pos[i], scope, len);
-               data.variable = pos[i];
-               mono_walk_stack_with_ctx (describe_variable, NULL, MONO_UNWIND_NONE, &data);
-       }
-       mono_walk_stack_with_ctx (describe_async_method_locals, NULL, MONO_UNWIND_NONE, &data);
-       mono_walk_stack_with_ctx (describe_this, NULL, MONO_UNWIND_NONE, &data);
+       data.cur_frame = 0;
+       data.len = len;
+       data.pos = pos;
+
+       mono_walk_stack_with_ctx (describe_variables_on_frame, NULL, MONO_UNWIND_NONE, &data);
 }
 
 EMSCRIPTEN_KEEPALIVE void