Skip to content

Commit fd47696

Browse files
authored
Merge pull request #1082 from Unity-Technologies/scripting_memory_capture_static_field_byte_reporting_legacy_bugfix_2018.3
[Backport][PR #1081] Scripting memory capture static field byte reporting legacy bugfix 2018.3
2 parents d286af3 + d2b4bc0 commit fd47696

File tree

1 file changed

+70
-50
lines changed

1 file changed

+70
-50
lines changed

unity/unity_memory_info.c

Lines changed: 70 additions & 50 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,33 +21,49 @@ 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)
4359
{
4460
CollectMetadataContext* context = (CollectMetadataContext*)user_data;
4561
GSList* list = (GSList*)value;
4662

47-
while (list != NULL)
63+
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
}
@@ -58,101 +74,106 @@ static void CollectGenericClass(gpointer value, gpointer user_data)
5874
CollectMetadataContext* context = (CollectMetadataContext*)user_data;
5975
MonoGenericClass* genericClass = (MonoGenericClass*)value;
6076

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

65-
static void CollectAssemblyMetaData (MonoAssembly *assembly, void *user_data)
81+
static void CollectAssemblyMetaData(MonoAssembly *assembly, void *user_data)
6682
{
6783
int i;
6884
CollectMetadataContext* context = (CollectMetadataContext*)user_data;
6985
MonoImage* image = mono_assembly_get_image(assembly);
70-
MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
86+
MonoTableInfo *tdef = &image->tables[MONO_TABLE_TYPEDEF];
7187

72-
for(i = 0; i < tdef->rows-1; ++i)
88+
for (i = 0; i < tdef->rows - 1; ++i)
7389
{
74-
MonoClass* klass = mono_class_get (image, (i + 2) | MONO_TOKEN_TYPE_DEF);
75-
ContextInsertClass(context, klass);
90+
MonoClass* klass = mono_class_get(image, (i + 2) | MONO_TOKEN_TYPE_DEF);
91+
ContextRecurseClassData(context, klass);
7692
}
7793

78-
if(image->array_cache)
79-
g_hash_table_foreach(image->array_cache, CollectHashMapListClasses, user_data);
94+
if (image->array_cache)
95+
g_hash_table_foreach(image->array_cache, CollectHashMapListClasses, user_data);
8096

81-
if(image->szarray_cache)
82-
g_hash_table_foreach(image->szarray_cache, CollectHashMapClass, user_data);
97+
if (image->szarray_cache)
98+
g_hash_table_foreach(image->szarray_cache, CollectHashMapClass, user_data);
8399

84-
if(image->ptr_cache)
85-
g_hash_table_foreach(image->ptr_cache, CollectHashMapClass, user_data);
100+
if (image->ptr_cache)
101+
g_hash_table_foreach(image->ptr_cache, CollectHashMapClass, user_data);
86102
}
87103

88104
static int FindClassIndex(GHashTable* hashTable, MonoClass* klass)
89105
{
90106
gpointer orig_key, value;
91107

92-
if(!g_hash_table_lookup_extended (hashTable, klass, &orig_key, &value))
108+
if (!g_hash_table_lookup_extended(hashTable, klass, &orig_key, &value))
93109
return -1;
94110

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,15 +186,14 @@ 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;
172192

173193
context.allTypes = g_hash_table_new(NULL, NULL);
174194
context.currentIndex = 0;
175195
context.metadata = metadata;
176-
196+
177197
mono_assembly_foreach((GFunc)CollectAssemblyMetaData, &context);
178198

179199
mono_metadata_generic_class_foreach(CollectGenericClass, &context);

0 commit comments

Comments
 (0)