11
11
#include <libgc/include/gc.h>
12
12
#include <libgc/include/private/gc_priv.h>
13
13
#include <mono/metadata/gc-internal.h>
14
-
14
+ #include <mono/metadata/mono-debug-debugger.h>
15
15
#include <glib.h>
16
16
17
17
typedef struct CollectMetadataContext
@@ -21,33 +21,49 @@ typedef struct CollectMetadataContext
21
21
MonoMetadataSnapshot * metadata ;
22
22
} CollectMetadataContext ;
23
23
24
- static void ContextInsertClass (CollectMetadataContext * context , MonoClass * klass )
24
+ static void ContextRecurseClassData (CollectMetadataContext * context , MonoClass * klass )
25
25
{
26
26
gpointer orig_key , value ;
27
+ gpointer iter = NULL ;
28
+ MonoClassField * field = NULL ;
29
+ int fieldCount ;
30
+
27
31
/* 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.
30
34
*/
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
+ }
33
49
}
34
50
35
51
static void CollectHashMapClass (gpointer key , gpointer value , gpointer user_data )
36
52
{
37
53
CollectMetadataContext * context = (CollectMetadataContext * )user_data ;
38
54
MonoClass * klass = (MonoClass * )value ;
39
- ContextInsertClass (context , klass );
55
+ ContextRecurseClassData (context , klass );
40
56
}
41
57
42
58
static void CollectHashMapListClasses (gpointer key , gpointer value , gpointer user_data )
43
59
{
44
60
CollectMetadataContext * context = (CollectMetadataContext * )user_data ;
45
61
GSList * list = (GSList * )value ;
46
62
47
- while (list != NULL )
63
+ while (list != NULL )
48
64
{
49
65
MonoClass * klass = (MonoClass * )list -> data ;
50
- ContextInsertClass (context , klass );
66
+ ContextRecurseClassData (context , klass );
51
67
52
68
list = g_slist_next (list );
53
69
}
@@ -58,101 +74,106 @@ static void CollectGenericClass(gpointer value, gpointer user_data)
58
74
CollectMetadataContext * context = (CollectMetadataContext * )user_data ;
59
75
MonoGenericClass * genericClass = (MonoGenericClass * )value ;
60
76
61
- if (genericClass -> cached_class != NULL )
62
- ContextInsertClass (context , genericClass -> cached_class );
77
+ if (genericClass -> cached_class != NULL )
78
+ ContextRecurseClassData (context , genericClass -> cached_class );
63
79
}
64
80
65
- static void CollectAssemblyMetaData (MonoAssembly * assembly , void * user_data )
81
+ static void CollectAssemblyMetaData (MonoAssembly * assembly , void * user_data )
66
82
{
67
83
int i ;
68
84
CollectMetadataContext * context = (CollectMetadataContext * )user_data ;
69
85
MonoImage * image = mono_assembly_get_image (assembly );
70
- MonoTableInfo * tdef = & image -> tables [MONO_TABLE_TYPEDEF ];
86
+ MonoTableInfo * tdef = & image -> tables [MONO_TABLE_TYPEDEF ];
71
87
72
- for (i = 0 ; i < tdef -> rows - 1 ; ++ i )
88
+ for (i = 0 ; i < tdef -> rows - 1 ; ++ i )
73
89
{
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 );
76
92
}
77
93
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 );
80
96
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 );
83
99
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 );
86
102
}
87
103
88
104
static int FindClassIndex (GHashTable * hashTable , MonoClass * klass )
89
105
{
90
106
gpointer orig_key , value ;
91
107
92
- if (!g_hash_table_lookup_extended (hashTable , klass , & orig_key , & value ))
108
+ if (!g_hash_table_lookup_extended (hashTable , klass , & orig_key , & value ))
93
109
return -1 ;
94
110
95
111
return GPOINTER_TO_INT (value );
96
112
}
97
113
98
- static void AddMetadataType (gpointer key , gpointer value , gpointer user_data )
114
+ static void AddMetadataType (gpointer key , gpointer value , gpointer user_data )
99
115
{
100
- MonoClass * klass = (MonoClass * )key ;
116
+ MonoClass * klass = (MonoClass * )key ;
117
+
101
118
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 ];
105
122
106
- if (klass -> rank > 0 )
107
- {
123
+ if (klass -> rank > 0 ) {
108
124
type -> flags = (MonoMetadataTypeFlags )(kArray | (kArrayRankMask & (klass -> rank << 16 )));
109
125
type -> baseOrElementTypeIndex = FindClassIndex (context -> allTypes , mono_class_get_element_class (klass ));
110
126
}
111
- else
112
- {
127
+ else {
113
128
gpointer iter = NULL ;
114
129
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 ;
118
134
119
135
type -> flags = (klass -> valuetype || klass -> byval_arg .type == MONO_TYPE_PTR ) ? kValueType : kNone ;
120
136
type -> fieldCount = 0 ;
137
+ fieldCount = mono_class_num_fields (klass );
138
+ if (fieldCount > 0 ) {
139
+ type -> fields = g_new (MonoMetadataField , fieldCount );
121
140
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 );
125
144
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 );
130
149
131
150
// This will happen if fields type is not initialized
132
151
// 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 ) {
134
153
continue ;
154
+ }
135
155
136
156
// 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 )
138
158
continue ;
139
159
140
160
metaField -> isStatic = (field -> type -> attrs & FIELD_ATTRIBUTE_STATIC ) != 0 ;
161
+
141
162
metaField -> offset = field -> offset ;
142
163
metaField -> name = field -> name ;
143
164
type -> fieldCount ++ ;
144
165
}
145
166
}
146
167
147
168
vtable = mono_class_try_get_vtable (mono_domain_get (), klass );
169
+ statics_data = vtable ? mono_vtable_get_static_field_data (vtable ) : NULL ;
148
170
149
- type -> staticsSize = vtable ? mono_class_data_size (klass ) : 0 ; // Correct?
171
+ type -> staticsSize = statics_data ? mono_class_data_size (klass ) : 0 ;
150
172
type -> statics = NULL ;
151
173
152
- if (type -> staticsSize > 0 && vtable && vtable -> data )
153
- {
174
+ if (type -> staticsSize > 0 ) {
154
175
type -> statics = g_new0 (uint8_t , type -> staticsSize );
155
- memcpy (type -> statics , vtable -> data , type -> staticsSize );
176
+ memcpy (type -> statics , statics_data , type -> staticsSize );
156
177
}
157
178
158
179
baseClass = mono_class_get_parent (klass );
@@ -165,15 +186,14 @@ static void AddMetadataType (gpointer key, gpointer value, gpointer user_data)
165
186
type -> size = (klass -> valuetype ) != 0 ? (mono_class_instance_size (klass ) - sizeof (MonoObject )) : mono_class_instance_size (klass );
166
187
}
167
188
168
-
169
189
static void CollectMetadata (MonoMetadataSnapshot * metadata )
170
190
{
171
191
CollectMetadataContext context ;
172
192
173
193
context .allTypes = g_hash_table_new (NULL , NULL );
174
194
context .currentIndex = 0 ;
175
195
context .metadata = metadata ;
176
-
196
+
177
197
mono_assembly_foreach ((GFunc )CollectAssemblyMetaData , & context );
178
198
179
199
mono_metadata_generic_class_foreach (CollectGenericClass , & context );
0 commit comments