Skip to content

Commit aece95d

Browse files
Merge pull request #2095 from Unity-Technologies/6000.1/bugfixes/uum-90945
Fix class initialization during class enumeration
2 parents 0766c5b + f837d93 commit aece95d

File tree

2 files changed

+53
-48
lines changed

2 files changed

+53
-48
lines changed

mono/metadata/unity-memory-info.c

Lines changed: 53 additions & 44 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,35 @@ 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 = (MonoClass *)head;
65+
66+
if (klass->inited)
67+
context->callback(klass, context->user_data);
68+
69+
head = *(table->next_value (head));
70+
}
71+
}
72+
}
73+
74+
// Report all classes from an assembly
4475
static void
4576
ReportClassesFromAssembly(MonoAssembly *assembly, void *user_data)
4677
{
@@ -65,11 +96,8 @@ ReportClassesFromAssembly(MonoAssembly *assembly, void *user_data)
6596
}
6697
}
6798

68-
/* Some classes are only in this list.
69-
They are added in reflection_setup_internal_class_internal.
70-
*/
99+
// Iterate all classes created with TypeBuilder
71100
list = image->reflection_info_unregister_classes;
72-
73101
while (list) {
74102
MonoClass *klass = (MonoClass *)list->data;
75103

@@ -79,51 +107,45 @@ ReportClassesFromAssembly(MonoAssembly *assembly, void *user_data)
79107
list = list->next;
80108
}
81109

82-
// 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-
}
110+
// Iterate all initialized image classes
111+
// Every created class is in the class_cache
112+
IterateMonoInternalHashTable(&image->class_cache, user_data);
94113

114+
// Iterate all initialized array classes
95115
if (image->array_cache)
96116
g_hash_table_foreach(image->array_cache, ReportHashMapListClasses, user_data);
97117

118+
// Iterate all initialized single-dimention array classes
98119
if (image->szarray_cache)
99-
g_hash_table_foreach(image->szarray_cache, ReportHashMapClasses, user_data);
120+
g_hash_table_foreach(image->szarray_cache, ReportHashMapClass, user_data);
100121

122+
// Iterate all initialized class pointer classes
101123
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);
124+
g_hash_table_foreach(image->ptr_cache, ReportHashMapClass, user_data);
112125
}
113126

127+
// Report all classes in image sets which contain generic instances.
114128
static void
115129
ReportImageSetClasses(MonoImageSet *imageSet, void* user_data)
116130
{
131+
// Generic class instances
132+
if (imageSet->gclass_cache)
133+
mono_conc_hashtable_foreach(imageSet->gclass_cache, ReportGenericClass, user_data);
134+
135+
// Generic array class instances
117136
if (imageSet->array_cache)
118137
g_hash_table_foreach(imageSet->array_cache, ReportHashMapListClasses, user_data);
119138

139+
// Generic single dimention array (SZArray) class instances
120140
if (imageSet->szarray_cache)
121-
g_hash_table_foreach(imageSet->szarray_cache, ReportHashMapClasses, user_data);
141+
g_hash_table_foreach(imageSet->szarray_cache, ReportHashMapClass, user_data);
122142

143+
// Generic class pointer instances
123144
if (imageSet->ptr_cache)
124-
g_hash_table_foreach(imageSet->ptr_cache, ReportHashMapClasses, user_data);
145+
g_hash_table_foreach(imageSet->ptr_cache, ReportHashMapClass, user_data);
125146
}
126147

148+
// Report all initialized classes in the current domain.
127149
MONO_API void
128150
mono_unity_class_for_each(ClassReportFunc callback, void *user_data)
129151
{
@@ -132,19 +154,6 @@ mono_unity_class_for_each(ClassReportFunc callback, void *user_data)
132154
reportContext.user_data = user_data;
133155
// Report all assembly classes and assembly specific arrays
134156
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
157+
// Report all image set arrays which include generic classes
138158
mono_metadata_image_set_foreach(ReportImageSetClasses, &reportContext);
139159
}
140-
141-
MONO_API MonoManagedMemorySnapshot*
142-
mono_unity_capture_memory_snapshot()
143-
{
144-
return NULL;
145-
}
146-
147-
MONO_API void
148-
mono_unity_free_captured_memory_snapshot(MonoManagedMemorySnapshot* snapshot)
149-
{
150-
}

mono/metadata/unity-memory-info.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,4 @@ typedef void(*ClassReportFunc) (MonoClass* klass, void *user_data);
66

77
MONO_API void mono_unity_class_for_each(ClassReportFunc callback, void* user_data);
88

9-
typedef struct MonoManagedMemorySnapshot MonoManagedMemorySnapshot;
10-
MONO_API MonoManagedMemorySnapshot* mono_unity_capture_memory_snapshot();
11-
MONO_API void mono_unity_free_captured_memory_snapshot(MonoManagedMemorySnapshot* snapshot);
12-
139
#endif

0 commit comments

Comments
 (0)