Skip to content

Commit 5009b51

Browse files
Fix class initialization during class enumeration
1 parent 0766c5b commit 5009b51

File tree

1 file changed

+40
-28
lines changed

1 file changed

+40
-28
lines changed

mono/metadata/unity-memory-info.c

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <config.h>
22
#include <mono/utils/mono-publib.h>
3+
34
#include "unity-memory-info.h"
45
#include <mono/metadata/assembly-internals.h>
56
#include <mono/metadata/class-internals.h>
@@ -8,6 +9,7 @@
89
#include <mono/metadata/object-internals.h>
910
#include <mono/metadata/tokentype.h>
1011
#include <mono/metadata/gc-internals.h>
12+
#include <mono/utils/mono-conc-hashtable.h>
1113
#include <glib.h>
1214
#include <stdlib.h>
1315

@@ -17,7 +19,7 @@ typedef struct ClassReportContext {
1719
} ClassReportContext;
1820

1921
static void
20-
ReportHashMapClasses(gpointer key, gpointer value, gpointer user_data)
22+
ReportHashMapClass(gpointer key, gpointer value, gpointer user_data)
2123
{
2224
ClassReportContext *context = (ClassReportContext *)user_data;
2325
MonoClass *klass = (MonoClass *)value;
@@ -41,6 +43,34 @@ ReportHashMapListClasses(gpointer key, gpointer value, gpointer user_data)
4143
}
4244
}
4345

46+
static void
47+
ReportGenericClass(gpointer key, gpointer value, gpointer user_data)
48+
{
49+
MonoGenericClass *genericClass = (MonoGenericClass *)key;
50+
ClassReportContext *context = (ClassReportContext *)user_data;
51+
52+
if (genericClass->cached_class != NULL && genericClass->cached_class->inited)
53+
context->callback(genericClass->cached_class, context->user_data);
54+
}
55+
56+
// Iterate MonoInternalHashTable similarly to mono_internal_hash_table_apply, but allow passing custom context
57+
static void
58+
IterateMonoInternalHashTable (MonoInternalHashTable *table, gpointer user_data)
59+
{
60+
ClassReportContext *context = (ClassReportContext *)user_data;
61+
for (gint i = 0; i < table->size; i++) {
62+
gpointer head = table->table [i];
63+
while (head) {
64+
MonoClass *klass = head;
65+
66+
if (klass->inited)
67+
context->callback(klass, context->user_data);
68+
69+
head = *(table->next_value (head));
70+
}
71+
}
72+
}
73+
4474
static void
4575
ReportClassesFromAssembly(MonoAssembly *assembly, void *user_data)
4676
{
@@ -80,48 +110,32 @@ ReportClassesFromAssembly(MonoAssembly *assembly, void *user_data)
80110
}
81111

82112
// Iterate all image classes
83-
for (i = 1; i < tdef->rows; ++i) {
84-
MonoClass *klass;
85-
MonoError error;
86-
87-
guint32 token = (i + 1) | MONO_TOKEN_TYPE_DEF;
88-
89-
klass = mono_class_get_checked(image, token, &error);
90-
91-
if (klass && klass->inited)
92-
context->callback(klass, context->user_data);
93-
}
113+
IterateMonoInternalHashTable(&image->class_cache, user_data);
94114

95115
if (image->array_cache)
96116
g_hash_table_foreach(image->array_cache, ReportHashMapListClasses, user_data);
97117

98118
if (image->szarray_cache)
99-
g_hash_table_foreach(image->szarray_cache, ReportHashMapClasses, user_data);
119+
g_hash_table_foreach(image->szarray_cache, ReportHashMapClass, user_data);
100120

101121
if (image->ptr_cache)
102-
g_hash_table_foreach(image->ptr_cache, ReportHashMapClasses, user_data);
103-
}
104-
105-
static void
106-
ReportGenericClasses(MonoGenericClass *genericClass, gpointer user_data)
107-
{
108-
ClassReportContext *context = (ClassReportContext *)user_data;
109-
110-
if (genericClass->cached_class != NULL && genericClass->cached_class->inited)
111-
context->callback(genericClass->cached_class, context->user_data);
122+
g_hash_table_foreach(image->ptr_cache, ReportHashMapClass, user_data);
112123
}
113124

114125
static void
115126
ReportImageSetClasses(MonoImageSet *imageSet, void* user_data)
116127
{
128+
if (imageSet->gclass_cache)
129+
mono_conc_hashtable_foreach(imageSet->gclass_cache, ReportGenericClass, user_data);
130+
117131
if (imageSet->array_cache)
118132
g_hash_table_foreach(imageSet->array_cache, ReportHashMapListClasses, user_data);
119133

120134
if (imageSet->szarray_cache)
121-
g_hash_table_foreach(imageSet->szarray_cache, ReportHashMapClasses, user_data);
135+
g_hash_table_foreach(imageSet->szarray_cache, ReportHashMapClass, user_data);
122136

123137
if (imageSet->ptr_cache)
124-
g_hash_table_foreach(imageSet->ptr_cache, ReportHashMapClasses, user_data);
138+
g_hash_table_foreach(imageSet->ptr_cache, ReportHashMapClass, user_data);
125139
}
126140

127141
MONO_API void
@@ -132,9 +146,7 @@ mono_unity_class_for_each(ClassReportFunc callback, void *user_data)
132146
reportContext.user_data = user_data;
133147
// Report all assembly classes and assembly specific arrays
134148
mono_domain_assembly_foreach(mono_domain_get(), ReportClassesFromAssembly, &reportContext);
135-
// Report all generic classes
136-
mono_metadata_generic_class_foreach(ReportGenericClasses, &reportContext);
137-
// Report all image set arrays
149+
// Report all image set arrays which include generic classes
138150
mono_metadata_image_set_foreach(ReportImageSetClasses, &reportContext);
139151
}
140152

0 commit comments

Comments
 (0)