[runtime] Fix locking issues while accessing MonoClass bitfields. (#4275)
[mono.git] / mono / metadata / class-accessors.c
1 /*
2  * Copyright 2016 Microsoft
3  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
4  */
5 #include <mono/metadata/class-internals.h>
6 #include <mono/metadata/tabledefs.h>
7
8
9 typedef enum {
10         PROP_MARSHAL_INFO = 1, /* MonoMarshalType */
11         PROP_REF_INFO_HANDLE = 2, /* gchandle */
12         PROP_EXCEPTION_DATA = 3, /* MonoErrorBoxed* */
13         PROP_NESTED_CLASSES = 4, /* GList* */
14         PROP_PROPERTY_INFO = 5, /* MonoClassPropertyInfo* */
15         PROP_EVENT_INFO = 6, /* MonoClassEventInfo* */
16         PROP_FIELD_DEF_VALUES = 7, /* MonoFieldDefaultValue* */
17         PROP_DECLSEC_FLAGS = 8 /* guint32 */
18 }  InfrequentDataKind;
19
20 /* Accessors based on class kind*/
21
22 /*
23 * mono_class_get_generic_class:
24 *
25 *   Return the MonoGenericClass of @klass, which MUST be a generic instance.
26 */
27 MonoGenericClass*
28 mono_class_get_generic_class (MonoClass *klass)
29 {
30         g_assert (mono_class_is_ginst (klass));
31         return ((MonoClassGenericInst*)klass)->generic_class;
32 }
33
34 /*
35 * mono_class_try_get_generic_class:
36 *
37 *   Return the MonoGenericClass if @klass is a ginst, NULL otherwise
38 */
39 MonoGenericClass*
40 mono_class_try_get_generic_class (MonoClass *klass)
41 {
42         if (mono_class_is_ginst (klass))
43                 return ((MonoClassGenericInst*)klass)->generic_class;
44         return NULL;
45 }
46
47 /**
48  * mono_class_get_flags:
49  * @klass: the MonoClass to act on
50  *
51  * Return the TypeAttributes flags of @klass.
52  * See the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the different values.
53  *
54  * Returns: The type flags
55  */
56 guint32
57 mono_class_get_flags (MonoClass *klass)
58 {
59         switch (klass->class_kind) {
60         case MONO_CLASS_DEF:
61         case MONO_CLASS_GTD:
62                 return ((MonoClassDef*)klass)->flags;
63         case MONO_CLASS_GINST:
64                 return mono_class_get_flags (((MonoClassGenericInst*)klass)->generic_class->container_class);
65         case MONO_CLASS_GPARAM:
66                 return TYPE_ATTRIBUTE_PUBLIC;
67         case MONO_CLASS_ARRAY:
68                 /* all arrays are marked serializable and sealed, bug #42779 */
69                 return TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
70         case MONO_CLASS_POINTER:
71                 return TYPE_ATTRIBUTE_CLASS | (mono_class_get_flags (klass->element_class) & TYPE_ATTRIBUTE_VISIBILITY_MASK);
72         }
73         g_assert_not_reached ();
74 }
75
76 void
77 mono_class_set_flags (MonoClass *klass, guint32 flags)
78 {
79         g_assert (klass->class_kind == MONO_CLASS_DEF || klass->class_kind == MONO_CLASS_GTD);
80         ((MonoClassDef*)klass)->flags = flags;
81 }
82
83 /*
84  * mono_class_get_generic_container:
85  *
86  *   Return the generic container of KLASS which should be a generic type definition.
87  */
88 MonoGenericContainer*
89 mono_class_get_generic_container (MonoClass *klass)
90 {
91         g_assert (mono_class_is_gtd (klass));
92
93         return ((MonoClassGtd*)klass)->generic_container;
94 }
95
96 MonoGenericContainer*
97 mono_class_try_get_generic_container (MonoClass *klass)
98 {
99         if (mono_class_is_gtd (klass))
100                 return ((MonoClassGtd*)klass)->generic_container;
101         return NULL;
102 }
103
104
105 void
106 mono_class_set_generic_container (MonoClass *klass, MonoGenericContainer *container)
107 {
108         g_assert (mono_class_is_gtd (klass));
109
110         ((MonoClassGtd*)klass)->generic_container = container;
111 }
112
113 /*
114  * mono_class_get_first_method_idx:
115  *
116  *   Return the table index of the first method for metadata classes.
117  */
118 guint32
119 mono_class_get_first_method_idx (MonoClass *klass)
120 {
121         g_assert (mono_class_has_static_metadata (klass));
122
123         return ((MonoClassDef*)klass)->first_method_idx;
124 }
125
126 void
127 mono_class_set_first_method_idx (MonoClass *klass, guint32 idx)
128 {
129         g_assert (mono_class_has_static_metadata (klass));
130
131         ((MonoClassDef*)klass)->first_method_idx = idx;
132 }
133
134 guint32
135 mono_class_get_first_field_idx (MonoClass *klass)
136 {
137         if (mono_class_is_ginst (klass))
138                 return mono_class_get_first_field_idx (mono_class_get_generic_class (klass)->container_class);
139
140         g_assert (mono_class_has_static_metadata (klass));
141
142         return ((MonoClassDef*)klass)->first_field_idx;
143 }
144
145 void
146 mono_class_set_first_field_idx (MonoClass *klass, guint32 idx)
147 {
148         g_assert (mono_class_has_static_metadata (klass));
149
150         ((MonoClassDef*)klass)->first_field_idx = idx;
151 }
152
153 guint32
154 mono_class_get_method_count (MonoClass *klass)
155 {
156         switch (klass->class_kind) {
157         case MONO_CLASS_DEF:
158         case MONO_CLASS_GTD:
159                 return ((MonoClassDef*)klass)->method_count;
160         case MONO_CLASS_GINST:
161                 return mono_class_get_method_count (((MonoClassGenericInst*)klass)->generic_class->container_class);
162         case MONO_CLASS_GPARAM:
163                 return 0;
164         case MONO_CLASS_ARRAY:
165                 return ((MonoClassArray*)klass)->method_count;
166         case MONO_CLASS_POINTER:
167                 return 0;
168         default:
169                 g_assert_not_reached ();
170                 return 0;
171         }
172 }
173
174 void
175 mono_class_set_method_count (MonoClass *klass, guint32 count)
176 {
177         switch (klass->class_kind) {
178         case MONO_CLASS_DEF:
179         case MONO_CLASS_GTD:
180                 ((MonoClassDef*)klass)->method_count = count;
181                 break;
182         case MONO_CLASS_GINST:
183                 break;
184         case MONO_CLASS_GPARAM:
185         case MONO_CLASS_POINTER:
186                 g_assert (count == 0);
187                 break;
188         case MONO_CLASS_ARRAY:
189                 ((MonoClassArray*)klass)->method_count = count;
190                 break;
191         default:
192                 g_assert_not_reached ();
193                 break;
194         }
195 }
196
197 guint32
198 mono_class_get_field_count (MonoClass *klass)
199 {
200         switch (klass->class_kind) {
201         case MONO_CLASS_DEF:
202         case MONO_CLASS_GTD:
203                 return ((MonoClassDef*)klass)->field_count;
204         case MONO_CLASS_GINST:
205                 return mono_class_get_field_count (((MonoClassGenericInst*)klass)->generic_class->container_class);
206         case MONO_CLASS_GPARAM:
207         case MONO_CLASS_ARRAY:
208         case MONO_CLASS_POINTER:
209                 return 0;
210         default:
211                 g_assert_not_reached ();
212                 return 0;
213         }
214 }
215
216 void
217 mono_class_set_field_count (MonoClass *klass, guint32 count)
218 {
219         switch (klass->class_kind) {
220         case MONO_CLASS_DEF:
221         case MONO_CLASS_GTD:
222                 ((MonoClassDef*)klass)->field_count = count;
223                 break;
224         case MONO_CLASS_GINST:
225                 break;
226         case MONO_CLASS_GPARAM:
227         case MONO_CLASS_ARRAY:
228         case MONO_CLASS_POINTER:
229                 g_assert (count == 0);
230                 break;
231         default:
232                 g_assert_not_reached ();
233                 break;
234         }
235 }
236
237 MonoMarshalType*
238 mono_class_get_marshal_info (MonoClass *class)
239 {
240         return mono_property_bag_get (&class->infrequent_data, PROP_MARSHAL_INFO);
241 }
242
243 void
244 mono_class_set_marshal_info (MonoClass *class, MonoMarshalType *marshal_info)
245 {
246         marshal_info->head.tag = PROP_MARSHAL_INFO;
247         mono_property_bag_add (&class->infrequent_data, marshal_info);
248 }
249
250 typedef struct {
251         MonoPropertyBagItem head;
252         guint32 value;
253 } Uint32Property;
254
255 guint32
256 mono_class_get_ref_info_handle (MonoClass *class)
257 {
258         Uint32Property *prop = mono_property_bag_get (&class->infrequent_data, PROP_REF_INFO_HANDLE);
259         return prop ? prop->value : 0;
260 }
261
262 guint32
263 mono_class_set_ref_info_handle (MonoClass *class, guint32 value)
264 {
265         if (!value) {
266                 Uint32Property *prop = mono_property_bag_get (&class->infrequent_data, PROP_REF_INFO_HANDLE);
267                 if (prop)
268                         prop->value = 0;
269                 return 0;
270         }
271
272         Uint32Property *prop = mono_class_alloc (class, sizeof (Uint32Property));
273         prop->head.tag = PROP_REF_INFO_HANDLE;
274         prop->value = value;
275         prop = mono_property_bag_add (&class->infrequent_data, prop);
276         return prop->value;
277 }
278
279 typedef struct {
280         MonoPropertyBagItem head;
281         gpointer value;
282 } PointerProperty;
283
284 static void
285 set_pointer_property (MonoClass *klass, InfrequentDataKind property, gpointer value)
286 {
287         PointerProperty *prop = mono_class_alloc (klass, sizeof (PointerProperty));
288         prop->head.tag = property;
289         prop->value = value;
290         mono_property_bag_add (&klass->infrequent_data, prop);
291 }
292
293 static gpointer
294 get_pointer_property (MonoClass *klass, InfrequentDataKind property)
295 {
296         PointerProperty *prop = (PointerProperty*)mono_property_bag_get (&klass->infrequent_data, property);
297         return prop ? prop->value : NULL;
298 }
299
300 MonoErrorBoxed*
301 mono_class_get_exception_data (MonoClass *klass)
302 {
303         return (MonoErrorBoxed*)get_pointer_property (klass, PROP_EXCEPTION_DATA);
304 }
305
306 void
307 mono_class_set_exception_data (MonoClass *klass, MonoErrorBoxed *value)
308 {
309         set_pointer_property (klass, PROP_EXCEPTION_DATA, value);
310 }
311
312 GList*
313 mono_class_get_nested_classes_property (MonoClass *klass)
314 {
315         return (GList*)get_pointer_property (klass, PROP_NESTED_CLASSES);
316 }
317
318 void
319 mono_class_set_nested_classes_property (MonoClass *klass, GList *value)
320 {
321         set_pointer_property (klass, PROP_NESTED_CLASSES, value);
322 }
323
324 MonoClassPropertyInfo*
325 mono_class_get_property_info (MonoClass *klass)
326 {
327         return mono_property_bag_get (&klass->infrequent_data, PROP_PROPERTY_INFO);
328 }
329
330 void
331 mono_class_set_property_info (MonoClass *klass, MonoClassPropertyInfo *info)
332 {
333         info->head.tag = PROP_PROPERTY_INFO;
334         mono_property_bag_add (&klass->infrequent_data, info);
335 }
336
337 MonoClassEventInfo*
338 mono_class_get_event_info (MonoClass *klass)
339 {
340         return mono_property_bag_get (&klass->infrequent_data, PROP_EVENT_INFO);
341 }
342
343 void
344 mono_class_set_event_info (MonoClass *klass, MonoClassEventInfo *info)
345 {
346         info->head.tag = PROP_EVENT_INFO;
347         mono_property_bag_add (&klass->infrequent_data, info);
348 }
349
350 MonoFieldDefaultValue*
351 mono_class_get_field_def_values (MonoClass *klass)
352 {
353         return (MonoFieldDefaultValue*)get_pointer_property (klass, PROP_FIELD_DEF_VALUES);
354 }
355
356 void
357 mono_class_set_field_def_values (MonoClass *klass, MonoFieldDefaultValue *values)
358 {
359         set_pointer_property (klass, PROP_FIELD_DEF_VALUES, values);
360 }
361
362 guint32
363 mono_class_get_declsec_flags (MonoClass *class)
364 {
365         Uint32Property *prop = mono_property_bag_get (&class->infrequent_data, PROP_DECLSEC_FLAGS);
366         return prop ? prop->value : 0;
367 }
368
369 void
370 mono_class_set_declsec_flags (MonoClass *class, guint32 value)
371 {
372         Uint32Property *prop = mono_class_alloc (class, sizeof (Uint32Property));
373         prop->head.tag = PROP_DECLSEC_FLAGS;
374         prop->value = value;
375         mono_property_bag_add (&class->infrequent_data, prop);
376 }
377
378 void
379 mono_class_set_is_com_object (MonoClass *klass)
380 {
381 #ifndef DISABLE_COM
382         mono_loader_lock ();
383         klass->is_com_object = 1;
384         mono_loader_unlock ();
385 #endif
386 }