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

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mono/mini/mini-wasm-debugger.c121
1 files changed, 80 insertions, 41 deletions
diff --git a/mono/mini/mini-wasm-debugger.c b/mono/mini/mini-wasm-debugger.c
index 43e61020b1f..3c60fcdd6cd 100644
--- a/mono/mini/mini-wasm-debugger.c
+++ b/mono/mini/mini-wasm-debugger.c
@@ -30,6 +30,12 @@ enum {
EXCEPTION_MODE_ALL
};
+// Flags for get_*_properties
+#define GPFLAG_NONE 0x0000
+#define GPFLAG_OWN_PROPERTIES 0x0001
+#define GPFLAG_ACCESSORS_ONLY 0x0002
+#define GPFLAG_EXPAND_VALUETYPES 0x0004
+
//functions exported to be used by JS
G_BEGIN_DECLS
@@ -41,8 +47,8 @@ EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_get_local_vars (int scope, int* pos, int
EMSCRIPTEN_KEEPALIVE void mono_wasm_clear_all_breakpoints (void);
EMSCRIPTEN_KEEPALIVE int mono_wasm_setup_single_step (int kind);
EMSCRIPTEN_KEEPALIVE int mono_wasm_pause_on_exceptions (int state);
-EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_get_object_properties (int object_id, gboolean expand_value_types);
-EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_get_array_values (int object_id, int start_idx, int count, gboolean expand_value_types);
+EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_get_object_properties (int object_id, int gpflags);
+EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_get_array_values (int object_id, int start_idx, int count, int gpflags);
EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_invoke_getter_on_object (int object_id, const char* name);
EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_invoke_getter_on_value (void *value, MonoClass *klass, const char *name);
EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_get_deref_ptr_value (void *value_addr, MonoClass *klass);
@@ -61,7 +67,7 @@ extern void mono_wasm_add_typed_value (const char *type, const char *str_value,
G_END_DECLS
-static void describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAsyncLocalThis, gboolean expandValueType);
+static void describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAsyncLocalThis, int gpflags);
static void handle_exception (MonoException *exc, MonoContext *throw_ctx, MonoContext *catch_ctx, StackFrameInfo *catch_frame);
//FIXME move all of those fields to the profiler object
@@ -823,7 +829,8 @@ read_enum_value (const char *mem, int type)
return 0;
}
-static gboolean describe_value(MonoType * type, gpointer addr, gboolean expandValueType)
+static gboolean
+describe_value(MonoType * type, gpointer addr, int gpflags)
{
ERROR_DECL (error);
switch (type->type) {
@@ -984,7 +991,7 @@ static gboolean describe_value(MonoType * type, gpointer addr, gboolean expandVa
} else {
char *to_string_val = get_to_string_description (class_name, klass, addr);
- if (expandValueType) {
+ if (gpflags & GPFLAG_EXPAND_VALUETYPES) {
int32_t size = mono_class_value_size (klass, NULL);
void *value_buf = g_malloc0 (size);
mono_value_copy_internal (value_buf, addr, klass);
@@ -996,7 +1003,7 @@ static gboolean describe_value(MonoType * type, gpointer addr, gboolean expandVa
g_free (value_buf);
// FIXME: isAsyncLocalThis
- describe_object_properties_for_klass (addr, klass, FALSE, expandValueType);
+ describe_object_properties_for_klass (addr, klass, FALSE, gpflags);
mono_wasm_add_typed_value ("end_vt", NULL, 0);
} else {
EM_ASM ({
@@ -1043,35 +1050,45 @@ invoke_and_describe_getter_value (MonoObject *obj, MonoProperty *p)
if (!is_ok (error) && exc == NULL)
exc = (MonoObject*) mono_error_convert_to_exception (error);
if (exc)
- describe_value (mono_get_object_type (), &exc, TRUE);
+ describe_value (mono_get_object_type (), &exc, GPFLAG_EXPAND_VALUETYPES);
else if (!res || !m_class_is_valuetype (mono_object_class (res)))
- describe_value (sig->ret, &res, TRUE);
+ describe_value (sig->ret, &res, GPFLAG_EXPAND_VALUETYPES);
else
- describe_value (sig->ret, mono_object_unbox_internal (res), TRUE);
+ describe_value (sig->ret, mono_object_unbox_internal (res), GPFLAG_EXPAND_VALUETYPES);
}
static void
-describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAsyncLocalThis, gboolean expandValueType)
+describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAsyncLocalThis, int gpflags)
{
MonoClassField *f;
MonoProperty *p;
MonoMethodSignature *sig;
- gpointer iter = NULL;
gboolean is_valuetype;
int pnum;
char *klass_name;
gboolean auto_invoke_getters;
+ gboolean is_own;
+ gboolean only_backing_fields;
g_assert (klass);
+ MonoClass *start_klass = klass;
+
+ only_backing_fields = gpflags & GPFLAG_ACCESSORS_ONLY;
is_valuetype = m_class_is_valuetype(klass);
+ if (is_valuetype)
+ gpflags |= GPFLAG_EXPAND_VALUETYPES;
+handle_parent:
+ is_own = (start_klass == klass);
+ klass_name = mono_class_full_name (klass);
+ gpointer iter = NULL;
while (obj && (f = mono_class_get_fields_internal (klass, &iter))) {
if (isAsyncLocalThis && f->name[0] == '<' && f->name[1] == '>') {
if (g_str_has_suffix (f->name, "__this")) {
mono_wasm_add_properties_var ("this", f->offset);
gpointer field_value = (guint8*)obj + f->offset;
- describe_value (f->type, field_value, is_valuetype | expandValueType);
+ describe_value (f->type, field_value, gpflags);
}
continue;
@@ -1081,20 +1098,23 @@ describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAs
if (mono_field_is_deleted (f))
continue;
- mono_wasm_add_properties_var (f->name, f->offset);
+ if (only_backing_fields && !g_str_has_suffix(f->name, "k__BackingField"))
+ continue;
+
+ EM_ASM ({
+ MONO.mono_wasm_add_properties_var ($0, { field_offset: $1, is_own: $2, attr: $3, owner_class: $4 });
+ }, f->name, f->offset, is_own, f->type->attrs, klass_name);
gpointer field_addr;
if (is_valuetype)
field_addr = mono_vtype_get_field_addr (obj, f);
else
field_addr = (guint8*)obj + f->offset;
-
- describe_value (f->type, field_addr, is_valuetype | expandValueType);
+
+ describe_value (f->type, field_addr, gpflags);
}
- klass_name = mono_class_full_name (klass);
auto_invoke_getters = are_getters_allowed (klass_name);
-
iter = NULL;
pnum = 0;
while ((p = mono_class_get_properties (klass, &iter))) {
@@ -1102,8 +1122,15 @@ describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAs
if (isAsyncLocalThis && (p->name[0] != '<' || (p->name[0] == '<' && p->name[1] == '>')))
continue;
- mono_wasm_add_properties_var (p->name, pnum);
sig = mono_method_signature_internal (p->get);
+ if (sig->param_count != 0) {
+ // getters with params are not shown
+ continue;
+ }
+
+ EM_ASM ({
+ MONO.mono_wasm_add_properties_var ($0, { field_offset: $1, is_own: $2, attr: $3, owner_class: $4 });
+ }, p->name, pnum, is_own, p->attrs, klass_name);
gboolean vt_self_type_getter = is_valuetype && mono_class_from_mono_type_internal (sig->ret) == klass;
if (auto_invoke_getters && !vt_self_type_getter) {
@@ -1112,8 +1139,7 @@ describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAs
// not allowed to call the getter here
char *ret_class_name = mono_class_full_name (mono_class_from_mono_type_internal (sig->ret));
- gboolean invokable = sig->param_count == 0;
- mono_wasm_add_typed_value ("getter", ret_class_name, invokable);
+ mono_wasm_add_typed_value ("getter", ret_class_name, -1);
g_free (ret_class_name);
continue;
@@ -1123,6 +1149,14 @@ describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAs
}
g_free (klass_name);
+
+ // ownProperties
+ // Note: ownProperties should mean that we return members of the klass itself,
+ // but we are going to ignore that here, because otherwise vscode/chrome don't
+ // seem to ask for inherited fields at all.
+ // if (!is_valuetype && !(gpflags & GPFLAG_OWN_PROPERTIES) && (klass = m_class_get_parent (klass)))
+ if (!is_valuetype && (klass = m_class_get_parent (klass)))
+ goto handle_parent;
}
/*
@@ -1148,9 +1182,9 @@ describe_delegate_properties (MonoObject *obj)
}
static gboolean
-describe_object_properties (guint64 objectId, gboolean isAsyncLocalThis, gboolean expandValueType)
+describe_object_properties (guint64 objectId, gboolean isAsyncLocalThis, int gpflags)
{
- DEBUG_PRINTF (2, "describe_object_properties %llu\n", objectId);
+ DEBUG_PRINTF (2, "describe_object_properties %llu, gpflags: %d\n", objectId, gpflags);
MonoObject *obj = get_object_from_id (objectId);
if (!obj)
@@ -1160,7 +1194,7 @@ describe_object_properties (guint64 objectId, gboolean isAsyncLocalThis, gboolea
// delegates get the same id format as regular objects
describe_delegate_properties (obj);
} else {
- describe_object_properties_for_klass (obj, obj->vtable->klass, isAsyncLocalThis, expandValueType);
+ describe_object_properties_for_klass (obj, obj->vtable->klass, isAsyncLocalThis, gpflags);
}
return TRUE;
@@ -1174,7 +1208,9 @@ invoke_getter (void *obj_or_value, MonoClass *klass, const char *name)
return FALSE;
}
- gpointer iter = NULL;
+ gpointer iter;
+handle_parent:
+ iter = NULL;
MonoProperty *p;
while ((p = mono_class_get_properties (klass, &iter))) {
//if get doesn't have name means that doesn't have a getter implemented and we don't want to show value, like VS debug
@@ -1185,11 +1221,14 @@ invoke_getter (void *obj_or_value, MonoClass *klass, const char *name)
return TRUE;
}
+ if ((klass = m_class_get_parent(klass)))
+ goto handle_parent;
+
return FALSE;
}
-static gboolean
-describe_array_values (guint64 objectId, int startIdx, int count, gboolean expandValueType)
+static gboolean
+describe_array_values (guint64 objectId, int startIdx, int count, int gpflags)
{
if (count == 0)
return TRUE;
@@ -1229,7 +1268,7 @@ describe_array_values (guint64 objectId, int startIdx, int count, gboolean expan
for (int i = startIdx; i < endIdx; i ++) {
mono_wasm_add_array_item(i);
elem = (gpointer*)((char*)arr->vector + (i * esize));
- describe_value (m_class_get_byval_arg (m_class_get_element_class (klass)), elem, expandValueType);
+ describe_value (m_class_get_byval_arg (m_class_get_element_class (klass)), elem, gpflags);
}
return TRUE;
}
@@ -1237,14 +1276,14 @@ describe_array_values (guint64 objectId, int startIdx, int count, gboolean expan
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
+ //Async methods are special in the way that local variables can be lifted to generated class fields
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;
int objId = get_object_id (obj);
mono_wasm_set_is_async_method (objId);
- describe_object_properties (objId, TRUE, FALSE);
+ describe_object_properties (objId, TRUE, GPFLAG_NONE);
}
}
@@ -1264,17 +1303,17 @@ describe_non_async_this (InterpFrame *frame, MonoMethod *method)
mono_wasm_add_properties_var ("this", -1);
if (m_class_is_valuetype (klass)) {
- describe_value (type, obj, TRUE);
+ describe_value (type, obj, GPFLAG_EXPAND_VALUETYPES);
} else {
// this is an object, and we can retrieve the valuetypes in it later
// through the object id
- describe_value (type, addr, FALSE);
+ describe_value (type, addr, GPFLAG_NONE);
}
}
}
static gboolean
-describe_variable (InterpFrame *frame, MonoMethod *method, int pos, gboolean expandValueType)
+describe_variable (InterpFrame *frame, MonoMethod *method, int pos, int gpflags)
{
ERROR_DECL (error);
MonoMethodHeader *header = NULL;
@@ -1295,7 +1334,7 @@ describe_variable (InterpFrame *frame, MonoMethod *method, int pos, gboolean exp
DEBUG_PRINTF (2, "adding val %p type [%p] %s\n", addr, type, mono_type_full_name (type));
- describe_value(type, addr, expandValueType);
+ describe_value(type, addr, gpflags);
if (header)
mono_metadata_free_mh (header);
@@ -1324,7 +1363,7 @@ describe_variables_on_frame (MonoStackFrameInfo *info, MonoContext *ctx, gpointe
for (int i = 0; i < data->len; i++)
{
- describe_variable (frame, method, data->pos[i], TRUE);
+ describe_variable (frame, method, data->pos[i], GPFLAG_EXPAND_VALUETYPES);
}
describe_async_method_locals (frame, method);
@@ -1343,7 +1382,7 @@ mono_wasm_get_deref_ptr_value (void *value_addr, MonoClass *klass)
}
mono_wasm_add_properties_var ("deref", -1);
- describe_value (type->data.type, value_addr, TRUE);
+ describe_value (type->data.type, value_addr, GPFLAG_EXPAND_VALUETYPES);
return TRUE;
}
@@ -1363,19 +1402,19 @@ mono_wasm_get_local_vars (int scope, int* pos, int len)
}
EMSCRIPTEN_KEEPALIVE gboolean
-mono_wasm_get_object_properties (int object_id, gboolean expand_value_types)
+mono_wasm_get_object_properties (int object_id, int gpflags)
{
- DEBUG_PRINTF (2, "getting properties of object %d\n", object_id);
+ DEBUG_PRINTF (2, "getting properties of object %d, gpflags: %d\n", object_id, gpflags);
- return describe_object_properties (object_id, FALSE, expand_value_types);
+ return describe_object_properties (object_id, FALSE, gpflags);
}
EMSCRIPTEN_KEEPALIVE gboolean
-mono_wasm_get_array_values (int object_id, int start_idx, int count, gboolean expand_value_types)
+mono_wasm_get_array_values (int object_id, int start_idx, int count, int gpflags)
{
- DEBUG_PRINTF (2, "getting array values %d, startIdx: %d, count: %d, expandValueType: %d\n", object_id, start_idx, count, expand_value_types);
+ DEBUG_PRINTF (2, "getting array values %d, startIdx: %d, count: %d, gpflags: 0x%x\n", object_id, start_idx, count, gpflags);
- return describe_array_values (object_id, start_idx, count, expand_value_types);
+ return describe_array_values (object_id, start_idx, count, gpflags);
}
EMSCRIPTEN_KEEPALIVE gboolean