2 * \file MonoClass construction and initialization
4 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
5 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
6 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
7 * Copyright 2018 Microsoft
8 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
11 #include <mono/metadata/class-init.h>
12 #include <mono/metadata/class-init-internals.h>
13 #include <mono/metadata/class-internals.h>
14 #include <mono/metadata/custom-attrs-internals.h>
15 #include <mono/metadata/debug-helpers.h>
16 #include <mono/metadata/exception-internals.h>
17 #include <mono/metadata/gc-internals.h>
18 #include <mono/metadata/object-internals.h>
19 #include <mono/metadata/profiler-private.h>
20 #include <mono/metadata/security-core-clr.h>
21 #include <mono/metadata/security-manager.h>
22 #include <mono/metadata/verify-internals.h>
23 #include <mono/metadata/abi-details.h>
24 #include <mono/utils/checked-build.h>
25 #include <mono/utils/mono-counters.h>
26 #include <mono/utils/mono-error-internals.h>
27 #include <mono/utils/mono-logger-internals.h>
28 #include <mono/utils/mono-memory-model.h>
29 #include <mono/utils/unlocked.h>
30 #ifdef MONO_CLASS_DEF_PRIVATE
31 /* Class initialization gets to see the fields of MonoClass */
32 #define REALLY_INCLUDE_CLASS_DEF 1
33 #include <mono/metadata/class-private-definition.h>
34 #undef REALLY_INCLUDE_CLASS_DEF
38 #define FEATURE_COVARIANT_RETURNS
41 gboolean mono_print_vtable
= FALSE
;
42 gboolean mono_align_small_structs
= FALSE
;
45 gint32 mono_simd_register_size
;
49 static gint32 classes_size
;
50 static gint32 inflated_classes_size
;
51 gint32 mono_inflated_methods_size
;
52 static gint32 class_def_count
, class_gtd_count
, class_ginst_count
, class_gparam_count
, class_array_count
, class_pointer_count
;
54 /* Low level lock which protects data structures in this module */
55 static mono_mutex_t classes_mutex
;
57 static gboolean
class_kind_may_contain_generic_instances (MonoTypeKind kind
);
58 static void mono_generic_class_setup_parent (MonoClass
*klass
, MonoClass
*gtd
);
59 static int generic_array_methods (MonoClass
*klass
);
60 static void setup_generic_array_ifaces (MonoClass
*klass
, MonoClass
*iface
, MonoMethod
**methods
, int pos
, GHashTable
*cache
);
61 static gboolean
class_has_isbyreflike_attribute (MonoClass
*klass
);
63 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
64 static MonoNativeTlsKey setup_fields_tls_id
;
66 static MonoNativeTlsKey init_pending_tls_id
;
71 mono_locks_os_acquire (&classes_mutex
, ClassesLock
);
77 mono_locks_os_release (&classes_mutex
, ClassesLock
);
81 We use gclass recording to allow recursive system f types to be referenced by a parent.
83 Given the following type hierarchy:
85 class TextBox : TextBoxBase<TextBox> {}
86 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
87 class TextInput<T> : Input<T> where T: TextInput<T> {}
90 The runtime tries to load TextBoxBase<>.
91 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
92 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
93 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
95 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
96 at this point, iow, both are registered in the type map and both and a NULL parent. This means
97 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
99 To fix that what we do is to record all generic instantes created while resolving the parent of
100 any generic type definition and, after resolved, correct the parent field if needed.
103 static int record_gclass_instantiation
;
104 static GSList
*gclass_recorded_list
;
105 typedef gboolean (*gclass_record_func
) (MonoClass
*, void*);
108 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
111 enable_gclass_recording (void)
113 ++record_gclass_instantiation
;
117 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
120 disable_gclass_recording (gclass_record_func func
, void *user_data
)
122 GSList
**head
= &gclass_recorded_list
;
124 g_assert (record_gclass_instantiation
> 0);
125 --record_gclass_instantiation
;
128 GSList
*node
= *head
;
129 if (func ((MonoClass
*)node
->data
, user_data
)) {
131 g_slist_free_1 (node
);
137 /* We automatically discard all recorded gclasses when disabled. */
138 if (!record_gclass_instantiation
&& gclass_recorded_list
) {
139 g_slist_free (gclass_recorded_list
);
140 gclass_recorded_list
= NULL
;
144 #define mono_class_new0(klass,struct_type, n_structs) \
145 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
148 * mono_class_setup_basic_field_info:
149 * \param class The class to initialize
151 * Initializes the following fields in MonoClass:
152 * * klass->fields (only field->parent and field->name)
153 * * klass->field.count
154 * * klass->first_field_idx
155 * LOCKING: Acquires the loader lock
158 mono_class_setup_basic_field_info (MonoClass
*klass
)
160 MonoGenericClass
*gklass
;
161 MonoClassField
*field
;
162 MonoClassField
*fields
;
170 gklass
= mono_class_try_get_generic_class (klass
);
171 gtd
= gklass
? mono_class_get_generic_type_definition (klass
) : NULL
;
172 image
= klass
->image
;
175 if (gklass
&& image_is_dynamic (gklass
->container_class
->image
) && !gklass
->container_class
->wastypebuilder
) {
177 * This happens when a generic instance of an unfinished generic typebuilder
178 * is used as an element type for creating an array type. We can't initialize
179 * the fields of this class using the fields of gklass, since gklass is not
180 * finished yet, fields could be added to it later.
186 mono_class_setup_basic_field_info (gtd
);
189 mono_class_set_field_count (klass
, mono_class_get_field_count (gtd
));
190 mono_loader_unlock ();
193 top
= mono_class_get_field_count (klass
);
195 fields
= (MonoClassField
*)mono_class_alloc0 (klass
, sizeof (MonoClassField
) * top
);
198 * Fetch all the field information.
200 int first_field_idx
= mono_class_has_static_metadata (klass
) ? mono_class_get_first_field_idx (klass
) : 0;
201 for (i
= 0; i
< top
; i
++) {
203 field
->parent
= klass
;
206 field
->name
= mono_field_get_name (>d
->fields
[i
]);
208 int idx
= first_field_idx
+ i
;
209 /* first_field_idx and idx points into the fieldptr table */
210 guint32 name_idx
= mono_metadata_decode_table_row_col (image
, MONO_TABLE_FIELD
, idx
, MONO_FIELD_NAME
);
211 /* The name is needed for fieldrefs */
212 field
->name
= mono_metadata_string_heap (image
, name_idx
);
216 mono_memory_barrier ();
220 klass
->fields
= fields
;
221 mono_loader_unlock ();
225 * mono_class_setup_fields:
226 * \p klass The class to initialize
228 * Initializes klass->fields, computes class layout and sizes.
229 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
230 * Sets the following fields in \p klass:
231 * - all the fields initialized by mono_class_init_sizes ()
232 * - element_class/cast_class (for enums)
233 * - sizes:element_size (for arrays)
234 * - field->type/offset for all fields
237 * LOCKING: Acquires the loader lock.
240 mono_class_setup_fields (MonoClass
*klass
)
243 MonoImage
*m
= klass
->image
;
245 guint32 layout
= mono_class_get_flags (klass
) & TYPE_ATTRIBUTE_LAYOUT_MASK
;
247 guint32 real_size
= 0;
248 guint32 packing_size
= 0;
250 gboolean explicit_size
;
251 MonoClassField
*field
;
252 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
253 MonoClass
*gtd
= gklass
? mono_class_get_generic_type_definition (klass
) : NULL
;
255 if (klass
->fields_inited
)
258 if (gklass
&& image_is_dynamic (gklass
->container_class
->image
) && !gklass
->container_class
->wastypebuilder
) {
260 * This happens when a generic instance of an unfinished generic typebuilder
261 * is used as an element type for creating an array type. We can't initialize
262 * the fields of this class using the fields of gklass, since gklass is not
263 * finished yet, fields could be added to it later.
268 mono_class_setup_basic_field_info (klass
);
269 top
= mono_class_get_field_count (klass
);
272 mono_class_setup_fields (gtd
);
273 if (mono_class_set_type_load_failure_causedby_class (klass
, gtd
, "Generic type definition failed"))
279 /* For generic instances, klass->parent might not have been initialized */
280 mono_class_init_internal (klass
->parent
);
281 mono_class_setup_fields (klass
->parent
);
282 if (mono_class_set_type_load_failure_causedby_class (klass
, klass
->parent
, "Could not set up parent class"))
284 instance_size
= klass
->parent
->instance_size
;
286 instance_size
= MONO_ABI_SIZEOF (MonoObject
);
289 /* Get the real size */
290 explicit_size
= mono_metadata_packing_from_typedef (klass
->image
, klass
->type_token
, &packing_size
, &real_size
);
292 instance_size
+= real_size
;
294 #ifdef ENABLE_NETCORE
295 if (mono_is_corlib_image (klass
->image
) && !strcmp (klass
->name_space
, "System.Numerics") && !strcmp (klass
->name
, "Register")) {
296 if (mono_simd_register_size
)
297 instance_size
+= mono_simd_register_size
;
302 * This function can recursively call itself.
303 * Prevent infinite recursion by using a list in TLS.
305 GSList
*init_list
= (GSList
*)mono_native_tls_get_value (setup_fields_tls_id
);
306 if (g_slist_find (init_list
, klass
))
308 init_list
= g_slist_prepend (init_list
, klass
);
309 mono_native_tls_set_value (setup_fields_tls_id
, init_list
);
312 * Fetch all the field information.
314 int first_field_idx
= mono_class_has_static_metadata (klass
) ? mono_class_get_first_field_idx (klass
) : 0;
315 for (i
= 0; i
< top
; i
++) {
316 int idx
= first_field_idx
+ i
;
317 field
= &klass
->fields
[i
];
320 mono_field_resolve_type (field
, error
);
321 if (!is_ok (error
)) {
322 /*mono_field_resolve_type already failed class*/
323 mono_error_cleanup (error
);
327 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass
), field
->name
);
328 g_assert (field
->type
);
331 if (!mono_type_get_underlying_type (field
->type
)) {
332 mono_class_set_type_load_failure (klass
, "Field '%s' is an enum type with a bad underlying type", field
->name
);
336 if (mono_field_is_deleted (field
))
338 if (layout
== TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) {
340 mono_metadata_field_info (m
, idx
, &uoffset
, NULL
, NULL
);
341 int offset
= uoffset
;
343 if (offset
== (guint32
)-1 && !(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
344 mono_class_set_type_load_failure (klass
, "Missing field layout info for %s", field
->name
);
347 if (offset
< -1) { /*-1 is used to encode special static fields */
348 mono_class_set_type_load_failure (klass
, "Field '%s' has a negative offset %d", field
->name
, offset
);
351 if (mono_class_is_gtd (klass
)) {
352 mono_class_set_type_load_failure (klass
, "Generic class cannot have explicit layout.");
356 if (mono_type_has_exceptions (field
->type
)) {
357 char *class_name
= mono_type_get_full_name (klass
);
358 char *type_name
= mono_type_full_name (field
->type
);
360 mono_class_set_type_load_failure (klass
, "Invalid type %s for instance field %s:%s", type_name
, class_name
, field
->name
);
365 /* The def_value of fields is compute lazily during vtable creation */
368 if (!mono_class_has_failure (klass
)) {
370 mono_class_layout_fields (klass
, instance_size
, packing_size
, real_size
, FALSE
);
371 mono_loader_unlock ();
374 init_list
= g_slist_remove (init_list
, klass
);
375 mono_native_tls_set_value (setup_fields_tls_id
, init_list
);
379 discard_gclass_due_to_failure (MonoClass
*gclass
, void *user_data
)
381 return mono_class_get_generic_class (gclass
)->container_class
== user_data
;
385 fix_gclass_incomplete_instantiation (MonoClass
*gclass
, void *user_data
)
387 MonoClass
*gtd
= (MonoClass
*)user_data
;
388 /* Only try to fix generic instances of @gtd */
389 if (mono_class_get_generic_class (gclass
)->container_class
!= gtd
)
392 /* Check if the generic instance has no parent. */
393 if (gtd
->parent
&& !gclass
->parent
)
394 mono_generic_class_setup_parent (gclass
, gtd
);
400 mono_class_set_failure_and_error (MonoClass
*klass
, MonoError
*error
, const char *msg
)
402 mono_class_set_type_load_failure (klass
, "%s", msg
);
403 mono_error_set_type_load_class (error
, klass
, "%s", msg
);
407 * mono_class_create_from_typedef:
408 * \param image: image where the token is valid
409 * \param type_token: typedef token
410 * \param error: used to return any error found while creating the type
412 * Create the MonoClass* representing the specified type token.
413 * \p type_token must be a TypeDef token.
415 * FIXME: don't return NULL on failure, just let the caller figure it out.
418 mono_class_create_from_typedef (MonoImage
*image
, guint32 type_token
, MonoError
*error
)
420 MonoTableInfo
*tt
= &image
->tables
[MONO_TABLE_TYPEDEF
];
421 MonoClass
*klass
, *parent
= NULL
;
422 guint32 cols
[MONO_TYPEDEF_SIZE
];
423 guint32 cols_next
[MONO_TYPEDEF_SIZE
];
424 guint tidx
= mono_metadata_token_index (type_token
);
425 MonoGenericContext
*context
= NULL
;
426 const char *name
, *nspace
;
428 MonoClass
**interfaces
;
429 guint32 field_last
, method_last
;
430 guint32 nesting_tokeen
;
434 if (mono_metadata_token_table (type_token
) != MONO_TABLE_TYPEDEF
|| tidx
> tt
->rows
) {
435 mono_error_set_bad_image (error
, image
, "Invalid typedef token %x", type_token
);
441 if ((klass
= (MonoClass
*)mono_internal_hash_table_lookup (&image
->class_cache
, GUINT_TO_POINTER (type_token
)))) {
442 mono_loader_unlock ();
446 mono_metadata_decode_row (tt
, tidx
- 1, cols
, MONO_TYPEDEF_SIZE
);
448 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
449 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
451 if (mono_metadata_has_generic_params (image
, type_token
)) {
452 klass
= (MonoClass
*)mono_image_alloc0 (image
, sizeof (MonoClassGtd
));
453 klass
->class_kind
= MONO_CLASS_GTD
;
454 UnlockedAdd (&classes_size
, sizeof (MonoClassGtd
));
457 klass
= (MonoClass
*)mono_image_alloc0 (image
, sizeof (MonoClassDef
));
458 klass
->class_kind
= MONO_CLASS_DEF
;
459 UnlockedAdd (&classes_size
, sizeof (MonoClassDef
));
464 klass
->name_space
= nspace
;
466 MONO_PROFILER_RAISE (class_loading
, (klass
));
468 klass
->image
= image
;
469 klass
->type_token
= type_token
;
470 mono_class_set_flags (klass
, cols
[MONO_TYPEDEF_FLAGS
]);
472 mono_internal_hash_table_insert (&image
->class_cache
, GUINT_TO_POINTER (type_token
), klass
);
475 * Check whether we're a generic type definition.
477 if (mono_class_is_gtd (klass
)) {
478 MonoGenericContainer
*generic_container
= mono_metadata_load_generic_params (image
, klass
->type_token
, NULL
, klass
);
479 context
= &generic_container
->context
;
480 mono_class_set_generic_container (klass
, generic_container
);
481 MonoType
*canonical_inst
= &((MonoClassGtd
*)klass
)->canonical_inst
;
482 canonical_inst
->type
= MONO_TYPE_GENERICINST
;
483 canonical_inst
->data
.generic_class
= mono_metadata_lookup_generic_class (klass
, context
->class_inst
, FALSE
);
484 enable_gclass_recording ();
487 if (cols
[MONO_TYPEDEF_EXTENDS
]) {
489 guint32 parent_token
= mono_metadata_token_from_dor (cols
[MONO_TYPEDEF_EXTENDS
]);
491 if (mono_metadata_token_table (parent_token
) == MONO_TABLE_TYPESPEC
) {
492 /*WARNING: this must satisfy mono_metadata_type_hash*/
493 klass
->this_arg
.byref
= 1;
494 klass
->this_arg
.data
.klass
= klass
;
495 klass
->this_arg
.type
= MONO_TYPE_CLASS
;
496 klass
->_byval_arg
.data
.klass
= klass
;
497 klass
->_byval_arg
.type
= MONO_TYPE_CLASS
;
499 parent
= mono_class_get_checked (image
, parent_token
, error
);
500 if (parent
&& context
) /* Always inflate */
501 parent
= mono_class_inflate_generic_class_checked (parent
, context
, error
);
503 if (parent
== NULL
) {
504 mono_class_set_type_load_failure (klass
, "%s", mono_error_get_message (error
));
508 for (tmp
= parent
; tmp
; tmp
= tmp
->parent
) {
510 mono_class_set_failure_and_error (klass
, error
, "Cycle found while resolving parent");
513 if (mono_class_is_gtd (klass
) && mono_class_is_ginst (tmp
) && mono_class_get_generic_class (tmp
)->container_class
== klass
) {
514 mono_class_set_failure_and_error (klass
, error
, "Parent extends generic instance of this type");
520 mono_class_setup_parent (klass
, parent
);
522 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
523 mono_class_setup_mono_type (klass
);
525 if (mono_class_is_gtd (klass
))
526 disable_gclass_recording (fix_gclass_incomplete_instantiation
, klass
);
529 * This might access klass->_byval_arg for recursion generated by generic constraints,
530 * so it has to come after setup_mono_type ().
532 if ((nesting_tokeen
= mono_metadata_nested_in_typedef (image
, type_token
))) {
533 klass
->nested_in
= mono_class_create_from_typedef (image
, nesting_tokeen
, error
);
534 if (!is_ok (error
)) {
535 /*FIXME implement a mono_class_set_failure_from_mono_error */
536 mono_class_set_type_load_failure (klass
, "%s", mono_error_get_message (error
));
537 mono_loader_unlock ();
538 MONO_PROFILER_RAISE (class_failed
, (klass
));
543 if ((mono_class_get_flags (klass
) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK
) == TYPE_ATTRIBUTE_UNICODE_CLASS
)
547 if ((mono_class_get_flags (klass
) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK
) == TYPE_ATTRIBUTE_AUTO_CLASS
)
551 klass
->cast_class
= klass
->element_class
= klass
;
552 if (mono_is_corlib_image (klass
->image
)) {
553 switch (m_class_get_byval_arg (klass
)->type
) {
555 if (mono_defaults
.byte_class
)
556 klass
->cast_class
= mono_defaults
.byte_class
;
559 if (mono_defaults
.sbyte_class
)
560 mono_defaults
.sbyte_class
= klass
;
563 if (mono_defaults
.uint16_class
)
564 mono_defaults
.uint16_class
= klass
;
567 if (mono_defaults
.int16_class
)
568 klass
->cast_class
= mono_defaults
.int16_class
;
571 if (mono_defaults
.uint32_class
)
572 mono_defaults
.uint32_class
= klass
;
575 if (mono_defaults
.int32_class
)
576 klass
->cast_class
= mono_defaults
.int32_class
;
579 if (mono_defaults
.uint64_class
)
580 mono_defaults
.uint64_class
= klass
;
583 if (mono_defaults
.int64_class
)
584 klass
->cast_class
= mono_defaults
.int64_class
;
591 if (!klass
->enumtype
) {
592 if (!mono_metadata_interfaces_from_typedef_full (
593 image
, type_token
, &interfaces
, &icount
, FALSE
, context
, error
)){
595 mono_class_set_type_load_failure (klass
, "%s", mono_error_get_message (error
));
596 mono_loader_unlock ();
597 MONO_PROFILER_RAISE (class_failed
, (klass
));
601 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
602 g_assert(icount
<= 65535);
604 klass
->interfaces
= interfaces
;
605 klass
->interface_count
= icount
;
606 klass
->interfaces_inited
= 1;
609 /*g_print ("Load class %s\n", name);*/
612 * Compute the field and method lists
615 first_field_idx
= cols
[MONO_TYPEDEF_FIELD_LIST
] - 1;
616 mono_class_set_first_field_idx (klass
, first_field_idx
);
617 int first_method_idx
;
618 first_method_idx
= cols
[MONO_TYPEDEF_METHOD_LIST
] - 1;
619 mono_class_set_first_method_idx (klass
, first_method_idx
);
621 if (tt
->rows
> tidx
){
622 mono_metadata_decode_row (tt
, tidx
, cols_next
, MONO_TYPEDEF_SIZE
);
623 field_last
= cols_next
[MONO_TYPEDEF_FIELD_LIST
] - 1;
624 method_last
= cols_next
[MONO_TYPEDEF_METHOD_LIST
] - 1;
626 field_last
= image
->tables
[MONO_TABLE_FIELD
].rows
;
627 method_last
= image
->tables
[MONO_TABLE_METHOD
].rows
;
630 if (cols
[MONO_TYPEDEF_FIELD_LIST
] &&
631 cols
[MONO_TYPEDEF_FIELD_LIST
] <= image
->tables
[MONO_TABLE_FIELD
].rows
)
632 mono_class_set_field_count (klass
, field_last
- first_field_idx
);
633 if (cols
[MONO_TYPEDEF_METHOD_LIST
] <= image
->tables
[MONO_TABLE_METHOD
].rows
)
634 mono_class_set_method_count (klass
, method_last
- first_method_idx
);
636 /* reserve space to store vector pointer in arrays */
637 if (mono_is_corlib_image (image
) && !strcmp (nspace
, "System") && !strcmp (name
, "Array")) {
638 klass
->instance_size
+= 2 * TARGET_SIZEOF_VOID_P
;
639 #ifndef ENABLE_NETCORE
640 g_assert (mono_class_get_field_count (klass
) == 0);
642 /* TODO: check that array has 0 non-const fields */
646 if (klass
->enumtype
) {
647 MonoType
*enum_basetype
= mono_class_find_enum_basetype (klass
, error
);
648 if (!enum_basetype
) {
649 /*set it to a default value as the whole runtime can't handle this to be null*/
650 klass
->cast_class
= klass
->element_class
= mono_defaults
.int32_class
;
651 mono_class_set_type_load_failure (klass
, "%s", mono_error_get_message (error
));
652 mono_loader_unlock ();
653 MONO_PROFILER_RAISE (class_failed
, (klass
));
656 klass
->cast_class
= klass
->element_class
= mono_class_from_mono_type_internal (enum_basetype
);
660 * If we're a generic type definition, load the constraints.
661 * We must do this after the class has been constructed to make certain recursive scenarios
664 if (mono_class_is_gtd (klass
) && !mono_metadata_load_generic_param_constraints_checked (image
, type_token
, mono_class_get_generic_container (klass
), error
)) {
665 mono_class_set_type_load_failure (klass
, "Could not load generic parameter constrains due to %s", mono_error_get_message (error
));
666 mono_loader_unlock ();
667 MONO_PROFILER_RAISE (class_failed
, (klass
));
671 if (klass
->image
->assembly_name
&& !strcmp (klass
->image
->assembly_name
, "Mono.Simd") && !strcmp (nspace
, "Mono.Simd")) {
672 if (!strncmp (name
, "Vector", 6))
673 klass
->simd_type
= !strcmp (name
+ 6, "2d") || !strcmp (name
+ 6, "2ul") || !strcmp (name
+ 6, "2l") || !strcmp (name
+ 6, "4f") || !strcmp (name
+ 6, "4ui") || !strcmp (name
+ 6, "4i") || !strcmp (name
+ 6, "8s") || !strcmp (name
+ 6, "8us") || !strcmp (name
+ 6, "16b") || !strcmp (name
+ 6, "16sb");
674 } else if (klass
->image
->assembly_name
&& !strcmp (klass
->image
->assembly_name
, "System.Numerics") && !strcmp (nspace
, "System.Numerics")) {
675 /* The JIT can't handle SIMD types with != 16 size yet */
676 //if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
677 if (!strcmp (name
, "Vector4"))
678 klass
->simd_type
= 1;
681 // compute is_byreflike
682 if (m_class_is_valuetype (klass
))
683 if (class_has_isbyreflike_attribute (klass
))
684 klass
->is_byreflike
= 1;
686 mono_loader_unlock ();
688 MONO_PROFILER_RAISE (class_loaded
, (klass
));
693 if (mono_class_is_gtd (klass
))
694 disable_gclass_recording (discard_gclass_due_to_failure
, klass
);
696 mono_class_setup_mono_type (klass
);
697 mono_loader_unlock ();
698 MONO_PROFILER_RAISE (class_failed
, (klass
));
704 mono_generic_class_setup_parent (MonoClass
*klass
, MonoClass
*gtd
)
708 MonoGenericClass
*gclass
= mono_class_get_generic_class (klass
);
710 klass
->parent
= mono_class_inflate_generic_class_checked (gtd
->parent
, mono_generic_class_get_context (gclass
), error
);
711 if (!is_ok (error
)) {
712 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
713 klass
->parent
= mono_defaults
.object_class
;
714 mono_class_set_type_load_failure (klass
, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (error
));
715 mono_error_cleanup (error
);
720 mono_class_setup_parent (klass
, klass
->parent
);
722 if (klass
->enumtype
) {
723 klass
->cast_class
= gtd
->cast_class
;
724 klass
->element_class
= gtd
->element_class
;
726 mono_loader_unlock ();
739 has_wellknown_attribute_func (MonoImage
*image
, guint32 typeref_scope_token
, const char *nspace
, const char *name
, guint32 method_token
, gpointer user_data
)
741 struct FoundAttrUD
*has_attr
= (struct FoundAttrUD
*)user_data
;
742 if (!strcmp (name
, has_attr
->name
) && !strcmp (nspace
, has_attr
->nspace
)) {
743 has_attr
->has_attr
= TRUE
;
746 /* TODO: use typeref_scope_token to check that attribute comes from
747 * corlib if in_corlib is TRUE, without triggering an assembly load.
748 * If we're inside corlib, expect the scope to be
749 * MONO_RESOLUTION_SCOPE_MODULE I think, if we're outside it'll be an
750 * MONO_RESOLUTION_SCOPE_ASSEMBLYREF and we'll need to check the
756 class_has_wellknown_attribute (MonoClass
*klass
, const char *nspace
, const char *name
, gboolean in_corlib
)
758 struct FoundAttrUD has_attr
;
759 has_attr
.nspace
= nspace
;
760 has_attr
.name
= name
;
761 has_attr
.in_corlib
= in_corlib
;
762 has_attr
.has_attr
= FALSE
;
764 mono_class_metadata_foreach_custom_attr (klass
, has_wellknown_attribute_func
, &has_attr
);
766 return has_attr
.has_attr
;
770 method_has_wellknown_attribute (MonoMethod
*method
, const char *nspace
, const char *name
, gboolean in_corlib
)
772 struct FoundAttrUD has_attr
;
773 has_attr
.nspace
= nspace
;
774 has_attr
.name
= name
;
775 has_attr
.in_corlib
= in_corlib
;
776 has_attr
.has_attr
= FALSE
;
778 mono_method_metadata_foreach_custom_attr (method
, has_wellknown_attribute_func
, &has_attr
);
780 return has_attr
.has_attr
;
785 class_has_isbyreflike_attribute (MonoClass
*klass
)
787 return class_has_wellknown_attribute (klass
, "System.Runtime.CompilerServices", "IsByRefLikeAttribute", TRUE
);
792 mono_class_setup_method_has_preserve_base_overrides_attribute (MonoMethod
*method
)
794 MonoImage
*image
= m_class_get_image (method
->klass
);
795 /* FIXME: implement well known attribute check for dynamic images */
796 if (image_is_dynamic (image
))
798 return method_has_wellknown_attribute (method
, "System.Runtime.CompilerServices", "PreserveBaseOverridesAttribute", TRUE
);
802 check_valid_generic_inst_arguments (MonoGenericInst
*inst
, MonoError
*error
)
804 for (int i
= 0; i
< inst
->type_argc
; i
++) {
805 if (!mono_type_is_valid_generic_argument (inst
->type_argv
[i
])) {
806 char *type_name
= mono_type_full_name (inst
->type_argv
[i
]);
807 mono_error_set_invalid_program (error
, "generic type cannot be instantiated with type '%s'", type_name
);
816 * Create the `MonoClass' for an instantiation of a generic type.
817 * We only do this if we actually need it.
818 * This will sometimes return a GTD due to checking the cached_class.
821 mono_class_create_generic_inst (MonoGenericClass
*gclass
)
823 MonoClass
*klass
, *gklass
;
825 if (gclass
->cached_class
)
826 return gclass
->cached_class
;
828 klass
= (MonoClass
*)mono_image_set_alloc0 (gclass
->owner
, sizeof (MonoClassGenericInst
));
830 gklass
= gclass
->container_class
;
832 if (gklass
->nested_in
) {
833 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
834 klass
->nested_in
= gklass
->nested_in
;
837 klass
->name
= gklass
->name
;
838 klass
->name_space
= gklass
->name_space
;
840 klass
->image
= gklass
->image
;
841 klass
->type_token
= gklass
->type_token
;
843 klass
->class_kind
= MONO_CLASS_GINST
;
845 ((MonoClassGenericInst
*)klass
)->generic_class
= gclass
;
847 klass
->_byval_arg
.type
= MONO_TYPE_GENERICINST
;
848 klass
->this_arg
.type
= m_class_get_byval_arg (klass
)->type
;
849 klass
->this_arg
.data
.generic_class
= klass
->_byval_arg
.data
.generic_class
= gclass
;
850 klass
->this_arg
.byref
= TRUE
;
851 klass
->enumtype
= gklass
->enumtype
;
852 klass
->valuetype
= gklass
->valuetype
;
855 if (gklass
->image
->assembly_name
&& !strcmp (gklass
->image
->assembly_name
, "System.Numerics.Vectors") && !strcmp (gklass
->name_space
, "System.Numerics") && !strcmp (gklass
->name
, "Vector`1")) {
856 g_assert (gclass
->context
.class_inst
);
857 g_assert (gclass
->context
.class_inst
->type_argc
> 0);
858 if (mono_type_is_primitive (gclass
->context
.class_inst
->type_argv
[0]))
859 klass
->simd_type
= 1;
861 #ifdef ENABLE_NETCORE
862 if (mono_is_corlib_image (gklass
->image
) &&
863 (!strcmp (gklass
->name
, "Vector`1") || !strcmp (gklass
->name
, "Vector128`1") || !strcmp (gklass
->name
, "Vector256`1"))) {
864 MonoType
*etype
= gclass
->context
.class_inst
->type_argv
[0];
865 if (mono_type_is_primitive (etype
) && etype
->type
!= MONO_TYPE_CHAR
&& etype
->type
!= MONO_TYPE_BOOLEAN
)
866 klass
->simd_type
= 1;
870 klass
->is_array_special_interface
= gklass
->is_array_special_interface
;
872 klass
->cast_class
= klass
->element_class
= klass
;
874 if (m_class_is_valuetype (klass
)) {
875 klass
->is_byreflike
= gklass
->is_byreflike
;
878 if (gclass
->is_dynamic
) {
880 * We don't need to do any init workf with unbaked typebuilders. Generic instances created at this point will be later unregistered and/or fixed.
881 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
882 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
884 if (!gklass
->wastypebuilder
)
887 if (klass
->enumtype
) {
889 * For enums, gklass->fields might not been set, but instance_size etc. is
890 * already set in mono_reflection_create_internal_class (). For non-enums,
891 * these will be computed normally in mono_class_layout_fields ().
893 klass
->instance_size
= gklass
->instance_size
;
894 klass
->sizes
.class_size
= gklass
->sizes
.class_size
;
895 klass
->size_inited
= 1;
900 ERROR_DECL (error_inst
);
901 if (!check_valid_generic_inst_arguments (gclass
->context
.class_inst
, error_inst
)) {
902 char *gklass_name
= mono_type_get_full_name (gklass
);
903 mono_class_set_type_load_failure (klass
, "Could not instantiate %s due to %s", gklass_name
, mono_error_get_message (error_inst
));
904 g_free (gklass_name
);
905 mono_error_cleanup (error_inst
);
911 if (gclass
->cached_class
) {
912 mono_loader_unlock ();
913 return gclass
->cached_class
;
916 if (record_gclass_instantiation
> 0)
917 gclass_recorded_list
= g_slist_append (gclass_recorded_list
, klass
);
919 if (mono_class_is_nullable (klass
))
920 klass
->cast_class
= klass
->element_class
= mono_class_get_nullable_param_internal (klass
);
922 MONO_PROFILER_RAISE (class_loading
, (klass
));
924 mono_generic_class_setup_parent (klass
, gklass
);
926 if (gclass
->is_dynamic
)
927 mono_class_setup_supertypes (klass
);
929 mono_memory_barrier ();
930 gclass
->cached_class
= klass
;
932 MONO_PROFILER_RAISE (class_loaded
, (klass
));
935 inflated_classes_size
+= sizeof (MonoClassGenericInst
);
937 mono_loader_unlock ();
943 * For a composite class like uint32[], uint32*, set MonoClass:cast_class to the corresponding "intermediate type" (for
944 * arrays) or "verification type" (for pointers) in the sense of ECMA I.8.7.3. This will be used by
945 * mono_class_is_assignable_from.
947 * Assumes MonoClass:cast_class is already set (for example if it's an array of
948 * some enum) and adjusts it.
951 class_composite_fixup_cast_class (MonoClass
*klass
, gboolean for_ptr
)
953 switch (m_class_get_byval_arg (m_class_get_cast_class (klass
))->type
) {
954 case MONO_TYPE_BOOLEAN
:
957 klass
->cast_class
= mono_defaults
.byte_class
;
960 klass
->cast_class
= mono_defaults
.byte_class
;
963 klass
->cast_class
= mono_defaults
.int16_class
;
966 #if TARGET_SIZEOF_VOID_P == 4
970 klass
->cast_class
= mono_defaults
.int32_class
;
973 #if TARGET_SIZEOF_VOID_P == 8
977 klass
->cast_class
= mono_defaults
.int64_class
;
985 class_kind_may_contain_generic_instances (MonoTypeKind kind
)
987 /* classes of type generic inst may contain generic arguments from other images,
988 * as well as arrays and pointers whose element types (recursively) may be a generic inst */
989 return (kind
== MONO_CLASS_GINST
|| kind
== MONO_CLASS_ARRAY
|| kind
== MONO_CLASS_POINTER
);
993 * mono_class_create_bounded_array:
994 * \param element_class element class
995 * \param rank the dimension of the array class
996 * \param bounded whenever the array has non-zero bounds
997 * \returns A class object describing the array with element type \p element_type and
1001 mono_class_create_bounded_array (MonoClass
*eclass
, guint32 rank
, gboolean bounded
)
1004 MonoClass
*klass
, *cached
, *k
;
1005 MonoClass
*parent
= NULL
;
1006 GSList
*list
, *rootlist
= NULL
;
1009 MonoImageSet
* image_set
;
1012 /* bounded only matters for one-dimensional arrays */
1015 image
= eclass
->image
;
1016 image_set
= class_kind_may_contain_generic_instances ((MonoTypeKind
)eclass
->class_kind
) ? mono_metadata_get_image_set_for_class (eclass
) : NULL
;
1020 if (rank
== 1 && !bounded
) {
1022 mono_image_set_lock (image_set
);
1023 cached
= (MonoClass
*)g_hash_table_lookup (image_set
->szarray_cache
, eclass
);
1024 mono_image_set_unlock (image_set
);
1027 * This case is very frequent not just during compilation because of calls
1028 * from mono_class_from_mono_type_internal (), mono_array_new (),
1029 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
1031 mono_os_mutex_lock (&image
->szarray_cache_lock
);
1032 if (!image
->szarray_cache
)
1033 image
->szarray_cache
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
1034 cached
= (MonoClass
*)g_hash_table_lookup (image
->szarray_cache
, eclass
);
1035 mono_os_mutex_unlock (&image
->szarray_cache_lock
);
1039 mono_image_set_lock (image_set
);
1040 rootlist
= (GSList
*)g_hash_table_lookup (image_set
->array_cache
, eclass
);
1041 for (list
= rootlist
; list
; list
= list
->next
) {
1042 k
= (MonoClass
*)list
->data
;
1043 if ((m_class_get_rank (k
) == rank
) && (m_class_get_byval_arg (k
)->type
== (((rank
> 1) || bounded
) ? MONO_TYPE_ARRAY
: MONO_TYPE_SZARRAY
))) {
1048 mono_image_set_unlock (image_set
);
1050 mono_loader_lock ();
1051 if (!image
->array_cache
)
1052 image
->array_cache
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
1053 rootlist
= (GSList
*)g_hash_table_lookup (image
->array_cache
, eclass
);
1054 for (list
= rootlist
; list
; list
= list
->next
) {
1055 k
= (MonoClass
*)list
->data
;
1056 if ((m_class_get_rank (k
) == rank
) && (m_class_get_byval_arg (k
)->type
== (((rank
> 1) || bounded
) ? MONO_TYPE_ARRAY
: MONO_TYPE_SZARRAY
))) {
1061 mono_loader_unlock ();
1067 parent
= mono_defaults
.array_class
;
1068 if (!parent
->inited
)
1069 mono_class_init_internal (parent
);
1071 klass
= image_set
? (MonoClass
*)mono_image_set_alloc0 (image_set
, sizeof (MonoClassArray
)) : (MonoClass
*)mono_image_alloc0 (image
, sizeof (MonoClassArray
));
1073 klass
->image
= image
;
1074 klass
->name_space
= eclass
->name_space
;
1075 klass
->class_kind
= MONO_CLASS_ARRAY
;
1077 nsize
= strlen (eclass
->name
);
1078 int maxrank
= MIN (rank
, 32);
1079 name
= (char *)g_malloc (nsize
+ 2 + maxrank
+ 1);
1080 memcpy (name
, eclass
->name
, nsize
);
1083 memset (name
+ nsize
+ 1, ',', maxrank
- 1);
1085 name
[nsize
+ maxrank
] = '*';
1086 name
[nsize
+ maxrank
+ bounded
] = ']';
1087 name
[nsize
+ maxrank
+ bounded
+ 1] = 0;
1088 klass
->name
= image_set
? mono_image_set_strdup (image_set
, name
) : mono_image_strdup (image
, name
);
1091 klass
->type_token
= 0;
1092 klass
->parent
= parent
;
1093 klass
->instance_size
= mono_class_instance_size (klass
->parent
);
1095 if (m_class_get_byval_arg (eclass
)->type
== MONO_TYPE_TYPEDBYREF
) {
1096 /*Arrays of those two types are invalid.*/
1097 ERROR_DECL (prepared_error
);
1098 mono_error_set_invalid_program (prepared_error
, "Arrays of System.TypedReference types are invalid.");
1099 mono_class_set_failure (klass
, mono_error_box (prepared_error
, klass
->image
));
1100 mono_error_cleanup (prepared_error
);
1101 } else if (m_class_is_byreflike (eclass
)) {
1102 /* .NET Core throws a type load exception: "Could not create array type 'fullname[]'" */
1103 char *full_name
= mono_type_get_full_name (eclass
);
1104 mono_class_set_type_load_failure (klass
, "Could not create array type '%s[]'", full_name
);
1106 } else if (eclass
->enumtype
&& !mono_class_enum_basetype_internal (eclass
)) {
1107 MonoGCHandle ref_info_handle
= mono_class_get_ref_info_handle (eclass
);
1108 if (!ref_info_handle
|| eclass
->wastypebuilder
) {
1109 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
1110 g_assert (ref_info_handle
&& !eclass
->wastypebuilder
);
1112 /* element_size -1 is ok as this is not an instantitable type*/
1113 klass
->sizes
.element_size
= -1;
1115 klass
->sizes
.element_size
= -1;
1117 mono_class_setup_supertypes (klass
);
1119 if (mono_class_is_ginst (eclass
))
1120 mono_class_init_internal (eclass
);
1121 if (!eclass
->size_inited
)
1122 mono_class_setup_fields (eclass
);
1123 mono_class_set_type_load_failure_causedby_class (klass
, eclass
, "Could not load array element type");
1124 /*FIXME we fail the array type, but we have to let other fields be set.*/
1126 klass
->has_references
= MONO_TYPE_IS_REFERENCE (m_class_get_byval_arg (eclass
)) || m_class_has_references (eclass
)? TRUE
: FALSE
;
1130 if (eclass
->enumtype
)
1131 klass
->cast_class
= eclass
->element_class
;
1133 klass
->cast_class
= eclass
;
1135 class_composite_fixup_cast_class (klass
, FALSE
);
1137 klass
->element_class
= eclass
;
1139 if ((rank
> 1) || bounded
) {
1140 MonoArrayType
*at
= image_set
? (MonoArrayType
*)mono_image_set_alloc0 (image_set
, sizeof (MonoArrayType
)) : (MonoArrayType
*)mono_image_alloc0 (image
, sizeof (MonoArrayType
));
1141 klass
->_byval_arg
.type
= MONO_TYPE_ARRAY
;
1142 klass
->_byval_arg
.data
.array
= at
;
1143 at
->eklass
= eclass
;
1145 /* FIXME: complete.... */
1147 klass
->_byval_arg
.type
= MONO_TYPE_SZARRAY
;
1148 klass
->_byval_arg
.data
.klass
= eclass
;
1150 klass
->this_arg
= klass
->_byval_arg
;
1151 klass
->this_arg
.byref
= 1;
1154 ERROR_DECL (prepared_error
);
1155 name
= mono_type_get_full_name (klass
);
1156 mono_error_set_type_load_class (prepared_error
, klass
, "%s has too many dimensions.", name
);
1157 mono_class_set_failure (klass
, mono_error_box (prepared_error
, klass
->image
));
1158 mono_error_cleanup (prepared_error
);
1162 mono_loader_lock ();
1164 /* Check cache again */
1166 if (rank
== 1 && !bounded
) {
1168 mono_image_set_lock (image_set
);
1169 cached
= (MonoClass
*)g_hash_table_lookup (image_set
->szarray_cache
, eclass
);
1170 mono_image_set_unlock (image_set
);
1172 mono_os_mutex_lock (&image
->szarray_cache_lock
);
1173 cached
= (MonoClass
*)g_hash_table_lookup (image
->szarray_cache
, eclass
);
1174 mono_os_mutex_unlock (&image
->szarray_cache_lock
);
1178 mono_image_set_lock (image_set
);
1179 rootlist
= (GSList
*)g_hash_table_lookup (image_set
->array_cache
, eclass
);
1180 for (list
= rootlist
; list
; list
= list
->next
) {
1181 k
= (MonoClass
*)list
->data
;
1182 if ((m_class_get_rank (k
) == rank
) && (m_class_get_byval_arg (k
)->type
== (((rank
> 1) || bounded
) ? MONO_TYPE_ARRAY
: MONO_TYPE_SZARRAY
))) {
1187 mono_image_set_unlock (image_set
);
1189 rootlist
= (GSList
*)g_hash_table_lookup (image
->array_cache
, eclass
);
1190 for (list
= rootlist
; list
; list
= list
->next
) {
1191 k
= (MonoClass
*)list
->data
;
1192 if ((m_class_get_rank (k
) == rank
) && (m_class_get_byval_arg (k
)->type
== (((rank
> 1) || bounded
) ? MONO_TYPE_ARRAY
: MONO_TYPE_SZARRAY
))) {
1200 mono_loader_unlock ();
1204 MONO_PROFILER_RAISE (class_loading
, (klass
));
1206 UnlockedAdd (&classes_size
, sizeof (MonoClassArray
));
1207 ++class_array_count
;
1209 if (rank
== 1 && !bounded
) {
1211 mono_image_set_lock (image_set
);
1212 g_hash_table_insert (image_set
->szarray_cache
, eclass
, klass
);
1213 mono_image_set_unlock (image_set
);
1215 mono_os_mutex_lock (&image
->szarray_cache_lock
);
1216 g_hash_table_insert (image
->szarray_cache
, eclass
, klass
);
1217 mono_os_mutex_unlock (&image
->szarray_cache_lock
);
1221 mono_image_set_lock (image_set
);
1222 list
= g_slist_append (rootlist
, klass
);
1223 g_hash_table_insert (image_set
->array_cache
, eclass
, list
);
1224 mono_image_set_unlock (image_set
);
1226 list
= g_slist_append (rootlist
, klass
);
1227 g_hash_table_insert (image
->array_cache
, eclass
, list
);
1231 mono_loader_unlock ();
1233 MONO_PROFILER_RAISE (class_loaded
, (klass
));
1239 * mono_class_create_array:
1240 * \param element_class element class
1241 * \param rank the dimension of the array class
1242 * \returns A class object describing the array with element type \p element_type and
1243 * dimension \p rank.
1246 mono_class_create_array (MonoClass
*eclass
, guint32 rank
)
1248 return mono_class_create_bounded_array (eclass
, rank
, FALSE
);
1251 // This is called by mono_class_create_generic_parameter when a new class must be created.
1253 make_generic_param_class (MonoGenericParam
*param
)
1255 MonoClass
*klass
, **ptr
;
1256 int count
, pos
, i
, min_align
;
1257 MonoGenericParamInfo
*pinfo
= mono_generic_param_info (param
);
1258 MonoGenericContainer
*container
= mono_generic_param_owner (param
);
1259 g_assert_checked (container
);
1261 MonoImage
*image
= mono_get_image_for_generic_param (param
);
1262 gboolean is_mvar
= container
->is_method
;
1263 gboolean is_anonymous
= container
->is_anonymous
;
1265 klass
= (MonoClass
*)mono_image_alloc0 (image
, sizeof (MonoClassGenericParam
));
1266 klass
->class_kind
= MONO_CLASS_GPARAM
;
1267 UnlockedAdd (&classes_size
, sizeof (MonoClassGenericParam
));
1268 UnlockedIncrement (&class_gparam_count
);
1270 if (!is_anonymous
) {
1271 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass
->name
, pinfo
->name
);
1273 int n
= mono_generic_param_num (param
);
1274 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass
->name
, mono_make_generic_name_string (image
, n
) );
1278 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass
->name_space
, "" );
1279 } else if (is_mvar
) {
1280 MonoMethod
*omethod
= container
->owner
.method
;
1281 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass
->name_space
, (omethod
&& omethod
->klass
) ? omethod
->klass
->name_space
: "" );
1283 MonoClass
*oklass
= container
->owner
.klass
;
1284 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass
->name_space
, oklass
? oklass
->name_space
: "" );
1287 MONO_PROFILER_RAISE (class_loading
, (klass
));
1289 // Count non-NULL items in pinfo->constraints
1292 for (ptr
= pinfo
->constraints
; ptr
&& *ptr
; ptr
++, count
++)
1296 if ((count
> 0) && !MONO_CLASS_IS_INTERFACE_INTERNAL (pinfo
->constraints
[0])) {
1297 CHECKED_METADATA_WRITE_PTR ( klass
->parent
, pinfo
->constraints
[0] );
1299 } else if (pinfo
&& pinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) {
1300 CHECKED_METADATA_WRITE_PTR ( klass
->parent
, mono_class_load_from_name (mono_defaults
.corlib
, "System", "ValueType") );
1302 CHECKED_METADATA_WRITE_PTR ( klass
->parent
, mono_defaults
.object_class
);
1305 if (count
- pos
> 0) {
1306 klass
->interface_count
= count
- pos
;
1307 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass
->interfaces
, (MonoClass
**)mono_image_alloc0 (image
, sizeof (MonoClass
*) * (count
- pos
)) );
1308 klass
->interfaces_inited
= TRUE
;
1309 for (i
= pos
; i
< count
; i
++)
1310 CHECKED_METADATA_WRITE_PTR ( klass
->interfaces
[i
- pos
] , pinfo
->constraints
[i
] );
1313 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass
->image
, image
);
1315 klass
->inited
= TRUE
;
1316 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass
->cast_class
, klass
);
1317 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass
->element_class
, klass
);
1319 MonoTypeEnum t
= is_mvar
? MONO_TYPE_MVAR
: MONO_TYPE_VAR
;
1320 klass
->_byval_arg
.type
= t
;
1321 klass
->this_arg
.type
= t
;
1322 CHECKED_METADATA_WRITE_PTR ( klass
->this_arg
.data
.generic_param
, param
);
1323 CHECKED_METADATA_WRITE_PTR ( klass
->_byval_arg
.data
.generic_param
, param
);
1324 klass
->this_arg
.byref
= TRUE
;
1326 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
1327 klass
->sizes
.generic_param_token
= !is_anonymous
? pinfo
->token
: 0;
1329 if (param
->gshared_constraint
) {
1330 MonoClass
*constraint_class
= mono_class_from_mono_type_internal (param
->gshared_constraint
);
1331 mono_class_init_sizes (constraint_class
);
1332 klass
->has_references
= m_class_has_references (constraint_class
);
1335 * This makes sure the the value size of this class is equal to the size of the types the gparam is
1336 * constrained to, the JIT depends on this.
1338 klass
->instance_size
= MONO_ABI_SIZEOF (MonoObject
) + mono_type_size (m_class_get_byval_arg (klass
), &min_align
);
1339 klass
->min_align
= min_align
;
1340 mono_memory_barrier ();
1341 klass
->size_inited
= 1;
1343 mono_class_setup_supertypes (klass
);
1345 if (count
- pos
> 0) {
1346 mono_class_setup_vtable (klass
->parent
);
1347 if (mono_class_has_failure (klass
->parent
))
1348 mono_class_set_type_load_failure (klass
, "Failed to setup parent interfaces");
1350 mono_class_setup_interface_offsets_internal (klass
, klass
->parent
->vtable_size
, TRUE
);
1357 * LOCKING: Acquires the image lock (@image).
1360 mono_class_create_generic_parameter (MonoGenericParam
*param
)
1362 MonoImage
*image
= mono_get_image_for_generic_param (param
);
1363 MonoGenericParamInfo
*pinfo
= mono_generic_param_info (param
);
1364 MonoClass
*klass
, *klass2
;
1366 // If a klass already exists for this object and is cached, return it.
1367 klass
= pinfo
->pklass
;
1372 // Create a new klass
1373 klass
= make_generic_param_class (param
);
1375 // Now we need to cache the klass we created.
1376 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
1377 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
1378 // and allow our newly-created klass object to just leak.
1379 mono_memory_barrier ();
1381 mono_image_lock (image
);
1383 // Here "klass2" refers to the klass potentially created by the other thread.
1384 klass2
= pinfo
->pklass
;
1389 pinfo
->pklass
= klass
;
1391 mono_image_unlock (image
);
1393 /* FIXME: Should this go inside 'make_generic_param_klass'? */
1395 MONO_PROFILER_RAISE (class_failed
, (klass2
));
1397 MONO_PROFILER_RAISE (class_loaded
, (klass
));
1403 * mono_class_create_ptr:
1406 mono_class_create_ptr (MonoType
*type
)
1409 MonoClass
*el_class
;
1412 MonoImageSet
* image_set
;
1414 el_class
= mono_class_from_mono_type_internal (type
);
1415 image
= el_class
->image
;
1416 image_set
= class_kind_may_contain_generic_instances ((MonoTypeKind
)el_class
->class_kind
) ? mono_metadata_get_image_set_for_class (el_class
) : NULL
;
1419 mono_image_set_lock (image_set
);
1420 if (image_set
->ptr_cache
) {
1421 if ((result
= (MonoClass
*)g_hash_table_lookup (image_set
->ptr_cache
, el_class
))) {
1422 mono_image_set_unlock (image_set
);
1426 mono_image_set_unlock (image_set
);
1428 mono_image_lock (image
);
1429 if (image
->ptr_cache
) {
1430 if ((result
= (MonoClass
*)g_hash_table_lookup (image
->ptr_cache
, el_class
))) {
1431 mono_image_unlock (image
);
1435 mono_image_unlock (image
);
1438 result
= image_set
? (MonoClass
*)mono_image_set_alloc0 (image_set
, sizeof (MonoClassPointer
)) : (MonoClass
*)mono_image_alloc0 (image
, sizeof (MonoClassPointer
));
1440 UnlockedAdd (&classes_size
, sizeof (MonoClassPointer
));
1441 ++class_pointer_count
;
1443 result
->parent
= NULL
; /* no parent for PTR types */
1444 result
->name_space
= el_class
->name_space
;
1445 name
= g_strdup_printf ("%s*", el_class
->name
);
1446 result
->name
= image_set
? mono_image_set_strdup (image_set
, name
) : mono_image_strdup (image
, name
);
1447 result
->class_kind
= MONO_CLASS_POINTER
;
1450 MONO_PROFILER_RAISE (class_loading
, (result
));
1452 result
->image
= el_class
->image
;
1453 result
->inited
= TRUE
;
1454 result
->instance_size
= MONO_ABI_SIZEOF (MonoObject
) + MONO_ABI_SIZEOF (gpointer
);
1455 result
->min_align
= sizeof (gpointer
);
1456 result
->element_class
= el_class
;
1457 result
->blittable
= TRUE
;
1459 if (el_class
->enumtype
)
1460 result
->cast_class
= el_class
->element_class
;
1462 result
->cast_class
= el_class
;
1463 class_composite_fixup_cast_class (result
, TRUE
);
1465 result
->this_arg
.type
= result
->_byval_arg
.type
= MONO_TYPE_PTR
;
1466 result
->this_arg
.data
.type
= result
->_byval_arg
.data
.type
= m_class_get_byval_arg (el_class
);
1467 result
->this_arg
.byref
= TRUE
;
1469 mono_class_setup_supertypes (result
);
1472 mono_image_set_lock (image_set
);
1473 if (image_set
->ptr_cache
) {
1475 if ((result2
= (MonoClass
*)g_hash_table_lookup (image_set
->ptr_cache
, el_class
))) {
1476 mono_image_set_unlock (image_set
);
1477 MONO_PROFILER_RAISE (class_failed
, (result
));
1482 image_set
->ptr_cache
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
1484 g_hash_table_insert (image_set
->ptr_cache
, el_class
, result
);
1485 mono_image_set_unlock (image_set
);
1487 mono_image_lock (image
);
1488 if (image
->ptr_cache
) {
1490 if ((result2
= (MonoClass
*)g_hash_table_lookup (image
->ptr_cache
, el_class
))) {
1491 mono_image_unlock (image
);
1492 MONO_PROFILER_RAISE (class_failed
, (result
));
1496 image
->ptr_cache
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
1498 g_hash_table_insert (image
->ptr_cache
, el_class
, result
);
1499 mono_image_unlock (image
);
1502 MONO_PROFILER_RAISE (class_loaded
, (result
));
1508 mono_class_create_fnptr (MonoMethodSignature
*sig
)
1510 MonoClass
*result
, *cached
;
1511 static GHashTable
*ptr_hash
= NULL
;
1513 /* FIXME: These should be allocate from a mempool as well, but which one ? */
1515 mono_loader_lock ();
1517 ptr_hash
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
1518 cached
= (MonoClass
*)g_hash_table_lookup (ptr_hash
, sig
);
1519 mono_loader_unlock ();
1523 result
= g_new0 (MonoClass
, 1);
1525 result
->parent
= NULL
; /* no parent for PTR types */
1526 result
->name_space
= "System";
1527 result
->name
= "MonoFNPtrFakeClass";
1528 result
->class_kind
= MONO_CLASS_POINTER
;
1530 result
->image
= mono_defaults
.corlib
; /* need to fix... */
1531 result
->instance_size
= MONO_ABI_SIZEOF (MonoObject
) + MONO_ABI_SIZEOF (gpointer
);
1532 result
->min_align
= sizeof (gpointer
);
1533 result
->cast_class
= result
->element_class
= result
;
1534 result
->this_arg
.type
= result
->_byval_arg
.type
= MONO_TYPE_FNPTR
;
1535 result
->this_arg
.data
.method
= result
->_byval_arg
.data
.method
= sig
;
1536 result
->this_arg
.byref
= TRUE
;
1537 result
->blittable
= TRUE
;
1538 result
->inited
= TRUE
;
1540 mono_class_setup_supertypes (result
);
1542 mono_loader_lock ();
1544 cached
= (MonoClass
*)g_hash_table_lookup (ptr_hash
, sig
);
1547 mono_loader_unlock ();
1551 MONO_PROFILER_RAISE (class_loading
, (result
));
1553 UnlockedAdd (&classes_size
, sizeof (MonoClassPointer
));
1554 ++class_pointer_count
;
1556 g_hash_table_insert (ptr_hash
, sig
, result
);
1558 mono_loader_unlock ();
1560 MONO_PROFILER_RAISE (class_loaded
, (result
));
1567 method_is_reabstracted (guint16 flags
)
1569 if ((flags
& METHOD_ATTRIBUTE_ABSTRACT
&& flags
& METHOD_ATTRIBUTE_FINAL
))
1575 * mono_class_setup_count_virtual_methods:
1577 * Return the number of virtual methods.
1578 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
1579 * Return -1 on failure.
1580 * FIXME It would be nice if this information could be cached somewhere.
1583 mono_class_setup_count_virtual_methods (MonoClass
*klass
)
1585 int i
, mcount
, vcount
= 0;
1587 klass
= mono_class_get_generic_type_definition (klass
); /*We can find this information by looking at the GTD*/
1589 if (klass
->methods
|| !MONO_CLASS_HAS_STATIC_METADATA (klass
)) {
1590 mono_class_setup_methods (klass
);
1591 if (mono_class_has_failure (klass
))
1594 mcount
= mono_class_get_method_count (klass
);
1595 for (i
= 0; i
< mcount
; ++i
) {
1596 flags
= klass
->methods
[i
]->flags
;
1597 if ((flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
1598 if (method_is_reabstracted (flags
))
1604 int first_idx
= mono_class_get_first_method_idx (klass
);
1605 mcount
= mono_class_get_method_count (klass
);
1606 for (i
= 0; i
< mcount
; ++i
) {
1607 flags
= mono_metadata_decode_table_row_col (klass
->image
, MONO_TABLE_METHOD
, first_idx
+ i
, MONO_METHOD_FLAGS
);
1609 if ((flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
1610 if (method_is_reabstracted (flags
))
1619 #ifdef COMPRESSED_INTERFACE_BITMAP
1622 * Compressed interface bitmap design.
1624 * Interface bitmaps take a large amount of memory, because their size is
1625 * linear with the maximum interface id assigned in the process (each interface
1626 * is assigned a unique id as it is loaded). The number of interface classes
1627 * is high because of the many implicit interfaces implemented by arrays (we'll
1628 * need to lazy-load them in the future).
1629 * Most classes implement a very small number of interfaces, so the bitmap is
1630 * sparse. This bitmap needs to be checked by interface casts, so access to the
1631 * needed bit must be fast and doable with few jit instructions.
1633 * The current compression format is as follows:
1634 * *) it is a sequence of one or more two-byte elements
1635 * *) the first byte in the element is the count of empty bitmap bytes
1636 * at the current bitmap position
1637 * *) the second byte in the element is an actual bitmap byte at the current
1640 * As an example, the following compressed bitmap bytes:
1641 * 0x07 0x01 0x00 0x7
1642 * correspond to the following bitmap:
1643 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
1645 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
1646 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
1647 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
1651 * mono_compress_bitmap:
1652 * \param dest destination buffer
1653 * \param bitmap bitmap buffer
1654 * \param size size of \p bitmap in bytes
1656 * This is a mono internal function.
1657 * The \p bitmap data is compressed into a format that is small but
1658 * still searchable in few instructions by the JIT and runtime.
1659 * The compressed data is stored in the buffer pointed to by the
1660 * \p dest array. Passing a NULL value for \p dest allows to just compute
1661 * the size of the buffer.
1662 * This compression algorithm assumes the bits set in the bitmap are
1663 * few and far between, like in interface bitmaps.
1664 * \returns The size of the compressed bitmap in bytes.
1667 mono_compress_bitmap (uint8_t *dest
, const uint8_t *bitmap
, int size
)
1671 const uint8_t *end
= bitmap
+ size
;
1672 while (bitmap
< end
) {
1673 if (*bitmap
|| numz
== 255) {
1697 * mono_class_interface_match:
1698 * \param bitmap a compressed bitmap buffer
1699 * \param id the index to check in the bitmap
1701 * This is a mono internal function.
1702 * Checks if a bit is set in a compressed interface bitmap. \p id must
1703 * be already checked for being smaller than the maximum id encoded in the
1706 * \returns A non-zero value if bit \p id is set in the bitmap \p bitmap,
1710 mono_class_interface_match (const uint8_t *bitmap
, int id
)
1713 id
-= bitmap
[0] * 8;
1717 return bitmap
[1] & (1 << id
);
1726 concat_two_strings_with_zero (MonoImage
*image
, const char *s1
, const char *s2
)
1728 int null_length
= strlen ("(null)");
1729 int len
= (s1
? strlen (s1
) : null_length
) + (s2
? strlen (s2
) : null_length
) + 2;
1730 char *s
= (char *)mono_image_alloc (image
, len
);
1733 result
= g_snprintf (s
, len
, "%s%c%s", s1
? s1
: "(null)", '\0', s2
? s2
: "(null)");
1734 g_assert (result
== len
- 1);
1741 init_sizes_with_info (MonoClass
*klass
, MonoCachedClassInfo
*cached_info
)
1744 mono_loader_lock ();
1745 klass
->instance_size
= cached_info
->instance_size
;
1746 klass
->sizes
.class_size
= cached_info
->class_size
;
1747 klass
->packing_size
= cached_info
->packing_size
;
1748 klass
->min_align
= cached_info
->min_align
;
1749 klass
->blittable
= cached_info
->blittable
;
1750 klass
->has_references
= cached_info
->has_references
;
1751 klass
->has_static_refs
= cached_info
->has_static_refs
;
1752 klass
->no_special_static_fields
= cached_info
->no_special_static_fields
;
1753 klass
->has_weak_fields
= cached_info
->has_weak_fields
;
1754 mono_loader_unlock ();
1757 if (!klass
->size_inited
)
1758 mono_class_setup_fields (klass
);
1763 * mono_class_init_sizes:
1765 * Initializes the size related fields of @klass without loading all field data if possible.
1766 * Sets the following fields in @klass:
1768 * - sizes.class_size
1775 * Can fail the class.
1777 * LOCKING: Acquires the loader lock.
1780 mono_class_init_sizes (MonoClass
*klass
)
1782 MonoCachedClassInfo cached_info
;
1783 gboolean has_cached_info
;
1785 if (klass
->size_inited
)
1788 has_cached_info
= mono_class_get_cached_class_info (klass
, &cached_info
);
1790 init_sizes_with_info (klass
, has_cached_info
? &cached_info
: NULL
);
1795 class_has_references (MonoClass
*klass
)
1797 mono_class_init_sizes (klass
);
1800 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1801 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1804 return klass
->has_references
;
1808 type_has_references (MonoClass
*klass
, MonoType
*ftype
)
1810 if (MONO_TYPE_IS_REFERENCE (ftype
) || IS_GC_REFERENCE (klass
, ftype
) || ((MONO_TYPE_ISSTRUCT (ftype
) && class_has_references (mono_class_from_mono_type_internal (ftype
)))))
1812 if (!ftype
->byref
&& (ftype
->type
== MONO_TYPE_VAR
|| ftype
->type
== MONO_TYPE_MVAR
)) {
1813 MonoGenericParam
*gparam
= ftype
->data
.generic_param
;
1815 if (gparam
->gshared_constraint
)
1816 return class_has_references (mono_class_from_mono_type_internal (gparam
->gshared_constraint
));
1822 * mono_class_is_gparam_with_nonblittable_parent:
1823 * \param klass a generic parameter
1825 * \returns TRUE if \p klass is definitely not blittable.
1827 * A parameter is definitely not blittable if it has the IL 'reference'
1828 * constraint, or if it has a class specified as a parent. If it has an IL
1829 * 'valuetype' constraint or no constraint at all or only interfaces as
1830 * constraints, we return FALSE because the parameter may be instantiated both
1831 * with blittable and non-blittable types.
1833 * If the paramter is a generic sharing parameter, we look at its gshared_constraint->blittable bit.
1836 mono_class_is_gparam_with_nonblittable_parent (MonoClass
*klass
)
1838 MonoType
*type
= m_class_get_byval_arg (klass
);
1839 g_assert (mono_type_is_generic_parameter (type
));
1840 MonoGenericParam
*gparam
= type
->data
.generic_param
;
1841 if ((mono_generic_param_info (gparam
)->flags
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) != 0)
1843 if ((mono_generic_param_info (gparam
)->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) != 0)
1846 if (gparam
->gshared_constraint
) {
1847 MonoClass
*constraint_class
= mono_class_from_mono_type_internal (gparam
->gshared_constraint
);
1848 return !m_class_is_blittable (constraint_class
);
1851 if (mono_generic_param_owner (gparam
)->is_anonymous
)
1854 /* We could have: T : U, U : Base. So have to follow the constraints. */
1855 MonoClass
*parent_class
= mono_generic_param_get_base_type (klass
);
1856 g_assert (!MONO_CLASS_IS_INTERFACE_INTERNAL (parent_class
));
1857 /* Parent can only be: System.Object, System.ValueType or some specific base class.
1859 * If the parent_class is ValueType, the valuetype constraint would be set, above, so
1860 * we wouldn't get here.
1862 * If there was a reference constraint, the parent_class would be System.Object,
1863 * but we would have returned early above.
1865 * So if we get here, there is either no base class constraint at all,
1866 * in which case parent_class would be set to System.Object, or there is none at all.
1868 return parent_class
!= mono_defaults
.object_class
;
1872 * mono_class_layout_fields:
1874 * @base_instance_size: base instance size
1877 * This contains the common code for computing the layout of classes and sizes.
1878 * This should only be called from mono_class_setup_fields () and
1879 * typebuilder_setup_fields ().
1881 * LOCKING: Acquires the loader lock
1884 mono_class_layout_fields (MonoClass
*klass
, int base_instance_size
, int packing_size
, int explicit_size
, gboolean sre
)
1887 const int top
= mono_class_get_field_count (klass
);
1888 guint32 layout
= mono_class_get_flags (klass
) & TYPE_ATTRIBUTE_LAYOUT_MASK
;
1889 guint32 pass
, passes
, real_size
;
1890 gboolean gc_aware_layout
= FALSE
;
1891 gboolean has_static_fields
= FALSE
;
1892 gboolean has_references
= FALSE
;
1893 gboolean has_static_refs
= FALSE
;
1894 MonoClassField
*field
;
1896 int instance_size
= base_instance_size
;
1897 int element_size
= -1;
1898 int class_size
, min_align
;
1900 gboolean
*fields_has_references
;
1903 * We want to avoid doing complicated work inside locks, so we compute all the required
1904 * information and write it to @klass inside a lock.
1906 if (klass
->fields_inited
)
1909 if ((packing_size
& 0xffffff00) != 0) {
1910 mono_class_set_type_load_failure (klass
, "Could not load struct '%s' with packing size %d >= 256", klass
->name
, packing_size
);
1914 if (klass
->parent
) {
1915 min_align
= klass
->parent
->min_align
;
1916 /* we use | since it may have been set already */
1917 has_references
= klass
->has_references
| klass
->parent
->has_references
;
1921 /* We can't really enable 16 bytes alignment until the GC supports it.
1922 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1923 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1924 Bug #506144 is an example of this issue.
1926 if (klass->simd_type)
1931 * When we do generic sharing we need to have layout
1932 * information for open generic classes (either with a generic
1933 * context containing type variables or with a generic
1934 * container), so we don't return in that case anymore.
1937 if (klass
->enumtype
) {
1938 for (i
= 0; i
< top
; i
++) {
1939 field
= &klass
->fields
[i
];
1940 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
1941 klass
->cast_class
= klass
->element_class
= mono_class_from_mono_type_internal (field
->type
);
1946 if (!mono_class_enum_basetype_internal (klass
)) {
1947 mono_class_set_type_load_failure (klass
, "The enumeration's base type is invalid.");
1953 * Enable GC aware auto layout: in this mode, reference
1954 * fields are grouped together inside objects, increasing collector
1956 * Requires that all classes whose layout is known to native code be annotated
1957 * with [StructLayout (LayoutKind.Sequential)]
1958 * Value types have gc_aware_layout disabled by default, as per
1959 * what the default is for other runtimes.
1961 /* corlib is missing [StructLayout] directives in many places */
1962 if (layout
== TYPE_ATTRIBUTE_AUTO_LAYOUT
) {
1963 if (!klass
->valuetype
)
1964 gc_aware_layout
= TRUE
;
1967 /* Compute klass->blittable */
1970 blittable
= klass
->parent
->blittable
;
1971 if (layout
== TYPE_ATTRIBUTE_AUTO_LAYOUT
&& !(mono_is_corlib_image (klass
->image
) && !strcmp (klass
->name_space
, "System") && !strcmp (klass
->name
, "ValueType")) && top
)
1973 for (i
= 0; i
< top
; i
++) {
1974 field
= &klass
->fields
[i
];
1976 if (mono_field_is_deleted (field
))
1978 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1981 if (field
->type
->byref
|| MONO_TYPE_IS_REFERENCE (field
->type
)) {
1983 } else if (mono_type_is_generic_parameter (field
->type
) &&
1984 mono_class_is_gparam_with_nonblittable_parent (mono_class_from_mono_type_internal (field
->type
))) {
1987 MonoClass
*field_class
= mono_class_from_mono_type_internal (field
->type
);
1989 mono_class_setup_fields (field_class
);
1990 if (mono_class_has_failure (field_class
)) {
1991 ERROR_DECL (field_error
);
1992 mono_error_set_for_class_failure (field_error
, field_class
);
1993 mono_class_set_type_load_failure (klass
, "Could not set up field '%s' due to: %s", field
->name
, mono_error_get_message (field_error
));
1994 mono_error_cleanup (field_error
);
1998 if (!field_class
|| !field_class
->blittable
)
2002 if (klass
->enumtype
)
2003 blittable
= klass
->element_class
->blittable
;
2005 if (mono_class_has_failure (klass
))
2007 if (klass
== mono_defaults
.string_class
)
2010 /* Compute klass->has_references */
2012 * Process non-static fields first, since static fields might recursively
2013 * refer to the class itself.
2015 for (i
= 0; i
< top
; i
++) {
2018 field
= &klass
->fields
[i
];
2020 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
2021 ftype
= mono_type_get_underlying_type (field
->type
);
2022 ftype
= mono_type_get_basic_type_from_generic (ftype
);
2023 if (type_has_references (klass
, ftype
))
2024 has_references
= TRUE
;
2029 * Compute field layout and total size (not considering static fields)
2031 field_offsets
= g_new0 (int, top
);
2032 fields_has_references
= g_new0 (gboolean
, top
);
2033 int first_field_idx
= mono_class_has_static_metadata (klass
) ? mono_class_get_first_field_idx (klass
) : 0;
2035 case TYPE_ATTRIBUTE_AUTO_LAYOUT
:
2036 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT
:
2037 if (gc_aware_layout
)
2042 if (layout
!= TYPE_ATTRIBUTE_AUTO_LAYOUT
)
2045 if (klass
->parent
) {
2046 mono_class_setup_fields (klass
->parent
);
2047 if (mono_class_set_type_load_failure_causedby_class (klass
, klass
->parent
, "Cannot initialize parent class"))
2049 real_size
= klass
->parent
->instance_size
;
2051 real_size
= MONO_ABI_SIZEOF (MonoObject
);
2054 for (pass
= 0; pass
< passes
; ++pass
) {
2055 for (i
= 0; i
< top
; i
++){
2060 field
= &klass
->fields
[i
];
2062 if (mono_field_is_deleted (field
))
2064 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
2067 ftype
= mono_type_get_underlying_type (field
->type
);
2068 ftype
= mono_type_get_basic_type_from_generic (ftype
);
2069 if (gc_aware_layout
) {
2070 fields_has_references
[i
] = type_has_references (klass
, ftype
);
2071 if (fields_has_references
[i
]) {
2080 if ((top
== 1) && (instance_size
== MONO_ABI_SIZEOF (MonoObject
)) &&
2081 (strcmp (mono_field_get_name (field
), "$PRIVATE$") == 0)) {
2082 /* This field is a hack inserted by MCS to empty structures */
2086 size
= mono_type_size (field
->type
, &align
);
2088 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
2089 align
= packing_size
? MIN (packing_size
, align
): align
;
2090 /* if the field has managed references, we need to force-align it
2093 if (type_has_references (klass
, ftype
))
2094 align
= MAX (align
, TARGET_SIZEOF_VOID_P
);
2096 min_align
= MAX (align
, min_align
);
2097 field_offsets
[i
] = real_size
;
2099 field_offsets
[i
] += align
- 1;
2100 field_offsets
[i
] &= ~(align
- 1);
2102 /*TypeBuilders produce all sort of weird things*/
2103 g_assert (image_is_dynamic (klass
->image
) || field_offsets
[i
] > 0);
2104 real_size
= field_offsets
[i
] + size
;
2107 instance_size
= MAX (real_size
, instance_size
);
2109 if (instance_size
& (min_align
- 1)) {
2110 instance_size
+= min_align
- 1;
2111 instance_size
&= ~(min_align
- 1);
2115 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
: {
2117 for (i
= 0; i
< top
; i
++) {
2122 field
= &klass
->fields
[i
];
2125 * There must be info about all the fields in a type if it
2126 * uses explicit layout.
2128 if (mono_field_is_deleted (field
))
2130 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
2133 size
= mono_type_size (field
->type
, &align
);
2134 align
= packing_size
? MIN (packing_size
, align
): align
;
2135 min_align
= MAX (align
, min_align
);
2138 /* Already set by typebuilder_setup_fields () */
2139 field_offsets
[i
] = field
->offset
+ MONO_ABI_SIZEOF (MonoObject
);
2141 int idx
= first_field_idx
+ i
;
2143 mono_metadata_field_info (klass
->image
, idx
, &offset
, NULL
, NULL
);
2144 field_offsets
[i
] = offset
+ MONO_ABI_SIZEOF (MonoObject
);
2146 ftype
= mono_type_get_underlying_type (field
->type
);
2147 ftype
= mono_type_get_basic_type_from_generic (ftype
);
2148 if (type_has_references (klass
, ftype
)) {
2149 if (field_offsets
[i
] % TARGET_SIZEOF_VOID_P
) {
2150 mono_class_set_type_load_failure (klass
, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field
->name
);
2157 real_size
= MAX (real_size
, size
+ field_offsets
[i
]);
2160 /* check for incorrectly aligned or overlapped by a non-object field */
2161 #ifdef ENABLE_NETCORE
2162 guint8
*layout_check
;
2163 if (has_references
) {
2164 layout_check
= g_new0 (guint8
, real_size
);
2165 for (i
= 0; i
< top
&& !mono_class_has_failure (klass
); i
++) {
2166 field
= &klass
->fields
[i
];
2169 if (mono_field_is_deleted (field
))
2171 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
2174 int size
= mono_type_size (field
->type
, &align
);
2175 MonoType
*ftype
= mono_type_get_underlying_type (field
->type
);
2176 ftype
= mono_type_get_basic_type_from_generic (ftype
);
2177 guint8 type
= type_has_references (klass
, ftype
) ? 1 : 2;
2178 for (int j
= 0; j
< size
; j
++) {
2179 if (layout_check
[field_offsets
[i
] + j
] != 0 && layout_check
[field_offsets
[i
] + j
] != type
) {
2180 mono_class_set_type_load_failure (klass
, "Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", klass
->name
, field
->offset
);
2183 layout_check
[field_offsets
[i
] + j
] = type
;
2186 g_free (layout_check
);
2190 instance_size
= MAX (real_size
, instance_size
);
2191 if (!((layout
== TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) && explicit_size
)) {
2192 if (instance_size
& (min_align
- 1)) {
2193 instance_size
+= min_align
- 1;
2194 instance_size
&= ~(min_align
- 1);
2201 if (layout
!= TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) {
2203 * This leads to all kinds of problems with nested structs, so only
2204 * enable it when a MONO_DEBUG property is set.
2206 * For small structs, set min_align to at least the struct size to improve
2207 * performance, and since the JIT memset/memcpy code assumes this and generates
2208 * unaligned accesses otherwise. See #78990 for a testcase.
2210 if (mono_align_small_structs
&& top
) {
2211 if (instance_size
<= MONO_ABI_SIZEOF (MonoObject
) + MONO_ABI_SIZEOF (gpointer
))
2212 min_align
= MAX (min_align
, instance_size
- MONO_ABI_SIZEOF (MonoObject
));
2216 MonoType
*klass_byval_arg
= m_class_get_byval_arg (klass
);
2217 if (klass_byval_arg
->type
== MONO_TYPE_VAR
|| klass_byval_arg
->type
== MONO_TYPE_MVAR
)
2218 instance_size
= MONO_ABI_SIZEOF (MonoObject
) + mono_type_size (klass_byval_arg
, &min_align
);
2219 else if (klass_byval_arg
->type
== MONO_TYPE_PTR
)
2220 instance_size
= MONO_ABI_SIZEOF (MonoObject
) + MONO_ABI_SIZEOF (gpointer
);
2222 if (klass_byval_arg
->type
== MONO_TYPE_SZARRAY
|| klass_byval_arg
->type
== MONO_TYPE_ARRAY
)
2223 element_size
= mono_class_array_element_size (klass
->element_class
);
2225 /* Publish the data */
2226 mono_loader_lock ();
2227 if (klass
->instance_size
&& !klass
->image
->dynamic
&& klass_byval_arg
->type
!= MONO_TYPE_FNPTR
) {
2228 /* Might be already set using cached info */
2229 if (klass
->instance_size
!= instance_size
) {
2230 /* Emit info to help debugging */
2231 g_print ("%s\n", mono_class_full_name (klass
));
2232 g_print ("%d %d %d %d\n", klass
->instance_size
, instance_size
, klass
->blittable
, blittable
);
2233 g_print ("%d %d %d %d\n", klass
->has_references
, has_references
, klass
->packing_size
, packing_size
);
2234 g_print ("%d %d\n", klass
->min_align
, min_align
);
2235 for (i
= 0; i
< top
; ++i
) {
2236 field
= &klass
->fields
[i
];
2237 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
))
2238 printf (" %s %d %d %d\n", klass
->fields
[i
].name
, klass
->fields
[i
].offset
, field_offsets
[i
], fields_has_references
[i
]);
2241 g_assert (klass
->instance_size
== instance_size
);
2243 klass
->instance_size
= instance_size
;
2245 klass
->blittable
= blittable
;
2246 klass
->has_references
= has_references
;
2247 klass
->packing_size
= packing_size
;
2248 klass
->min_align
= min_align
;
2249 for (i
= 0; i
< top
; ++i
) {
2250 field
= &klass
->fields
[i
];
2251 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
))
2252 klass
->fields
[i
].offset
= field_offsets
[i
];
2255 if (klass_byval_arg
->type
== MONO_TYPE_SZARRAY
|| klass_byval_arg
->type
== MONO_TYPE_ARRAY
)
2256 klass
->sizes
.element_size
= element_size
;
2258 mono_memory_barrier ();
2259 klass
->size_inited
= 1;
2260 mono_loader_unlock ();
2263 * Compute static field layout and size
2264 * Static fields can reference the class itself, so this has to be
2265 * done after instance_size etc. are initialized.
2268 for (i
= 0; i
< top
; i
++) {
2272 field
= &klass
->fields
[i
];
2274 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) || field
->type
->attrs
& FIELD_ATTRIBUTE_LITERAL
)
2276 if (mono_field_is_deleted (field
))
2279 if (mono_type_has_exceptions (field
->type
)) {
2280 mono_class_set_type_load_failure (klass
, "Field '%s' has an invalid type.", field
->name
);
2284 has_static_fields
= TRUE
;
2286 size
= mono_type_size (field
->type
, &align
);
2287 field_offsets
[i
] = class_size
;
2288 /*align is always non-zero here*/
2289 field_offsets
[i
] += align
- 1;
2290 field_offsets
[i
] &= ~(align
- 1);
2291 class_size
= field_offsets
[i
] + size
;
2294 if (has_static_fields
&& class_size
== 0)
2295 /* Simplify code which depends on class_size != 0 if the class has static fields */
2298 /* Compute klass->has_static_refs */
2299 has_static_refs
= FALSE
;
2300 for (i
= 0; i
< top
; i
++) {
2303 field
= &klass
->fields
[i
];
2305 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
2306 ftype
= mono_type_get_underlying_type (field
->type
);
2307 ftype
= mono_type_get_basic_type_from_generic (ftype
);
2308 if (type_has_references (klass
, ftype
))
2309 has_static_refs
= TRUE
;
2313 /*valuetypes can't be neither bigger than 1Mb or empty. */
2314 if (klass
->valuetype
&& (klass
->instance_size
<= 0 || klass
->instance_size
> (0x100000 + MONO_ABI_SIZEOF (MonoObject
)))) {
2315 /* Special case compiler generated types */
2316 /* Hard to check for [CompilerGenerated] here */
2317 if (!strstr (klass
->name
, "StaticArrayInitTypeSize") && !strstr (klass
->name
, "$ArrayType"))
2318 mono_class_set_type_load_failure (klass
, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass
->instance_size
);
2321 // Weak field support
2324 // - generic instances
2325 // - Disallow on structs/static fields/nonref fields
2326 gboolean has_weak_fields
= FALSE
;
2328 if (mono_class_has_static_metadata (klass
)) {
2329 for (MonoClass
*p
= klass
; p
!= NULL
; p
= p
->parent
) {
2330 gpointer iter
= NULL
;
2331 guint32 first_field_idx
= mono_class_get_first_field_idx (p
);
2333 while ((field
= mono_class_get_fields_internal (p
, &iter
))) {
2334 guint32 field_idx
= first_field_idx
+ (field
- p
->fields
);
2335 if (MONO_TYPE_IS_REFERENCE (field
->type
) && mono_assembly_is_weak_field (p
->image
, field_idx
+ 1)) {
2336 has_weak_fields
= TRUE
;
2337 mono_trace_message (MONO_TRACE_TYPE
, "Field %s:%s at offset %x is weak.", field
->parent
->name
, field
->name
, field
->offset
);
2344 * Check that any fields of IsByRefLike type are instance
2345 * fields and only inside other IsByRefLike structs.
2347 * (Has to be done late because we call
2348 * mono_class_from_mono_type_internal which may recursively
2349 * refer to the current class)
2351 gboolean allow_isbyreflike_fields
= m_class_is_byreflike (klass
);
2352 for (i
= 0; i
< top
; i
++) {
2353 field
= &klass
->fields
[i
];
2355 if (mono_field_is_deleted (field
))
2357 if ((field
->type
->attrs
& FIELD_ATTRIBUTE_LITERAL
))
2359 MonoClass
*field_class
= NULL
;
2360 /* have to be careful not to recursively invoke mono_class_init on a static field.
2361 * for example - if the field is an array of a subclass of klass, we can loop.
2363 switch (field
->type
->type
) {
2364 case MONO_TYPE_TYPEDBYREF
:
2365 case MONO_TYPE_VALUETYPE
:
2366 case MONO_TYPE_GENERICINST
:
2367 field_class
= mono_class_from_mono_type_internal (field
->type
);
2372 if (!field_class
|| !m_class_is_byreflike (field_class
))
2374 if ((field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
2375 mono_class_set_type_load_failure (klass
, "Static ByRefLike field '%s' is not allowed", field
->name
);
2378 /* instance field */
2379 if (allow_isbyreflike_fields
)
2381 mono_class_set_type_load_failure (klass
, "Instance ByRefLike field '%s' not in a ref struct", field
->name
);
2386 /* Publish the data */
2387 mono_loader_lock ();
2389 klass
->sizes
.class_size
= class_size
;
2390 klass
->has_static_refs
= has_static_refs
;
2391 klass
->has_weak_fields
= has_weak_fields
;
2392 for (i
= 0; i
< top
; ++i
) {
2393 field
= &klass
->fields
[i
];
2395 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
2396 field
->offset
= field_offsets
[i
];
2398 mono_memory_barrier ();
2399 klass
->fields_inited
= 1;
2400 mono_loader_unlock ();
2402 g_free (field_offsets
);
2403 g_free (fields_has_references
);
2406 static int finalize_slot
= -1;
2409 initialize_object_slots (MonoClass
*klass
)
2413 if (klass
!= mono_defaults
.object_class
|| finalize_slot
>= 0)
2416 mono_class_setup_vtable (klass
);
2418 for (i
= 0; i
< klass
->vtable_size
; ++i
) {
2419 if (!strcmp (klass
->vtable
[i
]->name
, "Finalize")) {
2420 int const j
= finalize_slot
;
2421 g_assert (j
== -1 || j
== i
);
2426 g_assert (finalize_slot
>= 0);
2430 mono_class_get_object_finalize_slot ()
2432 return finalize_slot
;
2436 mono_class_get_default_finalize_method ()
2438 int const i
= finalize_slot
;
2439 return (i
< 0) ? NULL
: mono_defaults
.object_class
->vtable
[i
];
2443 MonoMethod
*array_method
;
2445 } GenericArrayMethodInfo
;
2447 static int generic_array_method_num
= 0;
2448 static GenericArrayMethodInfo
*generic_array_method_info
= NULL
;
2451 setup_generic_array_ifaces (MonoClass
*klass
, MonoClass
*iface
, MonoMethod
**methods
, int pos
, GHashTable
*cache
)
2453 MonoGenericContext tmp_context
;
2454 MonoGenericClass
*gclass
;
2457 // The interface can sometimes be a GTD in cases like IList
2458 // See: https://github.com/mono/mono/issues/7095#issuecomment-470465597
2459 if (mono_class_is_gtd (iface
)) {
2460 MonoType
*ty
= mono_class_gtd_get_canonical_inst (iface
);
2461 g_assert (ty
->type
== MONO_TYPE_GENERICINST
);
2462 gclass
= ty
->data
.generic_class
;
2464 gclass
= mono_class_get_generic_class (iface
);
2466 tmp_context
.class_inst
= NULL
;
2467 tmp_context
.method_inst
= gclass
->context
.class_inst
;
2468 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (m_class_get_byval_arg (iface), 0));
2470 for (i
= 0; i
< generic_array_method_num
; i
++) {
2472 MonoMethod
*m
= generic_array_method_info
[i
].array_method
;
2473 MonoMethod
*inflated
, *helper
;
2475 inflated
= mono_class_inflate_generic_method_checked (m
, &tmp_context
, error
);
2476 mono_error_assert_ok (error
);
2477 helper
= (MonoMethod
*)g_hash_table_lookup (cache
, inflated
);
2479 helper
= mono_marshal_get_generic_array_helper (klass
, generic_array_method_info
[i
].name
, inflated
);
2480 g_hash_table_insert (cache
, inflated
, helper
);
2482 methods
[pos
++] = helper
;
2487 generic_array_methods (MonoClass
*klass
)
2489 int i
, count_generic
= 0, mcount
;
2490 GList
*list
= NULL
, *tmp
;
2491 if (generic_array_method_num
)
2492 return generic_array_method_num
;
2493 mono_class_setup_methods (klass
->parent
); /*This is setting up System.Array*/
2494 g_assert (!mono_class_has_failure (klass
->parent
)); /*So hitting this assert is a huge problem*/
2495 mcount
= mono_class_get_method_count (klass
->parent
);
2496 for (i
= 0; i
< mcount
; i
++) {
2497 MonoMethod
*m
= klass
->parent
->methods
[i
];
2498 if (!strncmp (m
->name
, "InternalArray__", 15)) {
2500 list
= g_list_prepend (list
, m
);
2503 list
= g_list_reverse (list
);
2504 generic_array_method_info
= (GenericArrayMethodInfo
*)mono_image_alloc (mono_defaults
.corlib
, sizeof (GenericArrayMethodInfo
) * count_generic
);
2506 for (tmp
= list
; tmp
; tmp
= tmp
->next
) {
2507 const char *mname
, *iname
;
2509 MonoMethod
*m
= (MonoMethod
*)tmp
->data
;
2510 const char *ireadonlylist_prefix
= "InternalArray__IReadOnlyList_";
2511 const char *ireadonlycollection_prefix
= "InternalArray__IReadOnlyCollection_";
2513 generic_array_method_info
[i
].array_method
= m
;
2514 if (!strncmp (m
->name
, "InternalArray__ICollection_", 27)) {
2515 iname
= "System.Collections.Generic.ICollection`1.";
2516 mname
= m
->name
+ 27;
2517 } else if (!strncmp (m
->name
, "InternalArray__IEnumerable_", 27)) {
2518 iname
= "System.Collections.Generic.IEnumerable`1.";
2519 mname
= m
->name
+ 27;
2520 } else if (!strncmp (m
->name
, ireadonlylist_prefix
, strlen (ireadonlylist_prefix
))) {
2521 iname
= "System.Collections.Generic.IReadOnlyList`1.";
2522 mname
= m
->name
+ strlen (ireadonlylist_prefix
);
2523 } else if (!strncmp (m
->name
, ireadonlycollection_prefix
, strlen (ireadonlycollection_prefix
))) {
2524 iname
= "System.Collections.Generic.IReadOnlyCollection`1.";
2525 mname
= m
->name
+ strlen (ireadonlycollection_prefix
);
2526 } else if (!strncmp (m
->name
, "InternalArray__", 15)) {
2527 iname
= "System.Collections.Generic.IList`1.";
2528 mname
= m
->name
+ 15;
2530 g_assert_not_reached ();
2533 name
= (gchar
*)mono_image_alloc (mono_defaults
.corlib
, strlen (iname
) + strlen (mname
) + 1);
2534 strcpy (name
, iname
);
2535 strcpy (name
+ strlen (iname
), mname
);
2536 generic_array_method_info
[i
].name
= name
;
2539 /*g_print ("array generic methods: %d\n", count_generic);*/
2541 generic_array_method_num
= count_generic
;
2543 return generic_array_method_num
;
2546 static int array_get_method_count (MonoClass
*klass
)
2548 MonoType
*klass_byval_arg
= m_class_get_byval_arg (klass
);
2549 if (klass_byval_arg
->type
== MONO_TYPE_ARRAY
)
2551 /* ctor([int32]*rank) */
2552 /* ctor([int32]*rank*2) */
2557 else if (klass_byval_arg
->type
== MONO_TYPE_SZARRAY
&& klass
->rank
== 1 && klass
->element_class
->rank
)
2558 /* Jagged arrays are typed as MONO_TYPE_SZARRAY but have an extra ctor in .net which creates an array of arrays */
2560 /* ctor([int32], [int32]) */
2566 /* Vectors don't have additional constructor since a zero lower bound is assumed */
2567 /* ctor([int32]*rank) */
2574 static gboolean
array_supports_additional_ctor_method (MonoClass
*klass
)
2576 MonoType
*klass_byval_arg
= m_class_get_byval_arg (klass
);
2577 if (klass_byval_arg
->type
== MONO_TYPE_ARRAY
)
2580 else if (klass_byval_arg
->type
== MONO_TYPE_SZARRAY
&& klass
->rank
== 1 && klass
->element_class
->rank
)
2589 * Global pool of interface IDs, represented as a bitset.
2590 * LOCKING: Protected by the classes lock.
2592 static MonoBitSet
*global_interface_bitset
= NULL
;
2595 * mono_unload_interface_ids:
2596 * @bitset: bit set of interface IDs
2598 * When an image is unloaded, the interface IDs associated with
2599 * the image are put back in the global pool of IDs so the numbers
2603 mono_unload_interface_ids (MonoBitSet
*bitset
)
2606 mono_bitset_sub (global_interface_bitset
, bitset
);
2611 mono_unload_interface_id (MonoClass
*klass
)
2613 if (global_interface_bitset
&& klass
->interface_id
) {
2615 mono_bitset_clear (global_interface_bitset
, klass
->interface_id
);
2621 * mono_get_unique_iid:
2622 * \param klass interface
2624 * Assign a unique integer ID to the interface represented by \p klass.
2625 * The ID will positive and as small as possible.
2626 * LOCKING: Acquires the classes lock.
2627 * \returns The new ID.
2630 mono_get_unique_iid (MonoClass
*klass
)
2634 g_assert (MONO_CLASS_IS_INTERFACE_INTERNAL (klass
));
2638 if (!global_interface_bitset
) {
2639 global_interface_bitset
= mono_bitset_new (128, 0);
2640 mono_bitset_set (global_interface_bitset
, 0); //don't let 0 be a valid iid
2643 iid
= mono_bitset_find_first_unset (global_interface_bitset
, -1);
2645 int old_size
= mono_bitset_size (global_interface_bitset
);
2646 MonoBitSet
*new_set
= mono_bitset_clone (global_interface_bitset
, old_size
* 2);
2647 mono_bitset_free (global_interface_bitset
);
2648 global_interface_bitset
= new_set
;
2651 mono_bitset_set (global_interface_bitset
, iid
);
2652 /* set the bit also in the per-image set */
2653 if (!mono_class_is_ginst (klass
)) {
2654 if (klass
->image
->interface_bitset
) {
2655 if (iid
>= mono_bitset_size (klass
->image
->interface_bitset
)) {
2656 MonoBitSet
*new_set
= mono_bitset_clone (klass
->image
->interface_bitset
, iid
+ 1);
2657 mono_bitset_free (klass
->image
->interface_bitset
);
2658 klass
->image
->interface_bitset
= new_set
;
2661 klass
->image
->interface_bitset
= mono_bitset_new (iid
+ 1, 0);
2663 mono_bitset_set (klass
->image
->interface_bitset
, iid
);
2668 #ifndef MONO_SMALL_CONFIG
2669 if (mono_print_vtable
) {
2671 char *type_name
= mono_type_full_name (m_class_get_byval_arg (klass
));
2672 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
2673 if (gklass
&& !gklass
->context
.class_inst
->is_open
) {
2674 generic_id
= gklass
->context
.class_inst
->id
;
2675 g_assert (generic_id
!= 0);
2679 printf ("Interface: assigned id %d to %s|%s|%d\n", iid
, klass
->image
->assembly_name
, type_name
, generic_id
);
2684 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2685 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2686 g_assert (iid
< INT_MAX
);
2691 * mono_class_init_internal:
2692 * \param klass the class to initialize
2694 * Compute the \c instance_size, \c class_size and other infos that cannot be
2695 * computed at \c mono_class_get time. Also compute vtable_size if possible.
2696 * Initializes the following fields in \p klass:
2697 * - all the fields initialized by \c mono_class_init_sizes
2702 * LOCKING: Acquires the loader lock.
2704 * \returns TRUE on success or FALSE if there was a problem in loading
2705 * the type (incorrect assemblies, missing assemblies, methods, etc).
2708 mono_class_init_internal (MonoClass
*klass
)
2710 int i
, vtable_size
= 0, array_method_count
= 0;
2711 MonoCachedClassInfo cached_info
;
2712 gboolean has_cached_info
;
2713 gboolean locked
= FALSE
;
2714 gboolean ghcimpl
= FALSE
;
2715 gboolean has_cctor
= FALSE
;
2716 int first_iface_slot
= 0;
2720 /* Double-checking locking pattern */
2721 if (klass
->inited
|| mono_class_has_failure (klass
))
2722 return !mono_class_has_failure (klass
);
2724 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
2727 * This function can recursively call itself.
2729 GSList
*init_list
= (GSList
*)mono_native_tls_get_value (init_pending_tls_id
);
2730 if (g_slist_find (init_list
, klass
)) {
2731 mono_class_set_type_load_failure (klass
, "Recursive type definition detected %s.%s", klass
->name_space
, klass
->name
);
2732 goto leave_no_init_pending
;
2734 init_list
= g_slist_prepend (init_list
, klass
);
2735 mono_native_tls_set_value (init_pending_tls_id
, init_list
);
2738 * We want to avoid doing complicated work inside locks, so we compute all the required
2739 * information and write it to @klass inside a lock.
2742 if (mono_verifier_is_enabled_for_class (klass
) && !mono_verifier_verify_class (klass
)) {
2743 mono_class_set_type_load_failure (klass
, "%s", concat_two_strings_with_zero (klass
->image
, klass
->name
, klass
->image
->assembly_name
));
2747 MonoType
*klass_byval_arg
;
2748 klass_byval_arg
= m_class_get_byval_arg (klass
);
2749 if (klass_byval_arg
->type
== MONO_TYPE_ARRAY
|| klass_byval_arg
->type
== MONO_TYPE_SZARRAY
) {
2750 MonoClass
*element_class
= klass
->element_class
;
2751 MonoClass
*cast_class
= klass
->cast_class
;
2753 if (!element_class
->inited
)
2754 mono_class_init_internal (element_class
);
2755 if (mono_class_set_type_load_failure_causedby_class (klass
, element_class
, "Could not load array element class"))
2757 if (!cast_class
->inited
)
2758 mono_class_init_internal (cast_class
);
2759 if (mono_class_set_type_load_failure_causedby_class (klass
, cast_class
, "Could not load array cast class"))
2763 UnlockedIncrement (&mono_stats
.initialized_class_count
);
2765 if (mono_class_is_ginst (klass
) && !mono_class_get_generic_class (klass
)->is_dynamic
) {
2766 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
2768 mono_class_init_internal (gklass
);
2769 if (mono_class_set_type_load_failure_causedby_class (klass
, gklass
, "Generic Type Definition failed to init"))
2772 if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass
))
2773 mono_class_setup_interface_id (klass
);
2776 if (klass
->parent
&& !klass
->parent
->inited
)
2777 mono_class_init_internal (klass
->parent
);
2779 has_cached_info
= mono_class_get_cached_class_info (klass
, &cached_info
);
2781 /* Compute instance size etc. */
2782 init_sizes_with_info (klass
, has_cached_info
? &cached_info
: NULL
);
2783 if (mono_class_has_failure (klass
))
2786 mono_class_setup_supertypes (klass
);
2788 initialize_object_slots (klass
);
2791 * Initialize the rest of the data without creating a generic vtable if possible.
2792 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
2793 * also avoid computing a generic vtable.
2795 if (has_cached_info
) {
2797 vtable_size
= cached_info
.vtable_size
;
2798 ghcimpl
= cached_info
.ghcimpl
;
2799 has_cctor
= cached_info
.has_cctor
;
2800 } else if (klass
->rank
== 1 && klass_byval_arg
->type
== MONO_TYPE_SZARRAY
) {
2801 /* SZARRAY can have 3 vtable layouts, with and without the stelemref method and enum element type
2802 * The first slot if for array with.
2804 static int szarray_vtable_size
[3] = { 0 };
2808 if (MONO_TYPE_IS_REFERENCE (m_class_get_byval_arg (m_class_get_element_class (klass
))))
2810 else if (klass
->element_class
->enumtype
)
2816 if (!szarray_vtable_size
[slot
]) {
2817 mono_class_setup_vtable (klass
);
2818 szarray_vtable_size
[slot
] = klass
->vtable_size
;
2819 vtable_size
= klass
->vtable_size
;
2821 vtable_size
= szarray_vtable_size
[slot
];
2823 } else if (mono_class_is_ginst (klass
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
2824 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
2826 /* Generic instance case */
2827 ghcimpl
= gklass
->ghcimpl
;
2828 has_cctor
= gklass
->has_cctor
;
2830 mono_class_setup_vtable (gklass
);
2831 if (mono_class_set_type_load_failure_causedby_class (klass
, gklass
, "Generic type definition failed to init"))
2834 vtable_size
= gklass
->vtable_size
;
2838 /* C# doesn't allow interfaces to have cctors */
2839 if (!MONO_CLASS_IS_INTERFACE_INTERNAL (klass
) || klass
->image
!= mono_defaults
.corlib
) {
2840 MonoMethod
*cmethod
= NULL
;
2842 if (mono_class_is_ginst (klass
)) {
2843 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
2845 /* Generic instance case */
2846 ghcimpl
= gklass
->ghcimpl
;
2847 has_cctor
= gklass
->has_cctor
;
2848 } else if (klass
->type_token
&& !image_is_dynamic(klass
->image
)) {
2849 cmethod
= mono_find_method_in_metadata (klass
, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME
);
2850 /* The find_method function ignores the 'flags' argument */
2851 if (cmethod
&& (cmethod
->flags
& METHOD_ATTRIBUTE_SPECIAL_NAME
))
2854 mono_class_setup_methods (klass
);
2855 if (mono_class_has_failure (klass
))
2858 int mcount
= mono_class_get_method_count (klass
);
2859 for (i
= 0; i
< mcount
; ++i
) {
2860 MonoMethod
*method
= klass
->methods
[i
];
2861 if ((method
->flags
& METHOD_ATTRIBUTE_SPECIAL_NAME
) &&
2862 (strcmp (".cctor", method
->name
) == 0)) {
2872 array_method_count
= array_get_method_count (klass
);
2874 if (klass
->interface_count
) {
2875 int count_generic
= generic_array_methods (klass
);
2876 array_method_count
+= klass
->interface_count
* count_generic
;
2880 if (klass
->parent
) {
2881 if (!klass
->parent
->vtable_size
)
2882 mono_class_setup_vtable (klass
->parent
);
2883 if (mono_class_set_type_load_failure_causedby_class (klass
, klass
->parent
, "Parent class vtable failed to initialize"))
2885 g_assert (klass
->parent
->vtable_size
);
2886 first_iface_slot
= klass
->parent
->vtable_size
;
2887 if (mono_class_setup_need_stelemref_method (klass
))
2892 * Do the actual changes to @klass inside the loader lock
2894 mono_loader_lock ();
2897 if (klass
->inited
|| mono_class_has_failure (klass
)) {
2898 /* Somebody might have gotten in before us */
2902 UnlockedIncrement (&mono_stats
.initialized_class_count
);
2904 if (mono_class_is_ginst (klass
) && !mono_class_get_generic_class (klass
)->is_dynamic
)
2905 UnlockedIncrement (&mono_stats
.generic_class_count
);
2907 if (mono_class_is_ginst (klass
) || image_is_dynamic (klass
->image
) || !klass
->type_token
|| (has_cached_info
&& !cached_info
.has_nested_classes
))
2908 klass
->nested_classes_inited
= TRUE
;
2909 klass
->ghcimpl
= ghcimpl
;
2910 klass
->has_cctor
= has_cctor
;
2912 klass
->vtable_size
= vtable_size
;
2913 if (has_cached_info
) {
2914 klass
->has_finalize
= cached_info
.has_finalize
;
2915 klass
->has_finalize_inited
= TRUE
;
2918 mono_class_set_method_count (klass
, array_method_count
);
2920 mono_loader_unlock ();
2923 mono_class_setup_interface_offsets_internal (klass
, first_iface_slot
, TRUE
);
2925 if (mono_security_core_clr_enabled ())
2926 mono_security_core_clr_check_inheritance (klass
);
2928 if (mono_class_is_ginst (klass
) && !mono_verifier_class_is_valid_generic_instantiation (klass
))
2929 mono_class_set_type_load_failure (klass
, "Invalid generic instantiation");
2934 init_list
= (GSList
*)mono_native_tls_get_value (init_pending_tls_id
);
2935 init_list
= g_slist_remove (init_list
, klass
);
2936 mono_native_tls_set_value (init_pending_tls_id
, init_list
);
2938 leave_no_init_pending
:
2940 mono_loader_unlock ();
2942 /* Leave this for last */
2943 mono_loader_lock ();
2945 mono_loader_unlock ();
2947 return !mono_class_has_failure (klass
);
2951 mono_class_init_checked (MonoClass
*klass
, MonoError
*error
)
2954 gboolean
const success
= mono_class_init_internal (klass
);
2956 mono_error_set_for_class_failure (error
, klass
);
2962 * COM initialization is delayed until needed.
2963 * However when a [ComImport] attribute is present on a type it will trigger
2964 * the initialization. This is not a problem unless the BCL being executed
2965 * lacks the types that COM depends on (e.g. Variant on Silverlight).
2968 init_com_from_comimport (MonoClass
*klass
)
2970 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
2971 if (mono_security_core_clr_enabled ()) {
2972 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
2973 if (!mono_security_core_clr_determine_platform_image (klass
->image
)) {
2974 /* but it can not be made available for application (i.e. user code) since all COM calls
2975 * are considered native calls. In this case we fail with a TypeLoadException (just like
2976 * Silverlight 2 does */
2977 mono_class_set_type_load_failure (klass
, "");
2982 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
2984 #endif /*DISABLE_COM*/
2987 * LOCKING: this assumes the loader lock is held
2990 mono_class_setup_parent (MonoClass
*klass
, MonoClass
*parent
)
2992 gboolean system_namespace
;
2993 gboolean is_corlib
= mono_is_corlib_image (klass
->image
);
2995 system_namespace
= !strcmp (klass
->name_space
, "System") && is_corlib
;
2997 /* if root of the hierarchy */
2998 if (system_namespace
&& !strcmp (klass
->name
, "Object")) {
2999 klass
->parent
= NULL
;
3000 klass
->instance_size
= MONO_ABI_SIZEOF (MonoObject
);
3003 if (!strcmp (klass
->name
, "<Module>")) {
3004 klass
->parent
= NULL
;
3005 klass
->instance_size
= 0;
3009 if (!MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3010 /* Imported COM Objects always derive from __ComObject. */
3012 if (MONO_CLASS_IS_IMPORT (klass
)) {
3013 init_com_from_comimport (klass
);
3014 if (parent
== mono_defaults
.object_class
)
3015 parent
= mono_class_get_com_object_class ();
3019 /* set the parent to something useful and safe, but mark the type as broken */
3020 parent
= mono_defaults
.object_class
;
3021 mono_class_set_type_load_failure (klass
, "");
3025 klass
->parent
= parent
;
3027 if (mono_class_is_ginst (parent
) && !parent
->name
) {
3029 * If the parent is a generic instance, we may get
3030 * called before it is fully initialized, especially
3031 * before it has its name.
3036 #ifndef DISABLE_REMOTING
3037 klass
->marshalbyref
= parent
->marshalbyref
;
3038 klass
->contextbound
= parent
->contextbound
;
3041 klass
->delegate
= parent
->delegate
;
3043 if (MONO_CLASS_IS_IMPORT (klass
) || mono_class_is_com_object (parent
))
3044 mono_class_set_is_com_object (klass
);
3046 if (system_namespace
) {
3047 #ifndef DISABLE_REMOTING
3048 if (klass
->name
[0] == 'M' && !strcmp (klass
->name
, "MarshalByRefObject"))
3049 klass
->marshalbyref
= 1;
3051 if (klass
->name
[0] == 'C' && !strcmp (klass
->name
, "ContextBoundObject"))
3052 klass
->contextbound
= 1;
3054 if (klass
->name
[0] == 'D' && !strcmp (klass
->name
, "Delegate"))
3055 klass
->delegate
= 1;
3058 if (klass
->parent
->enumtype
|| (mono_is_corlib_image (klass
->parent
->image
) && (strcmp (klass
->parent
->name
, "ValueType") == 0) &&
3059 (strcmp (klass
->parent
->name_space
, "System") == 0)))
3060 klass
->valuetype
= 1;
3061 if (mono_is_corlib_image (klass
->parent
->image
) && ((strcmp (klass
->parent
->name
, "Enum") == 0) && (strcmp (klass
->parent
->name_space
, "System") == 0))) {
3062 klass
->valuetype
= klass
->enumtype
= 1;
3064 /*klass->enumtype = klass->parent->enumtype; */
3066 /* initialize com types if COM interfaces are present */
3068 if (MONO_CLASS_IS_IMPORT (klass
))
3069 init_com_from_comimport (klass
);
3071 klass
->parent
= NULL
;
3076 /* Locking: must be called with the loader lock held. */
3078 mono_class_setup_interface_id_nolock (MonoClass
*klass
)
3080 if (!MONO_CLASS_IS_INTERFACE_INTERNAL (klass
) || klass
->interface_id
)
3082 klass
->interface_id
= mono_get_unique_iid (klass
);
3084 if (mono_is_corlib_image (klass
->image
) && !strcmp (m_class_get_name_space (klass
), "System.Collections.Generic")) {
3085 //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
3086 /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3087 * MS returns diferrent types based on which instance is called. For example:
3088 * object obj = new byte[10][];
3089 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3090 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3093 const char *name
= m_class_get_name (klass
);
3094 if (!strcmp (name
, "IList`1") || !strcmp (name
, "ICollection`1") || !strcmp (name
, "IEnumerable`1") || !strcmp (name
, "IEnumerator`1"))
3095 klass
->is_array_special_interface
= 1;
3101 * LOCKING: this assumes the loader lock is held
3104 mono_class_setup_mono_type (MonoClass
*klass
)
3106 const char *name
= klass
->name
;
3107 const char *nspace
= klass
->name_space
;
3108 gboolean is_corlib
= mono_is_corlib_image (klass
->image
);
3110 klass
->this_arg
.byref
= 1;
3111 klass
->this_arg
.data
.klass
= klass
;
3112 klass
->this_arg
.type
= MONO_TYPE_CLASS
;
3113 klass
->_byval_arg
.data
.klass
= klass
;
3114 klass
->_byval_arg
.type
= MONO_TYPE_CLASS
;
3116 if (is_corlib
&& !strcmp (nspace
, "System")) {
3117 if (!strcmp (name
, "ValueType")) {
3119 * do not set the valuetype bit for System.ValueType.
3120 * klass->valuetype = 1;
3122 klass
->blittable
= TRUE
;
3123 } else if (!strcmp (name
, "Enum")) {
3125 * do not set the valuetype bit for System.Enum.
3126 * klass->valuetype = 1;
3128 klass
->valuetype
= 0;
3129 klass
->enumtype
= 0;
3130 } else if (!strcmp (name
, "Object")) {
3131 klass
->_byval_arg
.type
= MONO_TYPE_OBJECT
;
3132 klass
->this_arg
.type
= MONO_TYPE_OBJECT
;
3133 } else if (!strcmp (name
, "String")) {
3134 klass
->_byval_arg
.type
= MONO_TYPE_STRING
;
3135 klass
->this_arg
.type
= MONO_TYPE_STRING
;
3136 } else if (!strcmp (name
, "TypedReference")) {
3137 klass
->_byval_arg
.type
= MONO_TYPE_TYPEDBYREF
;
3138 klass
->this_arg
.type
= MONO_TYPE_TYPEDBYREF
;
3142 if (klass
->valuetype
) {
3143 int t
= MONO_TYPE_VALUETYPE
;
3145 if (is_corlib
&& !strcmp (nspace
, "System")) {
3148 if (!strcmp (name
, "Boolean")) {
3149 t
= MONO_TYPE_BOOLEAN
;
3150 } else if (!strcmp(name
, "Byte")) {
3152 klass
->blittable
= TRUE
;
3156 if (!strcmp (name
, "Char")) {
3161 if (!strcmp (name
, "Double")) {
3163 klass
->blittable
= TRUE
;
3167 if (!strcmp (name
, "Int32")) {
3169 klass
->blittable
= TRUE
;
3170 } else if (!strcmp(name
, "Int16")) {
3172 klass
->blittable
= TRUE
;
3173 } else if (!strcmp(name
, "Int64")) {
3175 klass
->blittable
= TRUE
;
3176 } else if (!strcmp(name
, "IntPtr")) {
3178 klass
->blittable
= TRUE
;
3182 if (!strcmp (name
, "Single")) {
3184 klass
->blittable
= TRUE
;
3185 } else if (!strcmp(name
, "SByte")) {
3187 klass
->blittable
= TRUE
;
3191 if (!strcmp (name
, "UInt32")) {
3193 klass
->blittable
= TRUE
;
3194 } else if (!strcmp(name
, "UInt16")) {
3196 klass
->blittable
= TRUE
;
3197 } else if (!strcmp(name
, "UInt64")) {
3199 klass
->blittable
= TRUE
;
3200 } else if (!strcmp(name
, "UIntPtr")) {
3202 klass
->blittable
= TRUE
;
3206 if (!strcmp (name
, "TypedReference")) {
3207 t
= MONO_TYPE_TYPEDBYREF
;
3208 klass
->blittable
= TRUE
;
3212 if (!strcmp (name
, "Void")) {
3220 klass
->_byval_arg
.type
= (MonoTypeEnum
)t
;
3221 klass
->this_arg
.type
= (MonoTypeEnum
)t
;
3224 mono_class_setup_interface_id_nolock (klass
);
3228 create_array_method (MonoClass
*klass
, const char *name
, MonoMethodSignature
*sig
)
3232 method
= (MonoMethod
*) mono_image_alloc0 (klass
->image
, sizeof (MonoMethodPInvoke
));
3233 method
->klass
= klass
;
3234 method
->flags
= METHOD_ATTRIBUTE_PUBLIC
;
3235 method
->iflags
= METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
;
3236 method
->signature
= sig
;
3237 method
->name
= name
;
3240 if (name
[0] == '.') {
3241 method
->flags
|= METHOD_ATTRIBUTE_RT_SPECIAL_NAME
| METHOD_ATTRIBUTE_SPECIAL_NAME
;
3243 method
->iflags
|= METHOD_IMPL_ATTRIBUTE_RUNTIME
;
3249 * mono_class_setup_methods:
3252 * Initializes the 'methods' array in CLASS.
3253 * Calling this method should be avoided if possible since it allocates a lot
3254 * of long-living MonoMethod structures.
3255 * Methods belonging to an interface are assigned a sequential slot starting
3258 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
3261 mono_class_setup_methods (MonoClass
*klass
)
3264 MonoMethod
**methods
;
3269 if (mono_class_is_ginst (klass
)) {
3271 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
3273 mono_class_init_internal (gklass
);
3274 if (!mono_class_has_failure (gklass
))
3275 mono_class_setup_methods (gklass
);
3276 if (mono_class_set_type_load_failure_causedby_class (klass
, gklass
, "Generic type definition failed to load"))
3279 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
3280 count
= mono_class_get_method_count (gklass
);
3281 methods
= (MonoMethod
**)mono_class_alloc0 (klass
, sizeof (MonoMethod
*) * (count
+ 1));
3283 for (i
= 0; i
< count
; i
++) {
3284 methods
[i
] = mono_class_inflate_generic_method_full_checked (
3285 gklass
->methods
[i
], klass
, mono_class_get_context (klass
), error
);
3286 if (!is_ok (error
)) {
3287 char *method
= mono_method_full_name (gklass
->methods
[i
], TRUE
);
3288 mono_class_set_type_load_failure (klass
, "Could not inflate method %s due to %s", method
, mono_error_get_message (error
));
3291 mono_error_cleanup (error
);
3295 } else if (klass
->rank
) {
3297 MonoMethod
*amethod
;
3298 MonoMethodSignature
*sig
;
3299 int count_generic
= 0, first_generic
= 0;
3302 count
= array_get_method_count (klass
);
3304 mono_class_setup_interfaces (klass
, error
);
3305 g_assert (is_ok (error
)); /*FIXME can this fail for array types?*/
3307 if (klass
->interface_count
) {
3308 count_generic
= generic_array_methods (klass
);
3309 first_generic
= count
;
3310 count
+= klass
->interface_count
* count_generic
;
3313 methods
= (MonoMethod
**)mono_class_alloc0 (klass
, sizeof (MonoMethod
*) * count
);
3315 sig
= mono_metadata_signature_alloc (klass
->image
, klass
->rank
);
3316 sig
->ret
= mono_get_void_type ();
3317 sig
->pinvoke
= TRUE
;
3318 sig
->hasthis
= TRUE
;
3319 for (i
= 0; i
< klass
->rank
; ++i
)
3320 sig
->params
[i
] = mono_get_int32_type ();
3322 amethod
= create_array_method (klass
, ".ctor", sig
);
3323 methods
[method_num
++] = amethod
;
3325 if (array_supports_additional_ctor_method (klass
)) {
3326 sig
= mono_metadata_signature_alloc (klass
->image
, klass
->rank
* 2);
3327 sig
->ret
= mono_get_void_type ();
3328 sig
->pinvoke
= TRUE
;
3329 sig
->hasthis
= TRUE
;
3330 for (i
= 0; i
< klass
->rank
* 2; ++i
)
3331 sig
->params
[i
] = mono_get_int32_type ();
3333 amethod
= create_array_method (klass
, ".ctor", sig
);
3334 methods
[method_num
++] = amethod
;
3337 /* element Get (idx11, [idx2, ...]) */
3338 sig
= mono_metadata_signature_alloc (klass
->image
, klass
->rank
);
3339 sig
->ret
= m_class_get_byval_arg (m_class_get_element_class (klass
));
3340 sig
->pinvoke
= TRUE
;
3341 sig
->hasthis
= TRUE
;
3342 for (i
= 0; i
< klass
->rank
; ++i
)
3343 sig
->params
[i
] = mono_get_int32_type ();
3344 amethod
= create_array_method (klass
, "Get", sig
);
3345 methods
[method_num
++] = amethod
;
3346 /* element& Address (idx11, [idx2, ...]) */
3347 sig
= mono_metadata_signature_alloc (klass
->image
, klass
->rank
);
3348 sig
->ret
= &klass
->element_class
->this_arg
;
3349 sig
->pinvoke
= TRUE
;
3350 sig
->hasthis
= TRUE
;
3351 for (i
= 0; i
< klass
->rank
; ++i
)
3352 sig
->params
[i
] = mono_get_int32_type ();
3353 amethod
= create_array_method (klass
, "Address", sig
);
3354 methods
[method_num
++] = amethod
;
3355 /* void Set (idx11, [idx2, ...], element) */
3356 sig
= mono_metadata_signature_alloc (klass
->image
, klass
->rank
+ 1);
3357 sig
->ret
= mono_get_void_type ();
3358 sig
->pinvoke
= TRUE
;
3359 sig
->hasthis
= TRUE
;
3360 for (i
= 0; i
< klass
->rank
; ++i
)
3361 sig
->params
[i
] = mono_get_int32_type ();
3362 sig
->params
[i
] = m_class_get_byval_arg (m_class_get_element_class (klass
));
3363 amethod
= create_array_method (klass
, "Set", sig
);
3364 methods
[method_num
++] = amethod
;
3366 GHashTable
*cache
= g_hash_table_new (NULL
, NULL
);
3367 for (i
= 0; i
< klass
->interface_count
; i
++)
3368 setup_generic_array_ifaces (klass
, klass
->interfaces
[i
], methods
, first_generic
+ i
* count_generic
, cache
);
3369 g_hash_table_destroy (cache
);
3370 } else if (mono_class_has_static_metadata (klass
)) {
3372 int first_idx
= mono_class_get_first_method_idx (klass
);
3374 count
= mono_class_get_method_count (klass
);
3375 methods
= (MonoMethod
**)mono_class_alloc (klass
, sizeof (MonoMethod
*) * count
);
3376 for (i
= 0; i
< count
; ++i
) {
3377 int idx
= mono_metadata_translate_token_index (klass
->image
, MONO_TABLE_METHOD
, first_idx
+ i
+ 1);
3378 methods
[i
] = mono_get_method_checked (klass
->image
, MONO_TOKEN_METHOD_DEF
| idx
, klass
, NULL
, error
);
3380 mono_class_set_type_load_failure (klass
, "Could not load method %d due to %s", i
, mono_error_get_message (error
));
3381 mono_error_cleanup (error
);
3385 methods
= (MonoMethod
**)mono_class_alloc (klass
, sizeof (MonoMethod
*) * 1);
3389 if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3391 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
3392 for (i
= 0; i
< count
; ++i
) {
3393 if (methods
[i
]->flags
& METHOD_ATTRIBUTE_VIRTUAL
)
3395 if (method_is_reabstracted (methods
[i
]->flags
)) {
3396 if (!methods
[i
]->is_inflated
)
3397 mono_method_set_is_reabstracted (methods
[i
]);
3400 methods
[i
]->slot
= slot
++;
3405 mono_image_lock (klass
->image
);
3407 if (!klass
->methods
) {
3408 mono_class_set_method_count (klass
, count
);
3410 /* Needed because of the double-checking locking pattern */
3411 mono_memory_barrier ();
3413 klass
->methods
= methods
;
3416 mono_image_unlock (klass
->image
);
3420 * mono_class_setup_properties:
3422 * Initialize klass->ext.property and klass->ext.properties.
3424 * This method can fail the class.
3427 mono_class_setup_properties (MonoClass
*klass
)
3429 guint startm
, endm
, i
, j
;
3430 guint32 cols
[MONO_PROPERTY_SIZE
];
3431 MonoTableInfo
*msemt
= &klass
->image
->tables
[MONO_TABLE_METHODSEMANTICS
];
3432 MonoProperty
*properties
;
3435 MonoClassPropertyInfo
*info
;
3437 info
= mono_class_get_property_info (klass
);
3441 if (mono_class_is_ginst (klass
)) {
3442 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
3444 mono_class_init_internal (gklass
);
3445 mono_class_setup_properties (gklass
);
3446 if (mono_class_set_type_load_failure_causedby_class (klass
, gklass
, "Generic type definition failed to load"))
3449 MonoClassPropertyInfo
*ginfo
= mono_class_get_property_info (gklass
);
3450 properties
= mono_class_new0 (klass
, MonoProperty
, ginfo
->count
+ 1);
3452 for (i
= 0; i
< ginfo
->count
; i
++) {
3454 MonoProperty
*prop
= &properties
[i
];
3456 *prop
= ginfo
->properties
[i
];
3459 prop
->get
= mono_class_inflate_generic_method_full_checked (
3460 prop
->get
, klass
, mono_class_get_context (klass
), error
);
3462 prop
->set
= mono_class_inflate_generic_method_full_checked (
3463 prop
->set
, klass
, mono_class_get_context (klass
), error
);
3465 g_assert (is_ok (error
)); /*FIXME proper error handling*/
3466 prop
->parent
= klass
;
3469 first
= ginfo
->first
;
3470 count
= ginfo
->count
;
3472 first
= mono_metadata_properties_from_typedef (klass
->image
, mono_metadata_token_index (klass
->type_token
) - 1, &last
);
3473 count
= last
- first
;
3476 mono_class_setup_methods (klass
);
3477 if (mono_class_has_failure (klass
))
3481 properties
= (MonoProperty
*)mono_class_alloc0 (klass
, sizeof (MonoProperty
) * count
);
3482 for (i
= first
; i
< last
; ++i
) {
3483 mono_metadata_decode_table_row (klass
->image
, MONO_TABLE_PROPERTY
, i
, cols
, MONO_PROPERTY_SIZE
);
3484 properties
[i
- first
].parent
= klass
;
3485 properties
[i
- first
].attrs
= cols
[MONO_PROPERTY_FLAGS
];
3486 properties
[i
- first
].name
= mono_metadata_string_heap (klass
->image
, cols
[MONO_PROPERTY_NAME
]);
3488 startm
= mono_metadata_methods_from_property (klass
->image
, i
, &endm
);
3489 int first_idx
= mono_class_get_first_method_idx (klass
);
3490 for (j
= startm
; j
< endm
; ++j
) {
3493 mono_metadata_decode_row (msemt
, j
, cols
, MONO_METHOD_SEMA_SIZE
);
3495 if (klass
->image
->uncompressed_metadata
) {
3497 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
3498 method
= mono_get_method_checked (klass
->image
, MONO_TOKEN_METHOD_DEF
| cols
[MONO_METHOD_SEMA_METHOD
], klass
, NULL
, error
);
3499 mono_error_cleanup (error
); /* FIXME don't swallow this error */
3501 method
= klass
->methods
[cols
[MONO_METHOD_SEMA_METHOD
] - 1 - first_idx
];
3504 switch (cols
[MONO_METHOD_SEMA_SEMANTICS
]) {
3505 case METHOD_SEMANTIC_SETTER
:
3506 properties
[i
- first
].set
= method
;
3508 case METHOD_SEMANTIC_GETTER
:
3509 properties
[i
- first
].get
= method
;
3518 info
= (MonoClassPropertyInfo
*)mono_class_alloc0 (klass
, sizeof (MonoClassPropertyInfo
));
3519 info
->first
= first
;
3520 info
->count
= count
;
3521 info
->properties
= properties
;
3522 mono_memory_barrier ();
3524 /* This might leak 'info' which was allocated from the image mempool */
3525 mono_class_set_property_info (klass
, info
);
3529 inflate_method_listz (MonoMethod
**methods
, MonoClass
*klass
, MonoGenericContext
*context
)
3531 MonoMethod
**om
, **retval
;
3534 for (om
= methods
, count
= 0; *om
; ++om
, ++count
)
3537 retval
= g_new0 (MonoMethod
*, count
+ 1);
3539 for (om
= methods
, count
= 0; *om
; ++om
, ++count
) {
3541 retval
[count
] = mono_class_inflate_generic_method_full_checked (*om
, klass
, context
, error
);
3542 g_assert (is_ok (error
)); /*FIXME proper error handling*/
3548 /*This method can fail the class.*/
3550 mono_class_setup_events (MonoClass
*klass
)
3553 guint startm
, endm
, i
, j
;
3554 guint32 cols
[MONO_EVENT_SIZE
];
3555 MonoTableInfo
*msemt
= &klass
->image
->tables
[MONO_TABLE_METHODSEMANTICS
];
3559 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
3563 if (mono_class_is_ginst (klass
)) {
3564 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
3565 MonoGenericContext
*context
= NULL
;
3567 mono_class_setup_events (gklass
);
3568 if (mono_class_set_type_load_failure_causedby_class (klass
, gklass
, "Generic type definition failed to load"))
3571 MonoClassEventInfo
*ginfo
= mono_class_get_event_info (gklass
);
3572 first
= ginfo
->first
;
3573 count
= ginfo
->count
;
3575 events
= mono_class_new0 (klass
, MonoEvent
, count
);
3578 context
= mono_class_get_context (klass
);
3580 for (i
= 0; i
< count
; i
++) {
3582 MonoEvent
*event
= &events
[i
];
3583 MonoEvent
*gevent
= &ginfo
->events
[i
];
3585 event
->parent
= klass
;
3586 event
->name
= gevent
->name
;
3587 event
->add
= gevent
->add
? mono_class_inflate_generic_method_full_checked (gevent
->add
, klass
, context
, error
) : NULL
;
3588 g_assert (is_ok (error
)); /*FIXME proper error handling*/
3589 event
->remove
= gevent
->remove
? mono_class_inflate_generic_method_full_checked (gevent
->remove
, klass
, context
, error
) : NULL
;
3590 g_assert (is_ok (error
)); /*FIXME proper error handling*/
3591 event
->raise
= gevent
->raise
? mono_class_inflate_generic_method_full_checked (gevent
->raise
, klass
, context
, error
) : NULL
;
3592 g_assert (is_ok (error
)); /*FIXME proper error handling*/
3594 #ifndef MONO_SMALL_CONFIG
3595 event
->other
= gevent
->other
? inflate_method_listz (gevent
->other
, klass
, context
) : NULL
;
3597 event
->attrs
= gevent
->attrs
;
3600 first
= mono_metadata_events_from_typedef (klass
->image
, mono_metadata_token_index (klass
->type_token
) - 1, &last
);
3601 count
= last
- first
;
3604 mono_class_setup_methods (klass
);
3605 if (mono_class_has_failure (klass
)) {
3610 events
= (MonoEvent
*)mono_class_alloc0 (klass
, sizeof (MonoEvent
) * count
);
3611 for (i
= first
; i
< last
; ++i
) {
3612 MonoEvent
*event
= &events
[i
- first
];
3614 mono_metadata_decode_table_row (klass
->image
, MONO_TABLE_EVENT
, i
, cols
, MONO_EVENT_SIZE
);
3615 event
->parent
= klass
;
3616 event
->attrs
= cols
[MONO_EVENT_FLAGS
];
3617 event
->name
= mono_metadata_string_heap (klass
->image
, cols
[MONO_EVENT_NAME
]);
3619 startm
= mono_metadata_methods_from_event (klass
->image
, i
, &endm
);
3620 int first_idx
= mono_class_get_first_method_idx (klass
);
3621 for (j
= startm
; j
< endm
; ++j
) {
3624 mono_metadata_decode_row (msemt
, j
, cols
, MONO_METHOD_SEMA_SIZE
);
3626 if (klass
->image
->uncompressed_metadata
) {
3628 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
3629 method
= mono_get_method_checked (klass
->image
, MONO_TOKEN_METHOD_DEF
| cols
[MONO_METHOD_SEMA_METHOD
], klass
, NULL
, error
);
3630 mono_error_cleanup (error
); /* FIXME don't swallow this error */
3632 method
= klass
->methods
[cols
[MONO_METHOD_SEMA_METHOD
] - 1 - first_idx
];
3635 switch (cols
[MONO_METHOD_SEMA_SEMANTICS
]) {
3636 case METHOD_SEMANTIC_ADD_ON
:
3637 event
->add
= method
;
3639 case METHOD_SEMANTIC_REMOVE_ON
:
3640 event
->remove
= method
;
3642 case METHOD_SEMANTIC_FIRE
:
3643 event
->raise
= method
;
3645 case METHOD_SEMANTIC_OTHER
: {
3646 #ifndef MONO_SMALL_CONFIG
3649 if (event
->other
== NULL
) {
3650 event
->other
= g_new0 (MonoMethod
*, 2);
3652 while (event
->other
[n
])
3654 event
->other
= (MonoMethod
**)g_realloc (event
->other
, (n
+ 2) * sizeof (MonoMethod
*));
3656 event
->other
[n
] = method
;
3657 /* NULL terminated */
3658 event
->other
[n
+ 1] = NULL
;
3669 info
= (MonoClassEventInfo
*)mono_class_alloc0 (klass
, sizeof (MonoClassEventInfo
));
3670 info
->events
= events
;
3671 info
->first
= first
;
3672 info
->count
= count
;
3674 mono_memory_barrier ();
3676 mono_class_set_event_info (klass
, info
);
3681 * mono_class_setup_interface_id:
3683 * Initializes MonoClass::interface_id if required.
3685 * LOCKING: Acquires the loader lock.
3688 mono_class_setup_interface_id (MonoClass
*klass
)
3690 g_assert (MONO_CLASS_IS_INTERFACE_INTERNAL (klass
));
3691 mono_loader_lock ();
3692 mono_class_setup_interface_id_nolock (klass
);
3693 mono_loader_unlock ();
3697 * mono_class_setup_interfaces:
3699 * Initialize klass->interfaces/interfaces_count.
3700 * LOCKING: Acquires the loader lock.
3701 * This function can fail the type.
3704 mono_class_setup_interfaces (MonoClass
*klass
, MonoError
*error
)
3706 int i
, interface_count
;
3707 MonoClass
**interfaces
;
3711 if (klass
->interfaces_inited
)
3714 if (klass
->rank
== 1 && m_class_get_byval_arg (klass
)->type
!= MONO_TYPE_ARRAY
) {
3717 /* IList and IReadOnlyList -> 2x if enum*/
3718 interface_count
= klass
->element_class
->enumtype
? 4 : 2;
3719 interfaces
= (MonoClass
**)mono_image_alloc0 (klass
->image
, sizeof (MonoClass
*) * interface_count
);
3721 args
[0] = m_class_get_byval_arg (m_class_get_element_class (klass
));
3722 interfaces
[0] = mono_class_bind_generic_parameters (
3723 mono_defaults
.generic_ilist_class
, 1, args
, FALSE
);
3724 interfaces
[1] = mono_class_bind_generic_parameters (
3725 mono_defaults
.generic_ireadonlylist_class
, 1, args
, FALSE
);
3726 if (klass
->element_class
->enumtype
) {
3727 args
[0] = mono_class_enum_basetype_internal (klass
->element_class
);
3728 interfaces
[2] = mono_class_bind_generic_parameters (
3729 mono_defaults
.generic_ilist_class
, 1, args
, FALSE
);
3730 interfaces
[3] = mono_class_bind_generic_parameters (
3731 mono_defaults
.generic_ireadonlylist_class
, 1, args
, FALSE
);
3733 } else if (mono_class_is_ginst (klass
)) {
3734 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
3736 mono_class_setup_interfaces (gklass
, error
);
3737 if (!is_ok (error
)) {
3738 mono_class_set_type_load_failure (klass
, "Could not setup the interfaces");
3742 interface_count
= gklass
->interface_count
;
3743 interfaces
= mono_class_new0 (klass
, MonoClass
*, interface_count
);
3744 for (i
= 0; i
< interface_count
; i
++) {
3745 interfaces
[i
] = mono_class_inflate_generic_class_checked (gklass
->interfaces
[i
], mono_generic_class_get_context (mono_class_get_generic_class (klass
)), error
);
3746 if (!is_ok (error
)) {
3747 mono_class_set_type_load_failure (klass
, "Could not setup the interfaces");
3752 interface_count
= 0;
3756 mono_loader_lock ();
3757 if (!klass
->interfaces_inited
) {
3758 klass
->interface_count
= interface_count
;
3759 klass
->interfaces
= interfaces
;
3761 mono_memory_barrier ();
3763 klass
->interfaces_inited
= TRUE
;
3765 mono_loader_unlock ();
3770 * mono_class_setup_has_finalizer:
3772 * Initialize klass->has_finalizer if it isn't already initialized.
3774 * LOCKING: Acquires the loader lock.
3777 mono_class_setup_has_finalizer (MonoClass
*klass
)
3779 gboolean has_finalize
= FALSE
;
3781 if (m_class_is_has_finalize_inited (klass
))
3784 /* Interfaces and valuetypes are not supposed to have finalizers */
3785 if (!(MONO_CLASS_IS_INTERFACE_INTERNAL (klass
) || m_class_is_valuetype (klass
))) {
3786 MonoMethod
*cmethod
= NULL
;
3788 if (m_class_get_rank (klass
) == 1 && m_class_get_byval_arg (klass
)->type
== MONO_TYPE_SZARRAY
) {
3789 } else if (mono_class_is_ginst (klass
)) {
3790 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
3792 has_finalize
= mono_class_has_finalizer (gklass
);
3793 } else if (m_class_get_parent (klass
) && m_class_has_finalize (m_class_get_parent (klass
))) {
3794 has_finalize
= TRUE
;
3796 if (m_class_get_parent (klass
)) {
3798 * Can't search in metadata for a method named Finalize, because that
3799 * ignores overrides.
3801 mono_class_setup_vtable (klass
);
3802 if (mono_class_has_failure (klass
))
3805 cmethod
= m_class_get_vtable (klass
) [mono_class_get_object_finalize_slot ()];
3809 g_assert (m_class_get_vtable_size (klass
) > mono_class_get_object_finalize_slot ());
3811 if (m_class_get_parent (klass
)) {
3812 if (cmethod
->is_inflated
)
3813 cmethod
= ((MonoMethodInflated
*)cmethod
)->declaring
;
3814 if (cmethod
!= mono_class_get_default_finalize_method ())
3815 has_finalize
= TRUE
;
3821 mono_loader_lock ();
3822 if (!m_class_is_has_finalize_inited (klass
)) {
3823 klass
->has_finalize
= has_finalize
? 1 : 0;
3825 mono_memory_barrier ();
3826 klass
->has_finalize_inited
= TRUE
;
3828 mono_loader_unlock ();
3832 * mono_class_setup_supertypes:
3835 * Build the data structure needed to make fast type checks work.
3836 * This currently sets two fields in @class:
3837 * - idepth: distance between @class and System.Object in the type
3839 * - supertypes: array of classes: each element has a class in the hierarchy
3840 * starting from @class up to System.Object
3842 * LOCKING: Acquires the loader lock.
3845 mono_class_setup_supertypes (MonoClass
*klass
)
3848 MonoClass
**supertypes
;
3850 mono_atomic_load_acquire (supertypes
, MonoClass
**, &klass
->supertypes
);
3854 if (klass
->parent
&& !klass
->parent
->supertypes
)
3855 mono_class_setup_supertypes (klass
->parent
);
3857 idepth
= klass
->parent
->idepth
+ 1;
3861 ms
= MAX (MONO_DEFAULT_SUPERTABLE_SIZE
, idepth
);
3862 supertypes
= (MonoClass
**)mono_class_alloc0 (klass
, sizeof (MonoClass
*) * ms
);
3864 if (klass
->parent
) {
3865 CHECKED_METADATA_WRITE_PTR ( supertypes
[idepth
- 1] , klass
);
3868 for (supertype_idx
= 0; supertype_idx
< klass
->parent
->idepth
; supertype_idx
++)
3869 CHECKED_METADATA_WRITE_PTR ( supertypes
[supertype_idx
] , klass
->parent
->supertypes
[supertype_idx
] );
3871 CHECKED_METADATA_WRITE_PTR ( supertypes
[0] , klass
);
3874 mono_memory_barrier ();
3876 mono_loader_lock ();
3877 klass
->idepth
= idepth
;
3878 /* Needed so idepth is visible before supertypes is set */
3879 mono_memory_barrier ();
3880 klass
->supertypes
= supertypes
;
3881 mono_loader_unlock ();
3884 /* mono_class_setup_nested_types:
3886 * Initialize the nested_classes property for the given MonoClass if it hasn't already been initialized.
3888 * LOCKING: Acquires the loader lock.
3891 mono_class_setup_nested_types (MonoClass
*klass
)
3894 GList
*classes
, *nested_classes
, *l
;
3897 if (klass
->nested_classes_inited
)
3900 if (!klass
->type_token
) {
3901 mono_loader_lock ();
3902 klass
->nested_classes_inited
= TRUE
;
3903 mono_loader_unlock ();
3907 i
= mono_metadata_nesting_typedef (klass
->image
, klass
->type_token
, 1);
3911 guint32 cols
[MONO_NESTED_CLASS_SIZE
];
3912 mono_metadata_decode_row (&klass
->image
->tables
[MONO_TABLE_NESTEDCLASS
], i
- 1, cols
, MONO_NESTED_CLASS_SIZE
);
3913 nclass
= mono_class_create_from_typedef (klass
->image
, MONO_TOKEN_TYPE_DEF
| cols
[MONO_NESTED_CLASS_NESTED
], error
);
3914 if (!is_ok (error
)) {
3915 /*FIXME don't swallow the error message*/
3916 mono_error_cleanup (error
);
3918 i
= mono_metadata_nesting_typedef (klass
->image
, klass
->type_token
, i
+ 1);
3922 classes
= g_list_prepend (classes
, nclass
);
3924 i
= mono_metadata_nesting_typedef (klass
->image
, klass
->type_token
, i
+ 1);
3927 nested_classes
= NULL
;
3928 for (l
= classes
; l
; l
= l
->next
)
3929 nested_classes
= mono_g_list_prepend_image (klass
->image
, nested_classes
, l
->data
);
3930 g_list_free (classes
);
3932 mono_loader_lock ();
3933 if (!klass
->nested_classes_inited
) {
3934 mono_class_set_nested_classes_property (klass
, nested_classes
);
3935 mono_memory_barrier ();
3936 klass
->nested_classes_inited
= TRUE
;
3938 mono_loader_unlock ();
3942 * mono_class_setup_runtime_info:
3943 * \param klass the class to setup
3944 * \param domain the domain of the \p vtable
3947 * Store \p vtable in \c klass->runtime_info.
3949 * Sets the following field in MonoClass:
3952 * LOCKING: domain lock and loaderlock must be held.
3955 mono_class_setup_runtime_info (MonoClass
*klass
, MonoDomain
*domain
, MonoVTable
*vtable
)
3957 MonoClassRuntimeInfo
*old_info
= m_class_get_runtime_info (klass
);
3958 if (old_info
&& old_info
->max_domain
>= domain
->domain_id
) {
3959 /* someone already created a large enough runtime info */
3960 old_info
->domain_vtables
[domain
->domain_id
] = vtable
;
3962 int new_size
= domain
->domain_id
;
3964 new_size
= MAX (new_size
, old_info
->max_domain
);
3966 /* make the new size a power of two */
3968 while (new_size
> i
)
3971 /* this is a bounded memory retention issue: may want to
3972 * handle it differently when we'll have a rcu-like system.
3974 MonoClassRuntimeInfo
*runtime_info
= (MonoClassRuntimeInfo
*)mono_image_alloc0 (m_class_get_image (klass
), MONO_SIZEOF_CLASS_RUNTIME_INFO
+ new_size
* sizeof (gpointer
));
3975 runtime_info
->max_domain
= new_size
- 1;
3976 /* copy the stuff from the older info */
3978 memcpy (runtime_info
->domain_vtables
, old_info
->domain_vtables
, (old_info
->max_domain
+ 1) * sizeof (gpointer
));
3980 runtime_info
->domain_vtables
[domain
->domain_id
] = vtable
;
3982 mono_memory_barrier ();
3983 klass
->runtime_info
= runtime_info
;
3988 * mono_class_create_array_fill_type:
3990 * Returns a \c MonoClass that is used by SGen to fill out nursery fragments before a collection.
3993 mono_class_create_array_fill_type (void)
3995 static MonoClass klass
;
3997 klass
.element_class
= mono_defaults
.int64_class
;
3999 klass
.instance_size
= MONO_SIZEOF_MONO_ARRAY
;
4000 klass
.sizes
.element_size
= 8;
4001 klass
.size_inited
= 1;
4002 klass
.name
= "array_filler_type";
4008 * mono_classes_init:
4010 * Initialize the resources used by this module.
4011 * Known racy counters: `class_gparam_count`, `classes_size` and `mono_inflated_methods_size`
4013 MONO_NO_SANITIZE_THREAD
4015 mono_classes_init (void)
4017 mono_os_mutex_init (&classes_mutex
);
4019 mono_native_tls_alloc (&setup_fields_tls_id
, NULL
);
4020 mono_native_tls_alloc (&init_pending_tls_id
, NULL
);
4022 mono_counters_register ("MonoClassDef count",
4023 MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &class_def_count
);
4024 mono_counters_register ("MonoClassGtd count",
4025 MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &class_gtd_count
);
4026 mono_counters_register ("MonoClassGenericInst count",
4027 MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &class_ginst_count
);
4028 mono_counters_register ("MonoClassGenericParam count",
4029 MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &class_gparam_count
);
4030 mono_counters_register ("MonoClassArray count",
4031 MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &class_array_count
);
4032 mono_counters_register ("MonoClassPointer count",
4033 MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &class_pointer_count
);
4034 mono_counters_register ("Inflated methods size",
4035 MONO_COUNTER_GENERICS
| MONO_COUNTER_INT
, &mono_inflated_methods_size
);
4036 mono_counters_register ("Inflated classes size",
4037 MONO_COUNTER_GENERICS
| MONO_COUNTER_INT
, &inflated_classes_size
);
4038 mono_counters_register ("MonoClass size",
4039 MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &classes_size
);
4043 * mono_classes_cleanup:
4045 * Free the resources used by this module.
4048 mono_classes_cleanup (void)
4050 mono_native_tls_free (setup_fields_tls_id
);
4051 mono_native_tls_free (init_pending_tls_id
);
4053 if (global_interface_bitset
)
4054 mono_bitset_free (global_interface_bitset
);
4055 global_interface_bitset
= NULL
;
4056 mono_os_mutex_destroy (&classes_mutex
);