Reduce TLS accesses. (#11487)
[mono-project.git] / mono / metadata / class-accessors.c
blobf377383a25c927fa9e6e78fbfce9763f000f9e3a
1 /**
2 * \file
3 * Copyright 2016 Microsoft
4 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
5 */
6 #include <config.h>
7 #include <mono/metadata/class-internals.h>
8 #include <mono/metadata/marshal.h>
9 #include <mono/metadata/tabledefs.h>
10 #include <mono/metadata/class-abi-details.h>
11 #ifdef MONO_CLASS_DEF_PRIVATE
12 #include <mono/metadata/abi-details.h>
13 #define REALLY_INCLUDE_CLASS_DEF 1
14 #include <mono/metadata/class-private-definition.h>
15 #undef REALLY_INCLUDE_CLASS_DEF
16 #endif
18 typedef enum {
19 PROP_MARSHAL_INFO = 1, /* MonoMarshalType */
20 PROP_REF_INFO_HANDLE = 2, /* gchandle */
21 PROP_EXCEPTION_DATA = 3, /* MonoErrorBoxed* */
22 PROP_NESTED_CLASSES = 4, /* GList* */
23 PROP_PROPERTY_INFO = 5, /* MonoClassPropertyInfo* */
24 PROP_EVENT_INFO = 6, /* MonoClassEventInfo* */
25 PROP_FIELD_DEF_VALUES = 7, /* MonoFieldDefaultValue* */
26 PROP_DECLSEC_FLAGS = 8, /* guint32 */
27 PROP_WEAK_BITMAP = 9,
28 PROP_DIM_CONFLICTS = 10 /* GSList of MonoMethod* */
29 } InfrequentDataKind;
31 /* Accessors based on class kind*/
34 * mono_class_get_generic_class:
36 * Return the MonoGenericClass of @klass, which MUST be a generic instance.
38 MonoGenericClass*
39 mono_class_get_generic_class (MonoClass *klass)
41 g_assert (mono_class_is_ginst (klass));
42 return m_classgenericinst_get_generic_class ((MonoClassGenericInst*)klass);
46 * mono_class_try_get_generic_class:
48 * Return the MonoGenericClass if @klass is a ginst, NULL otherwise
50 MonoGenericClass*
51 mono_class_try_get_generic_class (MonoClass *klass)
53 if (mono_class_is_ginst (klass))
54 return m_classgenericinst_get_generic_class ((MonoClassGenericInst*)klass);
55 return NULL;
58 /**
59 * mono_class_get_flags:
60 * \param klass the MonoClass to act on
61 * \returns the \c TypeAttributes flags of \p klass.
62 * See the \c TYPE_ATTRIBUTE_* definitions in \c tabledefs.h for the different values.
64 guint32
65 mono_class_get_flags (MonoClass *klass)
67 switch (m_class_get_class_kind (klass)) {
68 case MONO_CLASS_DEF:
69 case MONO_CLASS_GTD:
70 return m_classdef_get_flags ((MonoClassDef*)klass);
71 case MONO_CLASS_GINST:
72 return mono_class_get_flags (m_classgenericinst_get_generic_class ((MonoClassGenericInst*)klass)->container_class);
73 case MONO_CLASS_GPARAM:
74 return TYPE_ATTRIBUTE_PUBLIC;
75 case MONO_CLASS_ARRAY:
76 /* all arrays are marked serializable and sealed, bug #42779 */
77 return TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
78 case MONO_CLASS_POINTER:
79 return TYPE_ATTRIBUTE_CLASS | (mono_class_get_flags (m_class_get_element_class (klass)) & TYPE_ATTRIBUTE_VISIBILITY_MASK);
81 g_assert_not_reached ();
84 void
85 mono_class_set_flags (MonoClass *klass, guint32 flags)
87 g_assert (m_class_get_class_kind (klass) == MONO_CLASS_DEF || m_class_get_class_kind (klass) == MONO_CLASS_GTD);
88 ((MonoClassDef*)klass)->flags = flags;
92 * mono_class_get_generic_container:
94 * Return the generic container of KLASS which should be a generic type definition.
96 MonoGenericContainer*
97 mono_class_get_generic_container (MonoClass *klass)
99 g_assert (mono_class_is_gtd (klass));
101 return m_classgtd_get_generic_container ((MonoClassGtd*)klass);
104 MonoGenericContainer*
105 mono_class_try_get_generic_container (MonoClass *klass)
107 if (mono_class_is_gtd (klass))
108 return m_classgtd_get_generic_container ((MonoClassGtd*)klass);
109 return NULL;
112 void
113 mono_class_set_generic_container (MonoClass *klass, MonoGenericContainer *container)
115 g_assert (mono_class_is_gtd (klass));
117 ((MonoClassGtd*)klass)->generic_container = container;
121 * mono_class_get_first_method_idx:
123 * Return the table index of the first method for metadata classes.
125 guint32
126 mono_class_get_first_method_idx (MonoClass *klass)
128 g_assert (mono_class_has_static_metadata (klass));
130 return m_classdef_get_first_method_idx ((MonoClassDef*)klass);
133 void
134 mono_class_set_first_method_idx (MonoClass *klass, guint32 idx)
136 g_assert (mono_class_has_static_metadata (klass));
138 ((MonoClassDef*)klass)->first_method_idx = idx;
141 guint32
142 mono_class_get_first_field_idx (MonoClass *klass)
144 if (mono_class_is_ginst (klass))
145 return mono_class_get_first_field_idx (mono_class_get_generic_class (klass)->container_class);
147 g_assert (klass->type_token && !mono_class_is_ginst (klass));
149 return m_classdef_get_first_field_idx ((MonoClassDef*)klass);
152 void
153 mono_class_set_first_field_idx (MonoClass *klass, guint32 idx)
155 g_assert (klass->type_token && !mono_class_is_ginst (klass));
157 ((MonoClassDef*)klass)->first_field_idx = idx;
160 guint32
161 mono_class_get_method_count (MonoClass *klass)
163 switch (m_class_get_class_kind (klass)) {
164 case MONO_CLASS_DEF:
165 case MONO_CLASS_GTD:
166 return m_classdef_get_method_count ((MonoClassDef*)klass);
167 case MONO_CLASS_GINST:
168 return mono_class_get_method_count (m_classgenericinst_get_generic_class ((MonoClassGenericInst*)klass)->container_class);
169 case MONO_CLASS_GPARAM:
170 return 0;
171 case MONO_CLASS_ARRAY:
172 return m_classarray_get_method_count ((MonoClassArray*)klass);
173 case MONO_CLASS_POINTER:
174 return 0;
175 default:
176 g_assert_not_reached ();
177 return 0;
181 void
182 mono_class_set_method_count (MonoClass *klass, guint32 count)
184 switch (m_class_get_class_kind (klass)) {
185 case MONO_CLASS_DEF:
186 case MONO_CLASS_GTD:
187 ((MonoClassDef*)klass)->method_count = count;
188 break;
189 case MONO_CLASS_GINST:
190 break;
191 case MONO_CLASS_GPARAM:
192 case MONO_CLASS_POINTER:
193 g_assert (count == 0);
194 break;
195 case MONO_CLASS_ARRAY:
196 ((MonoClassArray*)klass)->method_count = count;
197 break;
198 default:
199 g_assert_not_reached ();
200 break;
204 guint32
205 mono_class_get_field_count (MonoClass *klass)
207 switch (m_class_get_class_kind (klass)) {
208 case MONO_CLASS_DEF:
209 case MONO_CLASS_GTD:
210 return m_classdef_get_field_count ((MonoClassDef*)klass);
211 case MONO_CLASS_GINST:
212 return mono_class_get_field_count (m_classgenericinst_get_generic_class ((MonoClassGenericInst*)klass)->container_class);
213 case MONO_CLASS_GPARAM:
214 case MONO_CLASS_ARRAY:
215 case MONO_CLASS_POINTER:
216 return 0;
217 default:
218 g_assert_not_reached ();
219 return 0;
223 void
224 mono_class_set_field_count (MonoClass *klass, guint32 count)
226 switch (m_class_get_class_kind (klass)) {
227 case MONO_CLASS_DEF:
228 case MONO_CLASS_GTD:
229 ((MonoClassDef*)klass)->field_count = count;
230 break;
231 case MONO_CLASS_GINST:
232 break;
233 case MONO_CLASS_GPARAM:
234 case MONO_CLASS_ARRAY:
235 case MONO_CLASS_POINTER:
236 g_assert (count == 0);
237 break;
238 default:
239 g_assert_not_reached ();
240 break;
244 MonoMarshalType*
245 mono_class_get_marshal_info (MonoClass *klass)
247 return (MonoMarshalType*)mono_property_bag_get (m_class_get_infrequent_data (klass), PROP_MARSHAL_INFO);
250 void
251 mono_class_set_marshal_info (MonoClass *klass, MonoMarshalType *marshal_info)
253 marshal_info->head.tag = PROP_MARSHAL_INFO;
254 mono_property_bag_add (m_class_get_infrequent_data (klass), marshal_info);
257 typedef struct {
258 MonoPropertyBagItem head;
259 guint32 value;
260 } Uint32Property;
262 guint32
263 mono_class_get_ref_info_handle (MonoClass *klass)
265 Uint32Property *prop = (Uint32Property*)mono_property_bag_get (m_class_get_infrequent_data (klass), PROP_REF_INFO_HANDLE);
266 return prop ? prop->value : 0;
269 guint32
270 mono_class_set_ref_info_handle (MonoClass *klass, guint32 value)
272 if (!value) {
273 Uint32Property *prop = (Uint32Property*)mono_property_bag_get (m_class_get_infrequent_data (klass), PROP_REF_INFO_HANDLE);
274 if (prop)
275 prop->value = 0;
276 return 0;
279 Uint32Property *prop = (Uint32Property*)mono_class_alloc (klass, sizeof (Uint32Property));
280 prop->head.tag = PROP_REF_INFO_HANDLE;
281 prop->value = value;
282 prop = (Uint32Property*)mono_property_bag_add (m_class_get_infrequent_data (klass), prop);
283 return prop->value;
286 typedef struct {
287 MonoPropertyBagItem head;
288 gpointer value;
289 } PointerProperty;
291 static void
292 set_pointer_property (MonoClass *klass, InfrequentDataKind property, gpointer value)
294 PointerProperty *prop = (PointerProperty*)mono_class_alloc (klass, sizeof (PointerProperty));
295 prop->head.tag = property;
296 prop->value = value;
297 mono_property_bag_add (m_class_get_infrequent_data (klass), prop);
300 static gpointer
301 get_pointer_property (MonoClass *klass, InfrequentDataKind property)
303 PointerProperty *prop = (PointerProperty*)mono_property_bag_get (m_class_get_infrequent_data (klass), property);
304 return prop ? prop->value : NULL;
307 MonoErrorBoxed*
308 mono_class_get_exception_data (MonoClass *klass)
310 return (MonoErrorBoxed*)get_pointer_property (klass, PROP_EXCEPTION_DATA);
313 void
314 mono_class_set_exception_data (MonoClass *klass, MonoErrorBoxed *value)
316 set_pointer_property (klass, PROP_EXCEPTION_DATA, value);
319 GList*
320 mono_class_get_nested_classes_property (MonoClass *klass)
322 return (GList*)get_pointer_property (klass, PROP_NESTED_CLASSES);
325 void
326 mono_class_set_nested_classes_property (MonoClass *klass, GList *value)
328 set_pointer_property (klass, PROP_NESTED_CLASSES, value);
331 MonoClassPropertyInfo*
332 mono_class_get_property_info (MonoClass *klass)
334 return (MonoClassPropertyInfo*)mono_property_bag_get (m_class_get_infrequent_data (klass), PROP_PROPERTY_INFO);
337 void
338 mono_class_set_property_info (MonoClass *klass, MonoClassPropertyInfo *info)
340 info->head.tag = PROP_PROPERTY_INFO;
341 mono_property_bag_add (m_class_get_infrequent_data (klass), info);
344 MonoClassEventInfo*
345 mono_class_get_event_info (MonoClass *klass)
347 return (MonoClassEventInfo*)mono_property_bag_get (m_class_get_infrequent_data (klass), PROP_EVENT_INFO);
350 void
351 mono_class_set_event_info (MonoClass *klass, MonoClassEventInfo *info)
353 info->head.tag = PROP_EVENT_INFO;
354 mono_property_bag_add (m_class_get_infrequent_data (klass), info);
357 MonoFieldDefaultValue*
358 mono_class_get_field_def_values (MonoClass *klass)
360 return (MonoFieldDefaultValue*)get_pointer_property (klass, PROP_FIELD_DEF_VALUES);
363 void
364 mono_class_set_field_def_values (MonoClass *klass, MonoFieldDefaultValue *values)
366 set_pointer_property (klass, PROP_FIELD_DEF_VALUES, values);
369 guint32
370 mono_class_get_declsec_flags (MonoClass *klass)
372 Uint32Property *prop = (Uint32Property*)mono_property_bag_get (m_class_get_infrequent_data (klass), PROP_DECLSEC_FLAGS);
373 return prop ? prop->value : 0;
376 void
377 mono_class_set_declsec_flags (MonoClass *klass, guint32 value)
379 Uint32Property *prop = (Uint32Property*)mono_class_alloc (klass, sizeof (Uint32Property));
380 prop->head.tag = PROP_DECLSEC_FLAGS;
381 prop->value = value;
382 mono_property_bag_add (m_class_get_infrequent_data (klass), prop);
385 void
386 mono_class_set_is_com_object (MonoClass *klass)
388 #ifndef DISABLE_COM
389 mono_loader_lock ();
390 klass->is_com_object = 1;
391 mono_loader_unlock ();
392 #endif
395 MonoType*
396 mono_class_gtd_get_canonical_inst (MonoClass *klass)
398 g_assert (mono_class_is_gtd (klass));
399 return m_classgtd_get_canonical_inst ((MonoClassGtd*)klass);
402 typedef struct {
403 MonoPropertyBagItem head;
405 int nbits;
406 gsize *bits;
407 } WeakBitmapData;
409 void
410 mono_class_set_weak_bitmap (MonoClass *klass, int nbits, gsize *bits)
412 WeakBitmapData *info = (WeakBitmapData *)mono_class_alloc (klass, sizeof (WeakBitmapData));
413 info->nbits = nbits;
414 info->bits = bits;
416 info->head.tag = PROP_WEAK_BITMAP;
417 mono_property_bag_add (m_class_get_infrequent_data (klass), info);
420 gsize*
421 mono_class_get_weak_bitmap (MonoClass *klass, int *nbits)
423 WeakBitmapData *prop = (WeakBitmapData*)mono_property_bag_get (m_class_get_infrequent_data (klass), PROP_WEAK_BITMAP);
425 g_assert (prop);
426 *nbits = prop->nbits;
427 return prop->bits;
430 gboolean
431 mono_class_has_dim_conflicts (MonoClass *klass)
433 if (klass->has_dim_conflicts)
434 return TRUE;
436 if (mono_class_is_ginst (klass)) {
437 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
439 return gklass->has_dim_conflicts;
442 return FALSE;
445 typedef struct {
446 MonoPropertyBagItem head;
448 GSList *data;
449 } DimConflictData;
451 void
452 mono_class_set_dim_conflicts (MonoClass *klass, GSList *conflicts)
454 DimConflictData *info = (DimConflictData*)mono_class_alloc (klass, sizeof (DimConflictData));
455 info->data = conflicts;
457 g_assert (!mono_class_is_ginst (klass));
459 info->head.tag = PROP_DIM_CONFLICTS;
460 mono_property_bag_add (&klass->infrequent_data, info);
463 GSList*
464 mono_class_get_dim_conflicts (MonoClass *klass)
466 if (mono_class_is_ginst (klass))
467 return mono_class_get_dim_conflicts (mono_class_get_generic_class (klass)->container_class);
469 DimConflictData *info = (DimConflictData*)mono_property_bag_get (&klass->infrequent_data, PROP_DIM_CONFLICTS);
471 g_assert (info);
472 return info->data;
476 * mono_class_set_failure:
477 * \param klass class in which the failure was detected
478 * \param ex_type the kind of exception/error to be thrown (later)
479 * \param ex_data exception data (specific to each type of exception/error)
481 * Keep a detected failure informations in the class for later processing.
482 * Note that only the first failure is kept.
484 * LOCKING: Acquires the loader lock.
486 gboolean
487 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
489 g_assert (boxed_error != NULL);
491 if (mono_class_has_failure (klass))
492 return FALSE;
494 mono_loader_lock ();
495 klass->has_failure = 1;
496 mono_class_set_exception_data (klass, boxed_error);
497 mono_loader_unlock ();
499 return TRUE;
503 * mono_class_set_nonblittable:
504 * \param klass class which will be marked as not blittable.
506 * Mark \c klass as not blittable.
508 * LOCKING: Acquires the loader lock.
510 void
511 mono_class_set_nonblittable (MonoClass *klass) {
512 mono_loader_lock ();
513 klass->blittable = FALSE;
514 mono_loader_unlock ();
517 #ifndef DISABLE_REMOTING
518 void
519 mono_class_contextbound_bit_offset (int* byte_offset_out, guint8* mask_out) {
520 mono_marshal_find_bitfield_offset (MonoClass, contextbound, byte_offset_out, mask_out);
522 #endif
525 * mono_class_publish_gc_descriptor:
526 * \param klass the \c MonoClass whose GC descriptor is to be set
527 * \param gc_descr the GC descriptor for \p klass
529 * Sets the \c gc_descr_inited and \c gc_descr fields of \p klass.
530 * \returns previous value of \c klass->gc_descr_inited
532 * LOCKING: Acquires the loader lock.
534 gboolean
535 mono_class_publish_gc_descriptor (MonoClass *klass, MonoGCDescriptor gc_descr)
537 gboolean ret;
538 mono_loader_lock ();
539 ret = klass->gc_descr_inited;
540 klass->gc_descr = gc_descr;
541 mono_memory_barrier ();
542 klass->gc_descr_inited = TRUE;
543 mono_loader_unlock ();
544 return ret;
547 #ifdef MONO_CLASS_DEF_PRIVATE
548 #define MONO_CLASS_GETTER(funcname, rettype, optref, argtype, fieldname) rettype funcname (argtype *klass) { return optref klass-> fieldname ; }
549 #define MONO_CLASS_OFFSET(funcname, argtype, fieldname) intptr_t funcname (void) { return MONO_STRUCT_OFFSET (argtype, fieldname); }
550 #include "class-getters.h"
551 #undef MONO_CLASS_GETTER
552 #undef MONO_CLASS_OFFSET
553 #endif /* MONO_CLASS_DEF_PRIVATE */