Skip to content

Commit de478cc

Browse files
authored
Merge pull request #1081 from Unity-Technologies/scripting_memory_capture_static_field_byte_reporting_legacy_bugfix
Scripting memory capture static field byte reporting legacy bugfix
2 parents 67e0f71 + aefe37e commit de478cc

File tree

1 file changed

+56
-36
lines changed

1 file changed

+56
-36
lines changed

unity/unity_memory_info.c

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include <libgc/include/gc.h>
1212
#include <libgc/include/private/gc_priv.h>
1313
#include <mono/metadata/gc-internal.h>
14-
14+
#include <mono/metadata/mono-debug-debugger.h>
1515
#include <glib.h>
1616

1717
typedef struct CollectMetadataContext
@@ -21,22 +21,38 @@ typedef struct CollectMetadataContext
2121
MonoMetadataSnapshot* metadata;
2222
} CollectMetadataContext;
2323

24-
static void ContextInsertClass(CollectMetadataContext* context, MonoClass* klass)
24+
static void ContextRecurseClassData(CollectMetadataContext* context, MonoClass* klass)
2525
{
2626
gpointer orig_key, value;
27+
gpointer iter = NULL;
28+
MonoClassField *field = NULL;
29+
int fieldCount;
30+
2731
/* use g_hash_table_lookup_extended as it returns boolean to indicate if value was found.
28-
* If we use g_hash_table_lookup it returns the value which we were comparing to NULL. The problem is
29-
* that 0 is a valid class index and was confusing our logic.
32+
* If we use g_hash_table_lookup it returns the value which we were comparing to NULL. The problem is
33+
* that 0 is a valid class index and was confusing our logic.
3034
*/
31-
if (klass->inited && !g_hash_table_lookup_extended (context->allTypes, klass, &orig_key, &value))
32-
g_hash_table_insert(context->allTypes, klass, GINT_TO_POINTER (context->currentIndex++));
35+
if (!g_hash_table_lookup_extended(context->allTypes, klass, &orig_key, &value)) {
36+
g_hash_table_insert(context->allTypes, klass, GINT_TO_POINTER(context->currentIndex++));
37+
38+
fieldCount = mono_class_num_fields(klass);
39+
40+
if (fieldCount > 0) {
41+
while ((field = mono_class_get_fields(klass, &iter))) {
42+
MonoClass *fieldKlass = mono_class_from_mono_type(field->type);
43+
44+
if (fieldKlass != klass)
45+
ContextRecurseClassData(context, fieldKlass);
46+
}
47+
}
48+
}
3349
}
3450

3551
static void CollectHashMapClass(gpointer key, gpointer value, gpointer user_data)
3652
{
3753
CollectMetadataContext* context = (CollectMetadataContext*)user_data;
3854
MonoClass* klass = (MonoClass*)value;
39-
ContextInsertClass(context, klass);
55+
ContextRecurseClassData(context, klass);
4056
}
4157

4258
static void CollectHashMapListClasses(gpointer key, gpointer value, gpointer user_data)
@@ -47,7 +63,7 @@ static void CollectHashMapListClasses(gpointer key, gpointer value, gpointer use
4763
while (list != NULL)
4864
{
4965
MonoClass* klass = (MonoClass*)list->data;
50-
ContextInsertClass(context, klass);
66+
ContextRecurseClassData(context, klass);
5167

5268
list = g_slist_next(list);
5369
}
@@ -59,7 +75,7 @@ static void CollectGenericClass(gpointer value, gpointer user_data)
5975
MonoGenericClass* genericClass = (MonoGenericClass*)value;
6076

6177
if(genericClass->cached_class != NULL)
62-
ContextInsertClass(context, genericClass->cached_class);
78+
ContextRecurseClassData(context, genericClass->cached_class);
6379
}
6480

6581
static void CollectAssemblyMetaData (MonoAssembly *assembly, void *user_data)
@@ -72,7 +88,7 @@ static void CollectAssemblyMetaData (MonoAssembly *assembly, void *user_data)
7288
for(i = 0; i < tdef->rows-1; ++i)
7389
{
7490
MonoClass* klass = mono_class_get (image, (i + 2) | MONO_TOKEN_TYPE_DEF);
75-
ContextInsertClass(context, klass);
91+
ContextRecurseClassData(context, klass);
7692
}
7793

7894
if(image->array_cache)
@@ -95,64 +111,69 @@ static int FindClassIndex(GHashTable* hashTable, MonoClass* klass)
95111
return GPOINTER_TO_INT(value);
96112
}
97113

98-
static void AddMetadataType (gpointer key, gpointer value, gpointer user_data)
114+
static void AddMetadataType(gpointer key, gpointer value, gpointer user_data)
99115
{
100-
MonoClass* klass = (MonoClass*)key;
116+
MonoClass *klass = (MonoClass *)key;
117+
101118
int index = GPOINTER_TO_INT(value);
102-
CollectMetadataContext* context = (CollectMetadataContext*)user_data;
103-
MonoMetadataSnapshot* metadata = context->metadata;
104-
MonoMetadataType* type = &metadata->types[index];
119+
CollectMetadataContext *context = (CollectMetadataContext *)user_data;
120+
MonoMetadataSnapshot *metadata = context->metadata;
121+
MonoMetadataType *type = &metadata->types[index];
105122

106-
if(klass->rank > 0)
107-
{
123+
if (klass->rank > 0) {
108124
type->flags = (MonoMetadataTypeFlags)(kArray | (kArrayRankMask & (klass->rank << 16)));
109125
type->baseOrElementTypeIndex = FindClassIndex(context->allTypes, mono_class_get_element_class(klass));
110126
}
111-
else
112-
{
127+
else {
113128
gpointer iter = NULL;
114129
int fieldCount = 0;
115-
MonoClassField* field;
116-
MonoClass* baseClass;
117-
MonoVTable* vtable;
130+
MonoClassField *field;
131+
MonoClass *baseClass;
132+
MonoVTable *vtable;
133+
void *statics_data;
118134

119135
type->flags = (klass->valuetype || klass->byval_arg.type == MONO_TYPE_PTR) ? kValueType : kNone;
120136
type->fieldCount = 0;
137+
fieldCount = mono_class_num_fields(klass);
138+
if (fieldCount > 0) {
139+
type->fields = g_new(MonoMetadataField, fieldCount);
121140

122-
if(mono_class_num_fields(klass) > 0)
123-
{
124-
type->fields = g_new(MonoMetadataField, mono_class_num_fields(klass));
141+
while ((field = mono_class_get_fields(klass, &iter))) {
142+
MonoMetadataField *metaField = &type->fields[type->fieldCount];
143+
MonoClass *typeKlass = mono_class_from_mono_type(field->type);
125144

126-
while ((field = mono_class_get_fields (klass, &iter)))
127-
{
128-
MonoMetadataField* metaField = &type->fields[type->fieldCount];
129-
metaField->typeIndex = FindClassIndex(context->allTypes, mono_class_from_mono_type(field->type));
145+
if (typeKlass->rank > 0)
146+
metaField->typeIndex = FindClassIndex(context->allTypes, mono_class_get_element_class(typeKlass));
147+
else
148+
metaField->typeIndex = FindClassIndex(context->allTypes, typeKlass);
130149

131150
// This will happen if fields type is not initialized
132151
// It's OK to skip it, because it means the field is guaranteed to be null on any object
133-
if (metaField->typeIndex == -1)
152+
if (metaField->typeIndex == -1) {
134153
continue;
154+
}
135155

136156
// literals have no actual storage, and are not relevant in this context.
137-
if((field->type->attrs & FIELD_ATTRIBUTE_LITERAL) != 0)
157+
if ((field->type->attrs & FIELD_ATTRIBUTE_LITERAL) != 0)
138158
continue;
139159

140160
metaField->isStatic = (field->type->attrs & FIELD_ATTRIBUTE_STATIC) != 0;
161+
141162
metaField->offset = field->offset;
142163
metaField->name = field->name;
143164
type->fieldCount++;
144165
}
145166
}
146167

147168
vtable = mono_class_try_get_vtable(mono_domain_get(), klass);
169+
statics_data = vtable ? mono_vtable_get_static_field_data(vtable) : NULL;
148170

149-
type->staticsSize = vtable ? mono_class_data_size(klass) : 0; // Correct?
171+
type->staticsSize = statics_data ? mono_class_data_size(klass) : 0;
150172
type->statics = NULL;
151173

152-
if (type->staticsSize > 0 && vtable && vtable->data)
153-
{
174+
if (type->staticsSize > 0) {
154175
type->statics = g_new0(uint8_t, type->staticsSize);
155-
memcpy(type->statics, vtable->data, type->staticsSize);
176+
memcpy(type->statics, statics_data, type->staticsSize);
156177
}
157178

158179
baseClass = mono_class_get_parent(klass);
@@ -165,7 +186,6 @@ static void AddMetadataType (gpointer key, gpointer value, gpointer user_data)
165186
type->size = (klass->valuetype) != 0 ? (mono_class_instance_size(klass) - sizeof(MonoObject)) : mono_class_instance_size(klass);
166187
}
167188

168-
169189
static void CollectMetadata(MonoMetadataSnapshot* metadata)
170190
{
171191
CollectMetadataContext context;

0 commit comments

Comments
 (0)