2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include <mono/metadata/image.h>
21 #include <mono/metadata/image-internals.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/assembly-internals.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/profiler-private.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/metadata/security-core-clr.h>
38 #include <mono/metadata/attrdefs.h>
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/verify-internals.h>
41 #include <mono/metadata/mono-debug.h>
42 #include <mono/utils/mono-counters.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45 #include <mono/utils/mono-logger-internals.h>
46 #include <mono/utils/mono-memory-model.h>
47 #include <mono/utils/atomic.h>
48 #include <mono/utils/bsearch.h>
49 #include <mono/utils/checked-build.h>
53 gboolean mono_print_vtable = FALSE;
54 gboolean mono_align_small_structs = FALSE;
57 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
58 guint32 classes_size, class_ext_size;
60 /* Low level lock which protects data structures in this module */
61 static mono_mutex_t classes_mutex;
63 /* Function supplied by the runtime to find classes by name using information from the AOT file */
64 static MonoGetClassFromName get_class_from_name = NULL;
66 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
67 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
68 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
69 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
70 static int generic_array_methods (MonoClass *klass);
71 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
73 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
74 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
75 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
76 static guint32 mono_field_resolve_flags (MonoClassField *field);
77 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
78 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
80 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
81 static gpointer mono_class_get_exception_data (const MonoClass *klass);
85 We use gclass recording to allow recursive system f types to be referenced by a parent.
87 Given the following type hierarchy:
89 class TextBox : TextBoxBase<TextBox> {}
90 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
91 class TextInput<T> : Input<T> where T: TextInput<T> {}
94 The runtime tries to load TextBoxBase<>.
95 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
96 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
97 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
99 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
100 at this point, iow, both are registered in the type map and both and a NULL parent. This means
101 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
103 To fix that what we do is to record all generic instantes created while resolving the parent of
104 any generic type definition and, after resolved, correct the parent field if needed.
107 static int record_gclass_instantiation;
108 static GSList *gclass_recorded_list;
109 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
111 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
112 static MonoNativeTlsKey setup_fields_tls_id;
114 static MonoNativeTlsKey init_pending_tls_id;
119 mono_locks_os_acquire (&classes_mutex, ClassesLock);
123 classes_unlock (void)
125 mono_locks_os_release (&classes_mutex, ClassesLock);
129 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
132 enable_gclass_recording (void)
134 ++record_gclass_instantiation;
138 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
141 disable_gclass_recording (gclass_record_func func, void *user_data)
143 GSList **head = &gclass_recorded_list;
145 g_assert (record_gclass_instantiation > 0);
146 --record_gclass_instantiation;
149 GSList *node = *head;
150 if (func ((MonoClass*)node->data, user_data)) {
152 g_slist_free_1 (node);
158 /* We automatically discard all recorded gclasses when disabled. */
159 if (!record_gclass_instantiation && gclass_recorded_list) {
160 g_slist_free (gclass_recorded_list);
161 gclass_recorded_list = NULL;
166 * mono_class_from_typeref:
167 * @image: a MonoImage
168 * @type_token: a TypeRef token
170 * Creates the MonoClass* structure representing the type defined by
171 * the typeref token valid inside @image.
172 * Returns: The MonoClass* representing the typeref token, NULL ifcould
176 mono_class_from_typeref (MonoImage *image, guint32 type_token)
179 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
180 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
185 * mono_class_from_typeref_checked:
186 * @image: a MonoImage
187 * @type_token: a TypeRef token
188 * @error: error return code, if any.
190 * Creates the MonoClass* structure representing the type defined by
191 * the typeref token valid inside @image.
193 * Returns: The MonoClass* representing the typeref token, NULL if it could
194 * not be loaded with the @error value filled with the information about the
198 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
200 guint32 cols [MONO_TYPEREF_SIZE];
201 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
203 const char *name, *nspace;
204 MonoClass *res = NULL;
207 mono_error_init (error);
209 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
212 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
214 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
215 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
217 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
218 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
219 case MONO_RESOLUTION_SCOPE_MODULE:
221 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
222 This is not the observed behavior of existing implementations.
223 The defacto behavior is that it's just a typedef in disguise.
225 /* a typedef in disguise */
226 res = mono_class_from_name_checked (image, nspace, name, error);
229 case MONO_RESOLUTION_SCOPE_MODULEREF:
230 module = mono_image_load_module_checked (image, idx, error);
232 res = mono_class_from_name_checked (module, nspace, name, error);
235 case MONO_RESOLUTION_SCOPE_TYPEREF: {
236 MonoClass *enclosing;
239 if (idx == mono_metadata_token_index (type_token)) {
240 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
244 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
245 return_val_if_nok (error, NULL);
247 if (enclosing->nested_classes_inited && enclosing->ext) {
248 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
249 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
250 res = (MonoClass *)tmp->data;
251 if (strcmp (res->name, name) == 0)
255 /* Don't call mono_class_init as we might've been called by it recursively */
256 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
258 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
259 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
260 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
262 if (strcmp (nname, name) == 0)
263 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
265 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
268 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
271 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
275 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
276 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
280 if (!image->references || !image->references [idx - 1])
281 mono_assembly_load_reference (image, idx - 1);
282 g_assert (image->references [idx - 1]);
284 /* If the assembly did not load, register this as a type load exception */
285 if (image->references [idx - 1] == REFERENCE_MISSING){
286 MonoAssemblyName aname;
289 mono_assembly_get_assemblyref (image, idx - 1, &aname);
290 human_name = mono_stringify_assembly_name (&aname);
291 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
295 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
298 /* Generic case, should be avoided for when a better error is possible. */
299 if (!res && mono_error_ok (error)) {
300 char *name = mono_class_name_from_token (image, type_token);
301 char *assembly = mono_assembly_name_from_token (image, type_token);
302 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
309 mono_image_memdup (MonoImage *image, void *data, guint size)
311 void *res = mono_image_alloc (image, size);
312 memcpy (res, data, size);
316 /* Copy everything mono_metadata_free_array free. */
318 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
321 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
323 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
325 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
327 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
329 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
331 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
336 /* Copy everything mono_metadata_free_method_signature free. */
338 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
342 sig = mono_metadata_signature_dup_full (image, sig);
344 sig->ret = mono_metadata_type_dup (image, sig->ret);
345 for (i = 0; i < sig->param_count; ++i)
346 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
352 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
354 MonoAssembly *ta = klass->image->assembly;
357 name = mono_stringify_assembly_name (&ta->aname);
358 g_string_append_printf (str, ", %s", name);
363 mono_type_name_check_byref (MonoType *type, GString *str)
366 g_string_append_c (str, '&');
370 * mono_identifier_escape_type_name_chars:
371 * @str: a destination string
372 * @identifier: an IDENTIFIER in internal form
376 * The displayed form of the identifier is appended to str.
378 * The displayed form of an identifier has the characters ,+&*[]\
379 * that have special meaning in type names escaped with a preceeding
380 * backslash (\) character.
383 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
389 // reserve space for common case: there will be no escaped characters.
390 g_string_set_size(str, n + strlen(identifier));
391 g_string_set_size(str, n);
393 for (const char* s = identifier; *s != 0 ; s++) {
402 g_string_append_c (str, '\\');
403 g_string_append_c (str, *s);
406 g_string_append_c (str, *s);
414 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
415 MonoTypeNameFormat format)
419 switch (type->type) {
420 case MONO_TYPE_ARRAY: {
421 int i, rank = type->data.array->rank;
422 MonoTypeNameFormat nested_format;
424 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
425 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
427 mono_type_get_name_recurse (
428 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
429 g_string_append_c (str, '[');
431 g_string_append_c (str, '*');
432 for (i = 1; i < rank; i++)
433 g_string_append_c (str, ',');
434 g_string_append_c (str, ']');
436 mono_type_name_check_byref (type, str);
438 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
439 _mono_type_get_assembly_name (type->data.array->eklass, str);
442 case MONO_TYPE_SZARRAY: {
443 MonoTypeNameFormat nested_format;
445 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
446 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
448 mono_type_get_name_recurse (
449 &type->data.klass->byval_arg, str, FALSE, nested_format);
450 g_string_append (str, "[]");
452 mono_type_name_check_byref (type, str);
454 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
455 _mono_type_get_assembly_name (type->data.klass, str);
458 case MONO_TYPE_PTR: {
459 MonoTypeNameFormat nested_format;
461 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
462 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
464 mono_type_get_name_recurse (
465 type->data.type, str, FALSE, nested_format);
466 g_string_append_c (str, '*');
468 mono_type_name_check_byref (type, str);
470 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
471 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
476 if (!mono_generic_param_info (type->data.generic_param))
477 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
479 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
481 mono_type_name_check_byref (type, str);
485 klass = mono_class_from_mono_type (type);
486 if (klass->nested_in) {
487 mono_type_get_name_recurse (
488 &klass->nested_in->byval_arg, str, TRUE, format);
489 if (format == MONO_TYPE_NAME_FORMAT_IL)
490 g_string_append_c (str, '.');
492 g_string_append_c (str, '+');
493 } else if (*klass->name_space) {
494 if (format == MONO_TYPE_NAME_FORMAT_IL)
495 g_string_append (str, klass->name_space);
497 mono_identifier_escape_type_name_chars (str, klass->name_space);
498 g_string_append_c (str, '.');
500 if (format == MONO_TYPE_NAME_FORMAT_IL) {
501 char *s = strchr (klass->name, '`');
502 int len = s ? s - klass->name : strlen (klass->name);
503 g_string_append_len (str, klass->name, len);
505 mono_identifier_escape_type_name_chars (str, klass->name);
509 if (mono_class_is_ginst (klass)) {
510 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
511 MonoGenericInst *inst = gclass->context.class_inst;
512 MonoTypeNameFormat nested_format;
515 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
516 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
518 if (format == MONO_TYPE_NAME_FORMAT_IL)
519 g_string_append_c (str, '<');
521 g_string_append_c (str, '[');
522 for (i = 0; i < inst->type_argc; i++) {
523 MonoType *t = inst->type_argv [i];
526 g_string_append_c (str, ',');
527 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
528 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
529 g_string_append_c (str, '[');
530 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
531 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
532 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
533 g_string_append_c (str, ']');
535 if (format == MONO_TYPE_NAME_FORMAT_IL)
536 g_string_append_c (str, '>');
538 g_string_append_c (str, ']');
539 } else if (klass->generic_container &&
540 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
541 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
544 if (format == MONO_TYPE_NAME_FORMAT_IL)
545 g_string_append_c (str, '<');
547 g_string_append_c (str, '[');
548 for (i = 0; i < klass->generic_container->type_argc; i++) {
550 g_string_append_c (str, ',');
551 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
553 if (format == MONO_TYPE_NAME_FORMAT_IL)
554 g_string_append_c (str, '>');
556 g_string_append_c (str, ']');
559 mono_type_name_check_byref (type, str);
561 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
562 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
563 _mono_type_get_assembly_name (klass, str);
569 * mono_type_get_name_full:
571 * @format: the format for the return string.
574 * Returns: The string representation in a number of formats:
576 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
577 * returned in the formatrequired by System.Reflection, this is the
578 * inverse of mono_reflection_parse_type ().
580 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
581 * be used by the IL assembler.
583 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
585 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
588 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
592 result = g_string_new ("");
594 mono_type_get_name_recurse (type, result, FALSE, format);
596 return g_string_free (result, FALSE);
600 * mono_type_get_full_name:
603 * Returns: The string representation for type as required by System.Reflection.
604 * The inverse of mono_reflection_parse_type ().
607 mono_type_get_full_name (MonoClass *klass)
609 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
613 * mono_type_get_name:
616 * Returns: The string representation for type as it would be represented in IL code.
619 mono_type_get_name (MonoType *type)
621 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
625 * mono_type_get_underlying_type:
628 * Returns: The MonoType for the underlying integer type if @type
629 * is an enum and byref is false, otherwise the type itself.
632 mono_type_get_underlying_type (MonoType *type)
634 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
635 return mono_class_enum_basetype (type->data.klass);
636 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
637 return mono_class_enum_basetype (type->data.generic_class->container_class);
642 * mono_class_is_open_constructed_type:
645 * Returns: TRUE if type represents a generics open constructed type.
646 * IOW, not all type parameters required for the instantiation have
647 * been provided or it's a generic type definition.
649 * An open constructed type means it's a non realizable type. Not to
650 * be mixed up with an abstract type - we can't cast or dispatch to
651 * an open type, for example.
654 mono_class_is_open_constructed_type (MonoType *t)
660 case MONO_TYPE_SZARRAY:
661 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
662 case MONO_TYPE_ARRAY:
663 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
665 return mono_class_is_open_constructed_type (t->data.type);
666 case MONO_TYPE_GENERICINST:
667 return t->data.generic_class->context.class_inst->is_open;
668 case MONO_TYPE_CLASS:
669 case MONO_TYPE_VALUETYPE:
670 return t->data.klass->generic_container != NULL;
677 This is a simple function to catch the most common bad instances of generic types.
678 Specially those that might lead to further failures in the runtime.
681 is_valid_generic_argument (MonoType *type)
683 switch (type->type) {
685 //case MONO_TYPE_TYPEDBYREF:
693 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
695 mono_error_init (error);
697 switch (type->type) {
698 case MONO_TYPE_MVAR: {
700 int num = mono_type_get_generic_param_num (type);
701 MonoGenericInst *inst = context->method_inst;
704 if (num >= inst->type_argc) {
705 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
706 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
707 num, info ? info->name : "", inst->type_argc);
711 if (!is_valid_generic_argument (inst->type_argv [num])) {
712 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
713 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
714 num, info ? info->name : "", inst->type_argv [num]->type);
718 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
719 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
720 * ->byref and ->attrs from @type are propagated to the returned type.
722 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
723 nt->byref = type->byref;
724 nt->attrs = type->attrs;
727 case MONO_TYPE_VAR: {
729 int num = mono_type_get_generic_param_num (type);
730 MonoGenericInst *inst = context->class_inst;
733 if (num >= inst->type_argc) {
734 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
735 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
736 num, info ? info->name : "", inst->type_argc);
739 if (!is_valid_generic_argument (inst->type_argv [num])) {
740 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
741 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
742 num, info ? info->name : "", inst->type_argv [num]->type);
745 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
746 nt->byref = type->byref;
747 nt->attrs = type->attrs;
750 case MONO_TYPE_SZARRAY: {
751 MonoClass *eclass = type->data.klass;
752 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
753 if (!inflated || !mono_error_ok (error))
755 nt = mono_metadata_type_dup (image, type);
756 nt->data.klass = mono_class_from_mono_type (inflated);
757 mono_metadata_free_type (inflated);
760 case MONO_TYPE_ARRAY: {
761 MonoClass *eclass = type->data.array->eklass;
762 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
763 if (!inflated || !mono_error_ok (error))
765 nt = mono_metadata_type_dup (image, type);
766 nt->data.array->eklass = mono_class_from_mono_type (inflated);
767 mono_metadata_free_type (inflated);
770 case MONO_TYPE_GENERICINST: {
771 MonoGenericClass *gclass = type->data.generic_class;
772 MonoGenericInst *inst;
774 if (!gclass->context.class_inst->is_open)
777 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
778 return_val_if_nok (error, NULL);
780 if (inst != gclass->context.class_inst)
781 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
783 if (gclass == type->data.generic_class)
786 nt = mono_metadata_type_dup (image, type);
787 nt->data.generic_class = gclass;
790 case MONO_TYPE_CLASS:
791 case MONO_TYPE_VALUETYPE: {
792 MonoClass *klass = type->data.klass;
793 MonoGenericContainer *container = klass->generic_container;
794 MonoGenericInst *inst;
795 MonoGenericClass *gclass = NULL;
801 /* We can't use context->class_inst directly, since it can have more elements */
802 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
803 return_val_if_nok (error, NULL);
805 if (inst == container->context.class_inst)
808 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
810 nt = mono_metadata_type_dup (image, type);
811 nt->type = MONO_TYPE_GENERICINST;
812 nt->data.generic_class = gclass;
822 mono_generic_class_get_context (MonoGenericClass *gclass)
824 return &gclass->context;
828 mono_class_get_context (MonoClass *klass)
830 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
831 return gklass ? mono_generic_class_get_context (gklass) : NULL;
835 * mono_class_get_generic_container:
837 * Return the generic container of KLASS which should be a generic type definition.
839 MonoGenericContainer*
840 mono_class_get_generic_container (MonoClass *klass)
842 g_assert (mono_class_is_gtd (klass));
844 return klass->generic_container;
848 * mono_class_inflate_generic_type_with_mempool:
849 * @mempool: a mempool
851 * @context: a generics context
852 * @error: error context
854 * The same as mono_class_inflate_generic_type, but allocates the MonoType
855 * from mempool if it is non-NULL. If it is NULL, the MonoType is
856 * allocated on the heap and is owned by the caller.
857 * The returned type can potentially be the same as TYPE, so it should not be
858 * modified by the caller, and it should be freed using mono_metadata_free_type ().
861 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
863 MonoType *inflated = NULL;
864 mono_error_init (error);
867 inflated = inflate_generic_type (image, type, context, error);
868 return_val_if_nok (error, NULL);
871 MonoType *shared = mono_metadata_get_shared_type (type);
876 return mono_metadata_type_dup (image, type);
880 mono_stats.inflated_type_count++;
885 * mono_class_inflate_generic_type:
887 * @context: a generics context
889 * If @type is a generic type and @context is not NULL, instantiate it using the
890 * generics context @context.
892 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
893 * on the heap and is owned by the caller. Returns NULL on error.
895 * @deprecated Please use mono_class_inflate_generic_type_checked instead
898 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
902 result = mono_class_inflate_generic_type_checked (type, context, &error);
903 mono_error_cleanup (&error);
908 * mono_class_inflate_generic_type:
910 * @context: a generics context
911 * @error: error context to use
913 * If @type is a generic type and @context is not NULL, instantiate it using the
914 * generics context @context.
916 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
917 * on the heap and is owned by the caller.
920 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
922 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
926 * mono_class_inflate_generic_type_no_copy:
928 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
932 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
934 MonoType *inflated = NULL;
936 mono_error_init (error);
938 inflated = inflate_generic_type (image, type, context, error);
939 return_val_if_nok (error, NULL);
945 mono_stats.inflated_type_count++;
950 * mono_class_inflate_generic_class:
952 * Inflate the class @gklass with @context. Set @error on failure.
955 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
960 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
961 return_val_if_nok (error, NULL);
963 res = mono_class_from_mono_type (inflated);
964 mono_metadata_free_type (inflated);
969 static MonoGenericContext
970 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
972 MonoGenericInst *class_inst = NULL;
973 MonoGenericInst *method_inst = NULL;
974 MonoGenericContext res = { NULL, NULL };
976 mono_error_init (error);
978 if (context->class_inst) {
979 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
980 if (!mono_error_ok (error))
984 if (context->method_inst) {
985 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
986 if (!mono_error_ok (error))
990 res.class_inst = class_inst;
991 res.method_inst = method_inst;
997 * mono_class_inflate_generic_method:
998 * @method: a generic method
999 * @context: a generics context
1001 * Instantiate the generic method @method using the generics context @context.
1003 * Returns: The new instantiated method
1006 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1008 return mono_class_inflate_generic_method_full (method, NULL, context);
1012 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1014 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1018 * mono_class_inflate_generic_method_full:
1020 * Instantiate method @method with the generic context @context.
1021 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1022 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1025 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1028 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1029 if (!mono_error_ok (&error))
1030 /*FIXME do proper error handling - on this case, kill this function. */
1031 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1037 * mono_class_inflate_generic_method_full_checked:
1038 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1041 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1044 MonoMethodInflated *iresult, *cached;
1045 MonoMethodSignature *sig;
1046 MonoGenericContext tmp_context;
1048 mono_error_init (error);
1050 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1051 while (method->is_inflated) {
1052 MonoGenericContext *method_context = mono_method_get_context (method);
1053 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1055 tmp_context = inflate_generic_context (method_context, context, error);
1056 return_val_if_nok (error, NULL);
1058 context = &tmp_context;
1060 if (mono_metadata_generic_context_equal (method_context, context))
1063 method = imethod->declaring;
1067 * A method only needs to be inflated if the context has argument for which it is
1070 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1071 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1074 if (!((method->is_generic && context->method_inst) ||
1075 (method->klass->generic_container && context->class_inst)))
1078 iresult = g_new0 (MonoMethodInflated, 1);
1079 iresult->context = *context;
1080 iresult->declaring = method;
1082 if (!context->method_inst && method->is_generic)
1083 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1085 if (!context->class_inst) {
1086 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1087 if (iresult->declaring->klass->generic_container)
1088 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1090 /* This can happen with some callers like mono_object_get_virtual_method () */
1091 if (!iresult->declaring->klass->generic_container && !mono_class_is_ginst (iresult->declaring->klass))
1092 iresult->context.class_inst = NULL;
1094 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1097 mono_image_set_lock (set);
1098 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1099 mono_image_set_unlock (set);
1103 return (MonoMethod*)cached;
1106 mono_stats.inflated_method_count++;
1108 inflated_methods_size += sizeof (MonoMethodInflated);
1110 sig = mono_method_signature (method);
1112 char *name = mono_type_get_full_name (method->klass);
1113 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1119 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1121 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1124 result = (MonoMethod *) iresult;
1125 result->is_inflated = TRUE;
1126 result->is_generic = FALSE;
1127 result->sre_method = FALSE;
1128 result->signature = NULL;
1130 if (method->wrapper_type) {
1131 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1132 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1133 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1135 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1136 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1139 if (iresult->context.method_inst) {
1140 /* Set the generic_container of the result to the generic_container of method */
1141 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1143 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1144 result->is_generic = 1;
1145 mono_method_set_generic_container (result, generic_container);
1150 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1151 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1155 if (method->klass->generic_container)
1156 result->klass = klass_hint;
1158 if (!result->klass) {
1159 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1160 if (!mono_error_ok (error))
1163 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1165 mono_metadata_free_type (inflated);
1169 * FIXME: This should hold, but it doesn't:
1171 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1172 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1173 * g_assert (result->is_generic);
1176 * Fixing this here causes other things to break, hence a very
1177 * ugly hack in mini-trampolines.c - see
1178 * is_generic_method_definition().
1182 mono_image_set_lock (set);
1183 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1185 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1186 iresult->owner = set;
1189 mono_image_set_unlock (set);
1191 return (MonoMethod*)cached;
1199 * mono_get_inflated_method:
1201 * Obsolete. We keep it around since it's mentioned in the public API.
1204 mono_get_inflated_method (MonoMethod *method)
1210 * mono_method_get_context_general:
1212 * @uninflated: handle uninflated methods?
1214 * Returns the generic context of a method or NULL if it doesn't have
1215 * one. For an inflated method that's the context stored in the
1216 * method. Otherwise it's in the method's generic container or in the
1217 * generic container of the method's class.
1220 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1222 if (method->is_inflated) {
1223 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1224 return &imethod->context;
1228 if (method->is_generic)
1229 return &(mono_method_get_generic_container (method)->context);
1230 if (method->klass->generic_container)
1231 return &method->klass->generic_container->context;
1236 * mono_method_get_context:
1239 * Returns the generic context for method if it's inflated, otherwise
1243 mono_method_get_context (MonoMethod *method)
1245 return mono_method_get_context_general (method, FALSE);
1249 * mono_method_get_generic_container:
1251 * Returns the generic container of METHOD, which should be a generic method definition.
1252 * Returns NULL if METHOD is not a generic method definition.
1253 * LOCKING: Acquires the loader lock.
1255 MonoGenericContainer*
1256 mono_method_get_generic_container (MonoMethod *method)
1258 MonoGenericContainer *container;
1260 if (!method->is_generic)
1263 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1264 g_assert (container);
1270 * mono_method_set_generic_container:
1272 * Sets the generic container of METHOD to CONTAINER.
1273 * LOCKING: Acquires the image lock.
1276 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1278 g_assert (method->is_generic);
1280 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1284 * mono_class_find_enum_basetype:
1285 * @class: The enum class
1287 * Determine the basetype of an enum by iterating through its fields. We do this
1288 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1291 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1293 MonoGenericContainer *container = NULL;
1294 MonoImage *m = klass->image;
1295 const int top = klass->field.count;
1298 g_assert (klass->enumtype);
1300 mono_error_init (error);
1302 if (klass->generic_container)
1303 container = klass->generic_container;
1304 else if (mono_class_is_ginst (klass)) {
1305 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1307 container = gklass->generic_container;
1308 g_assert (container);
1312 * Fetch all the field information.
1314 for (i = 0; i < top; i++){
1316 guint32 cols [MONO_FIELD_SIZE];
1317 int idx = klass->field.first + i;
1320 /* klass->field.first and idx points into the fieldptr table */
1321 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1323 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1326 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1327 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1331 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1332 mono_metadata_decode_value (sig, &sig);
1333 /* FIELD signature == 0x06 */
1335 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1339 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1343 if (mono_class_is_ginst (klass)) {
1344 //FIXME do we leak here?
1345 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1346 if (!mono_error_ok (error))
1348 ftype->attrs = cols [MONO_FIELD_FLAGS];
1353 mono_error_set_type_load_class (error, klass, "Could not find base type");
1360 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1363 mono_type_has_exceptions (MonoType *type)
1365 switch (type->type) {
1366 case MONO_TYPE_CLASS:
1367 case MONO_TYPE_VALUETYPE:
1368 case MONO_TYPE_SZARRAY:
1369 return mono_class_has_failure (type->data.klass);
1370 case MONO_TYPE_ARRAY:
1371 return mono_class_has_failure (type->data.array->eklass);
1372 case MONO_TYPE_GENERICINST:
1373 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1380 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1382 g_assert (mono_class_has_failure (klass));
1383 MonoErrorBoxed *box = (MonoErrorBoxed*)mono_class_get_exception_data (klass);
1384 mono_error_set_from_boxed (oerror, box);
1391 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1395 mono_class_alloc (MonoClass *klass, int size)
1397 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1399 return mono_image_set_alloc (gklass->owner, size);
1401 return mono_image_alloc (klass->image, size);
1405 mono_class_alloc0 (MonoClass *klass, int size)
1409 res = mono_class_alloc (klass, size);
1410 memset (res, 0, size);
1414 #define mono_class_new0(klass,struct_type, n_structs) \
1415 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1418 * mono_class_setup_basic_field_info:
1419 * @class: The class to initialize
1421 * Initializes the following fields in MonoClass:
1422 * * klass->fields (only field->parent and field->name)
1423 * * klass->field.count
1424 * * klass->field.first
1425 * LOCKING: Acquires the loader lock
1428 mono_class_setup_basic_field_info (MonoClass *klass)
1430 MonoGenericClass *gklass;
1431 MonoClassField *field;
1432 MonoClassField *fields;
1440 gklass = mono_class_try_get_generic_class (klass);
1441 gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1442 image = klass->image;
1445 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1447 * This happens when a generic instance of an unfinished generic typebuilder
1448 * is used as an element type for creating an array type. We can't initialize
1449 * the fields of this class using the fields of gklass, since gklass is not
1450 * finished yet, fields could be added to it later.
1456 mono_class_setup_basic_field_info (gtd);
1458 mono_loader_lock ();
1459 klass->field.first = gtd->field.first;
1460 klass->field.count = gtd->field.count;
1461 mono_loader_unlock ();
1464 top = klass->field.count;
1466 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1469 * Fetch all the field information.
1471 for (i = 0; i < top; i++){
1472 field = &fields [i];
1473 field->parent = klass;
1476 field->name = mono_field_get_name (>d->fields [i]);
1478 int idx = klass->field.first + i;
1479 /* klass->field.first and idx points into the fieldptr table */
1480 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1481 /* The name is needed for fieldrefs */
1482 field->name = mono_metadata_string_heap (image, name_idx);
1486 mono_memory_barrier ();
1488 mono_loader_lock ();
1490 klass->fields = fields;
1491 mono_loader_unlock ();
1495 * mono_class_set_failure_causedby_class:
1496 * @klass: the class that is failing
1497 * @caused_by: the class that caused the failure
1498 * @msg: Why @klass is failing.
1500 * If @caused_by has a failure, sets a TypeLoadException failure on
1501 * @klass with message "@msg, due to: {@caused_by message}".
1503 * Returns: TRUE if a failiure was set, or FALSE if @caused_by doesn't have a failure.
1506 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1508 if (mono_class_has_failure (caused_by)) {
1509 MonoError cause_error;
1510 mono_error_init (&cause_error);
1511 mono_error_set_for_class_failure (&cause_error, caused_by);
1512 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1513 mono_error_cleanup (&cause_error);
1522 * mono_class_setup_fields:
1523 * @klass: The class to initialize
1525 * Initializes klass->fields, computes class layout and sizes.
1526 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1527 * Sets the following fields in @klass:
1528 * - all the fields initialized by mono_class_init_sizes ()
1529 * - element_class/cast_class (for enums)
1530 * - field->type/offset for all fields
1533 * LOCKING: Acquires the loader lock.
1536 mono_class_setup_fields (MonoClass *klass)
1539 MonoImage *m = klass->image;
1541 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1543 guint32 real_size = 0;
1544 guint32 packing_size = 0;
1546 gboolean explicit_size;
1547 MonoClassField *field;
1548 MonoGenericContainer *container = NULL;
1549 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1550 MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1552 if (klass->fields_inited)
1555 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1557 * This happens when a generic instance of an unfinished generic typebuilder
1558 * is used as an element type for creating an array type. We can't initialize
1559 * the fields of this class using the fields of gklass, since gklass is not
1560 * finished yet, fields could be added to it later.
1565 mono_class_setup_basic_field_info (klass);
1566 top = klass->field.count;
1568 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1570 mono_class_setup_fields (gtd);
1571 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1576 if (klass->parent) {
1577 /* For generic instances, klass->parent might not have been initialized */
1578 mono_class_init (klass->parent);
1579 mono_class_setup_fields (klass->parent);
1580 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1582 instance_size = klass->parent->instance_size;
1584 instance_size = sizeof (MonoObject);
1587 /* Get the real size */
1588 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1590 instance_size += real_size;
1593 * This function can recursively call itself.
1594 * Prevent infinite recursion by using a list in TLS.
1596 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1597 if (g_slist_find (init_list, klass))
1599 init_list = g_slist_prepend (init_list, klass);
1600 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1603 * Fetch all the field information.
1605 for (i = 0; i < top; i++) {
1606 int idx = klass->field.first + i;
1607 field = &klass->fields [i];
1610 mono_field_resolve_type (field, &error);
1611 if (!mono_error_ok (&error)) {
1612 /*mono_field_resolve_type already failed class*/
1613 mono_error_cleanup (&error);
1617 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1618 g_assert (field->type);
1621 if (mono_field_is_deleted (field))
1623 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1625 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1626 int offset = uoffset;
1628 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1629 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1632 if (offset < -1) { /*-1 is used to encode special static fields */
1633 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1636 if (klass->generic_container) {
1637 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1641 if (mono_type_has_exceptions (field->type)) {
1642 char *class_name = mono_type_get_full_name (klass);
1643 char *type_name = mono_type_full_name (field->type);
1645 mono_class_set_type_load_failure (klass, "");
1646 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1647 g_free (class_name);
1651 /* The def_value of fields is compute lazily during vtable creation */
1654 if (!mono_class_has_failure (klass))
1655 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1657 init_list = g_slist_remove (init_list, klass);
1658 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1662 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1665 klass->instance_size = cached_info->instance_size;
1666 klass->sizes.class_size = cached_info->class_size;
1667 klass->packing_size = cached_info->packing_size;
1668 klass->min_align = cached_info->min_align;
1669 klass->blittable = cached_info->blittable;
1670 klass->has_references = cached_info->has_references;
1671 klass->has_static_refs = cached_info->has_static_refs;
1672 klass->no_special_static_fields = cached_info->no_special_static_fields;
1675 if (!klass->size_inited)
1676 mono_class_setup_fields (klass);
1681 * mono_class_init_sizes:
1683 * Initializes the size related fields of @klass without loading all field data if possible.
1684 * Sets the following fields in @klass:
1686 * - sizes.class_size
1693 * Can fail the class.
1695 * LOCKING: Acquires the loader lock.
1698 mono_class_init_sizes (MonoClass *klass)
1700 MonoCachedClassInfo cached_info;
1701 gboolean has_cached_info;
1703 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1705 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1709 * mono_type_get_basic_type_from_generic:
1712 * Returns a closed type corresponding to the possibly open type
1716 mono_type_get_basic_type_from_generic (MonoType *type)
1718 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1719 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1720 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1721 return &mono_defaults.object_class->byval_arg;
1726 class_has_references (MonoClass *klass)
1728 mono_class_init_sizes (klass);
1731 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1732 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1735 return klass->has_references;
1739 type_has_references (MonoClass *klass, MonoType *ftype)
1741 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1743 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1744 MonoGenericParam *gparam = ftype->data.generic_param;
1746 if (gparam->gshared_constraint)
1747 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1753 * mono_class_layout_fields:
1755 * @base_instance_size: base instance size
1758 * This contains the common code for computing the layout of classes and sizes.
1759 * This should only be called from mono_class_setup_fields () and
1760 * typebuilder_setup_fields ().
1762 * LOCKING: Acquires the loader lock
1765 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1768 const int top = klass->field.count;
1769 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1770 guint32 pass, passes, real_size;
1771 gboolean gc_aware_layout = FALSE;
1772 gboolean has_static_fields = FALSE;
1773 gboolean has_references = FALSE;
1774 gboolean has_static_refs = FALSE;
1775 MonoClassField *field;
1777 int instance_size = base_instance_size;
1778 int class_size, min_align;
1782 * We want to avoid doing complicated work inside locks, so we compute all the required
1783 * information and write it to @klass inside a lock.
1785 if (klass->fields_inited)
1788 if ((packing_size & 0xffffff00) != 0) {
1789 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1793 if (klass->parent) {
1794 min_align = klass->parent->min_align;
1795 /* we use | since it may have been set already */
1796 has_references = klass->has_references | klass->parent->has_references;
1800 /* We can't really enable 16 bytes alignment until the GC supports it.
1801 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1802 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1803 Bug #506144 is an example of this issue.
1805 if (klass->simd_type)
1810 * When we do generic sharing we need to have layout
1811 * information for open generic classes (either with a generic
1812 * context containing type variables or with a generic
1813 * container), so we don't return in that case anymore.
1816 if (klass->enumtype) {
1817 for (i = 0; i < top; i++) {
1818 field = &klass->fields [i];
1819 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1820 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1825 if (!mono_class_enum_basetype (klass)) {
1826 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1832 * Enable GC aware auto layout: in this mode, reference
1833 * fields are grouped together inside objects, increasing collector
1835 * Requires that all classes whose layout is known to native code be annotated
1836 * with [StructLayout (LayoutKind.Sequential)]
1837 * Value types have gc_aware_layout disabled by default, as per
1838 * what the default is for other runtimes.
1840 /* corlib is missing [StructLayout] directives in many places */
1841 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1842 if (!klass->valuetype)
1843 gc_aware_layout = TRUE;
1846 /* Compute klass->blittable */
1849 blittable = klass->parent->blittable;
1850 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1852 for (i = 0; i < top; i++) {
1853 field = &klass->fields [i];
1855 if (mono_field_is_deleted (field))
1857 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1860 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1863 MonoClass *field_class = mono_class_from_mono_type (field->type);
1865 mono_class_setup_fields (field_class);
1866 if (mono_class_has_failure (field_class)) {
1867 MonoError field_error;
1868 mono_error_init (&field_error);
1869 mono_error_set_for_class_failure (&field_error, field_class);
1870 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1871 mono_error_cleanup (&field_error);
1875 if (!field_class || !field_class->blittable)
1879 if (klass->enumtype)
1880 blittable = klass->element_class->blittable;
1882 if (mono_class_has_failure (klass))
1884 if (klass == mono_defaults.string_class)
1887 /* Compute klass->has_references */
1889 * Process non-static fields first, since static fields might recursively
1890 * refer to the class itself.
1892 for (i = 0; i < top; i++) {
1895 field = &klass->fields [i];
1897 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1898 ftype = mono_type_get_underlying_type (field->type);
1899 ftype = mono_type_get_basic_type_from_generic (ftype);
1900 if (type_has_references (klass, ftype))
1901 has_references = TRUE;
1906 * Compute field layout and total size (not considering static fields)
1908 field_offsets = g_new0 (int, top);
1910 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1911 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1912 if (gc_aware_layout)
1917 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1920 if (klass->parent) {
1921 mono_class_setup_fields (klass->parent);
1922 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1924 real_size = klass->parent->instance_size;
1926 real_size = sizeof (MonoObject);
1929 for (pass = 0; pass < passes; ++pass) {
1930 for (i = 0; i < top; i++){
1935 field = &klass->fields [i];
1937 if (mono_field_is_deleted (field))
1939 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1942 ftype = mono_type_get_underlying_type (field->type);
1943 ftype = mono_type_get_basic_type_from_generic (ftype);
1944 if (gc_aware_layout) {
1945 if (type_has_references (klass, ftype)) {
1954 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1955 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1956 /* This field is a hack inserted by MCS to empty structures */
1960 size = mono_type_size (field->type, &align);
1962 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1963 align = packing_size ? MIN (packing_size, align): align;
1964 /* if the field has managed references, we need to force-align it
1967 if (type_has_references (klass, ftype))
1968 align = MAX (align, sizeof (gpointer));
1970 min_align = MAX (align, min_align);
1971 field_offsets [i] = real_size;
1973 field_offsets [i] += align - 1;
1974 field_offsets [i] &= ~(align - 1);
1976 /*TypeBuilders produce all sort of weird things*/
1977 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1978 real_size = field_offsets [i] + size;
1981 instance_size = MAX (real_size, instance_size);
1983 if (instance_size & (min_align - 1)) {
1984 instance_size += min_align - 1;
1985 instance_size &= ~(min_align - 1);
1989 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1993 for (i = 0; i < top; i++) {
1998 field = &klass->fields [i];
2001 * There must be info about all the fields in a type if it
2002 * uses explicit layout.
2004 if (mono_field_is_deleted (field))
2006 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2009 size = mono_type_size (field->type, &align);
2010 align = packing_size ? MIN (packing_size, align): align;
2011 min_align = MAX (align, min_align);
2014 /* Already set by typebuilder_setup_fields () */
2015 field_offsets [i] = field->offset + sizeof (MonoObject);
2017 int idx = klass->field.first + i;
2019 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2020 field_offsets [i] = offset + sizeof (MonoObject);
2022 ftype = mono_type_get_underlying_type (field->type);
2023 ftype = mono_type_get_basic_type_from_generic (ftype);
2024 if (type_has_references (klass, ftype)) {
2025 if (field_offsets [i] % sizeof (gpointer)) {
2026 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2033 real_size = MAX (real_size, size + field_offsets [i]);
2036 if (klass->has_references) {
2037 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2039 /* Check for overlapping reference and non-reference fields */
2040 for (i = 0; i < top; i++) {
2043 field = &klass->fields [i];
2045 if (mono_field_is_deleted (field))
2047 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2049 ftype = mono_type_get_underlying_type (field->type);
2050 if (MONO_TYPE_IS_REFERENCE (ftype))
2051 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2053 for (i = 0; i < top; i++) {
2054 field = &klass->fields [i];
2056 if (mono_field_is_deleted (field))
2058 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2061 // FIXME: Too much code does this
2063 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2064 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_offsets [i]);
2068 g_free (ref_bitmap);
2071 instance_size = MAX (real_size, instance_size);
2072 if (instance_size & (min_align - 1)) {
2073 instance_size += min_align - 1;
2074 instance_size &= ~(min_align - 1);
2080 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2082 * This leads to all kinds of problems with nested structs, so only
2083 * enable it when a MONO_DEBUG property is set.
2085 * For small structs, set min_align to at least the struct size to improve
2086 * performance, and since the JIT memset/memcpy code assumes this and generates
2087 * unaligned accesses otherwise. See #78990 for a testcase.
2089 if (mono_align_small_structs && top) {
2090 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2091 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2095 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2096 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2097 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2098 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2100 /* Publish the data */
2101 mono_loader_lock ();
2102 if (klass->instance_size && !klass->image->dynamic) {
2103 /* Might be already set using cached info */
2104 g_assert (klass->instance_size == instance_size);
2106 klass->instance_size = instance_size;
2108 klass->blittable = blittable;
2109 klass->has_references = has_references;
2110 klass->packing_size = packing_size;
2111 klass->min_align = min_align;
2112 for (i = 0; i < top; ++i) {
2113 field = &klass->fields [i];
2114 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2115 klass->fields [i].offset = field_offsets [i];
2118 mono_memory_barrier ();
2119 klass->size_inited = 1;
2120 mono_loader_unlock ();
2123 * Compute static field layout and size
2124 * Static fields can reference the class itself, so this has to be
2125 * done after instance_size etc. are initialized.
2128 for (i = 0; i < top; i++) {
2132 field = &klass->fields [i];
2134 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2136 if (mono_field_is_deleted (field))
2139 if (mono_type_has_exceptions (field->type)) {
2140 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2144 has_static_fields = TRUE;
2146 size = mono_type_size (field->type, &align);
2147 field_offsets [i] = class_size;
2148 /*align is always non-zero here*/
2149 field_offsets [i] += align - 1;
2150 field_offsets [i] &= ~(align - 1);
2151 class_size = field_offsets [i] + size;
2154 if (has_static_fields && class_size == 0)
2155 /* Simplify code which depends on class_size != 0 if the class has static fields */
2158 /* Compute klass->has_static_refs */
2159 has_static_refs = FALSE;
2160 for (i = 0; i < top; i++) {
2163 field = &klass->fields [i];
2165 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2166 ftype = mono_type_get_underlying_type (field->type);
2167 ftype = mono_type_get_basic_type_from_generic (ftype);
2168 if (type_has_references (klass, ftype))
2169 has_static_refs = TRUE;
2173 /*valuetypes can't be neither bigger than 1Mb or empty. */
2174 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2175 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2177 /* Publish the data */
2178 mono_loader_lock ();
2180 klass->sizes.class_size = class_size;
2181 klass->has_static_refs = has_static_refs;
2182 for (i = 0; i < top; ++i) {
2183 field = &klass->fields [i];
2185 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2186 field->offset = field_offsets [i];
2189 mono_memory_barrier ();
2190 klass->fields_inited = 1;
2191 mono_loader_unlock ();
2193 g_free (field_offsets);
2197 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2201 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2202 method->klass = klass;
2203 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2204 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2205 method->signature = sig;
2206 method->name = name;
2209 if (name [0] == '.') {
2210 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2212 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2218 * mono_class_setup_methods:
2221 * Initializes the 'methods' array in CLASS.
2222 * Calling this method should be avoided if possible since it allocates a lot
2223 * of long-living MonoMethod structures.
2224 * Methods belonging to an interface are assigned a sequential slot starting
2227 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2230 mono_class_setup_methods (MonoClass *klass)
2233 MonoMethod **methods;
2238 if (mono_class_is_ginst (klass)) {
2240 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2242 mono_class_init (gklass);
2243 if (!mono_class_has_failure (gklass))
2244 mono_class_setup_methods (gklass);
2245 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2248 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2249 count = gklass->method.count;
2250 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2252 for (i = 0; i < count; i++) {
2253 methods [i] = mono_class_inflate_generic_method_full_checked (
2254 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2255 if (!mono_error_ok (&error)) {
2256 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2257 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2260 mono_error_cleanup (&error);
2264 } else if (klass->rank) {
2266 MonoMethod *amethod;
2267 MonoMethodSignature *sig;
2268 int count_generic = 0, first_generic = 0;
2270 gboolean jagged_ctor = FALSE;
2272 count = 3 + (klass->rank > 1? 2: 1);
2274 mono_class_setup_interfaces (klass, &error);
2275 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2277 if (klass->rank == 1 && klass->element_class->rank) {
2279 klass->method.count ++;
2282 if (klass->interface_count) {
2283 count_generic = generic_array_methods (klass);
2284 first_generic = count;
2285 count += klass->interface_count * count_generic;
2288 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2290 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2291 sig->ret = &mono_defaults.void_class->byval_arg;
2292 sig->pinvoke = TRUE;
2293 sig->hasthis = TRUE;
2294 for (i = 0; i < klass->rank; ++i)
2295 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2297 amethod = create_array_method (klass, ".ctor", sig);
2298 methods [method_num++] = amethod;
2299 if (klass->rank > 1) {
2300 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2301 sig->ret = &mono_defaults.void_class->byval_arg;
2302 sig->pinvoke = TRUE;
2303 sig->hasthis = TRUE;
2304 for (i = 0; i < klass->rank * 2; ++i)
2305 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2307 amethod = create_array_method (klass, ".ctor", sig);
2308 methods [method_num++] = amethod;
2312 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2313 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2314 sig->ret = &mono_defaults.void_class->byval_arg;
2315 sig->pinvoke = TRUE;
2316 sig->hasthis = TRUE;
2317 for (i = 0; i < klass->rank + 1; ++i)
2318 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2319 amethod = create_array_method (klass, ".ctor", sig);
2320 methods [method_num++] = amethod;
2323 /* element Get (idx11, [idx2, ...]) */
2324 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2325 sig->ret = &klass->element_class->byval_arg;
2326 sig->pinvoke = TRUE;
2327 sig->hasthis = TRUE;
2328 for (i = 0; i < klass->rank; ++i)
2329 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2330 amethod = create_array_method (klass, "Get", sig);
2331 methods [method_num++] = amethod;
2332 /* element& Address (idx11, [idx2, ...]) */
2333 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2334 sig->ret = &klass->element_class->this_arg;
2335 sig->pinvoke = TRUE;
2336 sig->hasthis = TRUE;
2337 for (i = 0; i < klass->rank; ++i)
2338 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2339 amethod = create_array_method (klass, "Address", sig);
2340 methods [method_num++] = amethod;
2341 /* void Set (idx11, [idx2, ...], element) */
2342 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2343 sig->ret = &mono_defaults.void_class->byval_arg;
2344 sig->pinvoke = TRUE;
2345 sig->hasthis = TRUE;
2346 for (i = 0; i < klass->rank; ++i)
2347 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2348 sig->params [i] = &klass->element_class->byval_arg;
2349 amethod = create_array_method (klass, "Set", sig);
2350 methods [method_num++] = amethod;
2352 for (i = 0; i < klass->interface_count; i++)
2353 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2357 count = klass->method.count;
2358 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2359 for (i = 0; i < count; ++i) {
2360 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2361 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2363 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2364 mono_error_cleanup (&error);
2369 if (MONO_CLASS_IS_INTERFACE (klass)) {
2371 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2372 for (i = 0; i < count; ++i) {
2373 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2374 methods [i]->slot = slot++;
2378 mono_image_lock (klass->image);
2380 if (!klass->methods) {
2381 klass->method.count = count;
2383 /* Needed because of the double-checking locking pattern */
2384 mono_memory_barrier ();
2386 klass->methods = methods;
2389 mono_image_unlock (klass->image);
2393 * mono_class_get_method_by_index:
2395 * Returns klass->methods [index], initializing klass->methods if neccesary.
2397 * LOCKING: Acquires the loader lock.
2400 mono_class_get_method_by_index (MonoClass *klass, int index)
2404 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2405 /* Avoid calling setup_methods () if possible */
2406 if (gklass && !klass->methods) {
2409 m = mono_class_inflate_generic_method_full_checked (
2410 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2411 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2413 * If setup_methods () is called later for this class, no duplicates are created,
2414 * since inflate_generic_method guarantees that only one instance of a method
2415 * is created for each context.
2418 mono_class_setup_methods (klass);
2419 g_assert (m == klass->methods [index]);
2423 mono_class_setup_methods (klass);
2424 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2426 g_assert (index >= 0 && index < klass->method.count);
2427 return klass->methods [index];
2432 * mono_class_get_inflated_method:
2434 * Given an inflated class CLASS and a method METHOD which should be a method of
2435 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2438 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2440 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2443 g_assert (method->klass == gklass);
2445 mono_class_setup_methods (gklass);
2446 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2448 for (i = 0; i < gklass->method.count; ++i) {
2449 if (gklass->methods [i] == method) {
2450 if (klass->methods) {
2451 return klass->methods [i];
2454 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2455 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2465 * mono_class_get_vtable_entry:
2467 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2468 * LOCKING: Acquires the loader lock.
2471 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2475 if (klass->rank == 1) {
2477 * szarrays do not overwrite any methods of Array, so we can avoid
2478 * initializing their vtables in some cases.
2480 mono_class_setup_vtable (klass->parent);
2481 if (offset < klass->parent->vtable_size)
2482 return klass->parent->vtable [offset];
2485 if (mono_class_is_ginst (klass)) {
2487 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2488 mono_class_setup_vtable (gklass);
2489 m = gklass->vtable [offset];
2491 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2492 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2494 mono_class_setup_vtable (klass);
2495 if (mono_class_has_failure (klass))
2497 m = klass->vtable [offset];
2504 * mono_class_get_vtable_size:
2506 * Return the vtable size for KLASS.
2509 mono_class_get_vtable_size (MonoClass *klass)
2511 mono_class_setup_vtable (klass);
2513 return klass->vtable_size;
2517 * mono_class_setup_properties:
2519 * Initialize klass->ext.property and klass->ext.properties.
2521 * This method can fail the class.
2524 mono_class_setup_properties (MonoClass *klass)
2526 guint startm, endm, i, j;
2527 guint32 cols [MONO_PROPERTY_SIZE];
2528 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2529 MonoProperty *properties;
2533 if (klass->ext && klass->ext->properties)
2536 if (mono_class_is_ginst (klass)) {
2537 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2539 mono_class_init (gklass);
2540 mono_class_setup_properties (gklass);
2541 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2544 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2546 for (i = 0; i < gklass->ext->property.count; i++) {
2548 MonoProperty *prop = &properties [i];
2550 *prop = gklass->ext->properties [i];
2553 prop->get = mono_class_inflate_generic_method_full_checked (
2554 prop->get, klass, mono_class_get_context (klass), &error);
2556 prop->set = mono_class_inflate_generic_method_full_checked (
2557 prop->set, klass, mono_class_get_context (klass), &error);
2559 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2560 prop->parent = klass;
2563 first = gklass->ext->property.first;
2564 count = gklass->ext->property.count;
2566 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2567 count = last - first;
2570 mono_class_setup_methods (klass);
2571 if (mono_class_has_failure (klass))
2575 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2576 for (i = first; i < last; ++i) {
2577 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2578 properties [i - first].parent = klass;
2579 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2580 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2582 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2583 for (j = startm; j < endm; ++j) {
2586 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2588 if (klass->image->uncompressed_metadata) {
2590 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2591 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2592 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2594 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2597 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2598 case METHOD_SEMANTIC_SETTER:
2599 properties [i - first].set = method;
2601 case METHOD_SEMANTIC_GETTER:
2602 properties [i - first].get = method;
2611 mono_class_alloc_ext (klass);
2613 mono_image_lock (klass->image);
2615 if (klass->ext->properties) {
2616 /* We leak 'properties' which was allocated from the image mempool */
2617 mono_image_unlock (klass->image);
2621 klass->ext->property.first = first;
2622 klass->ext->property.count = count;
2624 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2625 mono_memory_barrier ();
2627 /* Leave this assignment as the last op in the function */
2628 klass->ext->properties = properties;
2630 mono_image_unlock (klass->image);
2634 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2636 MonoMethod **om, **retval;
2639 for (om = methods, count = 0; *om; ++om, ++count)
2642 retval = g_new0 (MonoMethod*, count + 1);
2644 for (om = methods, count = 0; *om; ++om, ++count) {
2646 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2647 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2653 /*This method can fail the class.*/
2655 mono_class_setup_events (MonoClass *klass)
2658 guint startm, endm, i, j;
2659 guint32 cols [MONO_EVENT_SIZE];
2660 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2664 if (klass->ext && klass->ext->events)
2667 if (mono_class_is_ginst (klass)) {
2668 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2669 MonoGenericContext *context = NULL;
2671 mono_class_setup_events (gklass);
2672 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2675 first = gklass->ext->event.first;
2676 count = gklass->ext->event.count;
2678 events = mono_class_new0 (klass, MonoEvent, count);
2681 context = mono_class_get_context (klass);
2683 for (i = 0; i < count; i++) {
2685 MonoEvent *event = &events [i];
2686 MonoEvent *gevent = &gklass->ext->events [i];
2688 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2690 event->parent = klass;
2691 event->name = gevent->name;
2692 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2693 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2694 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2695 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2696 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2697 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2699 #ifndef MONO_SMALL_CONFIG
2700 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2702 event->attrs = gevent->attrs;
2705 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2706 count = last - first;
2709 mono_class_setup_methods (klass);
2710 if (mono_class_has_failure (klass)) {
2715 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2716 for (i = first; i < last; ++i) {
2717 MonoEvent *event = &events [i - first];
2719 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2720 event->parent = klass;
2721 event->attrs = cols [MONO_EVENT_FLAGS];
2722 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2724 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2725 for (j = startm; j < endm; ++j) {
2728 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2730 if (klass->image->uncompressed_metadata) {
2732 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2733 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2734 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2736 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2739 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2740 case METHOD_SEMANTIC_ADD_ON:
2741 event->add = method;
2743 case METHOD_SEMANTIC_REMOVE_ON:
2744 event->remove = method;
2746 case METHOD_SEMANTIC_FIRE:
2747 event->raise = method;
2749 case METHOD_SEMANTIC_OTHER: {
2750 #ifndef MONO_SMALL_CONFIG
2753 if (event->other == NULL) {
2754 event->other = g_new0 (MonoMethod*, 2);
2756 while (event->other [n])
2758 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2760 event->other [n] = method;
2761 /* NULL terminated */
2762 event->other [n + 1] = NULL;
2773 mono_class_alloc_ext (klass);
2775 mono_image_lock (klass->image);
2777 if (klass->ext->events) {
2778 mono_image_unlock (klass->image);
2782 klass->ext->event.first = first;
2783 klass->ext->event.count = count;
2785 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2786 mono_memory_barrier ();
2788 /* Leave this assignment as the last op in the function */
2789 klass->ext->events = events;
2791 mono_image_unlock (klass->image);
2795 * Global pool of interface IDs, represented as a bitset.
2796 * LOCKING: Protected by the classes lock.
2798 static MonoBitSet *global_interface_bitset = NULL;
2801 * mono_unload_interface_ids:
2802 * @bitset: bit set of interface IDs
2804 * When an image is unloaded, the interface IDs associated with
2805 * the image are put back in the global pool of IDs so the numbers
2809 mono_unload_interface_ids (MonoBitSet *bitset)
2812 mono_bitset_sub (global_interface_bitset, bitset);
2817 mono_unload_interface_id (MonoClass *klass)
2819 if (global_interface_bitset && klass->interface_id) {
2821 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2827 * mono_get_unique_iid:
2830 * Assign a unique integer ID to the interface represented by @class.
2831 * The ID will positive and as small as possible.
2832 * LOCKING: Acquires the classes lock.
2833 * Returns: The new ID.
2836 mono_get_unique_iid (MonoClass *klass)
2840 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2844 if (!global_interface_bitset) {
2845 global_interface_bitset = mono_bitset_new (128, 0);
2848 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2850 int old_size = mono_bitset_size (global_interface_bitset);
2851 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2852 mono_bitset_free (global_interface_bitset);
2853 global_interface_bitset = new_set;
2856 mono_bitset_set (global_interface_bitset, iid);
2857 /* set the bit also in the per-image set */
2858 if (!mono_class_is_ginst (klass)) {
2859 if (klass->image->interface_bitset) {
2860 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2861 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2862 mono_bitset_free (klass->image->interface_bitset);
2863 klass->image->interface_bitset = new_set;
2866 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2868 mono_bitset_set (klass->image->interface_bitset, iid);
2873 #ifndef MONO_SMALL_CONFIG
2874 if (mono_print_vtable) {
2876 char *type_name = mono_type_full_name (&klass->byval_arg);
2877 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2878 if (gklass && !gklass->context.class_inst->is_open) {
2879 generic_id = gklass->context.class_inst->id;
2880 g_assert (generic_id != 0);
2884 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2889 g_assert (iid <= 65535);
2894 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2899 mono_class_setup_interfaces (klass, error);
2900 return_if_nok (error);
2902 for (i = 0; i < klass->interface_count; i++) {
2903 ic = klass->interfaces [i];
2906 *res = g_ptr_array_new ();
2907 g_ptr_array_add (*res, ic);
2908 mono_class_init (ic);
2909 if (mono_class_has_failure (ic)) {
2910 mono_error_set_type_load_class (error, ic, "Error Loading class");
2914 collect_implemented_interfaces_aux (ic, res, error);
2915 return_if_nok (error);
2920 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2922 GPtrArray *res = NULL;
2924 collect_implemented_interfaces_aux (klass, &res, error);
2925 if (!mono_error_ok (error)) {
2927 g_ptr_array_free (res, TRUE);
2934 compare_interface_ids (const void *p_key, const void *p_element) {
2935 const MonoClass *key = (const MonoClass *)p_key;
2936 const MonoClass *element = *(const MonoClass **)p_element;
2938 return (key->interface_id - element->interface_id);
2941 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2943 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2944 MonoClass **result = (MonoClass **)mono_binary_search (
2946 klass->interfaces_packed,
2947 klass->interface_offsets_count,
2948 sizeof (MonoClass *),
2949 compare_interface_ids);
2951 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2958 * mono_class_interface_offset_with_variance:
2960 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2961 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2963 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2965 * FIXME figure out MS disambiguation rules and fix this function.
2968 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2969 int i = mono_class_interface_offset (klass, itf);
2970 *non_exact_match = FALSE;
2974 if (!mono_class_has_variant_generic_params (itf))
2977 for (i = 0; i < klass->interface_offsets_count; i++) {
2978 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2979 *non_exact_match = TRUE;
2980 return klass->interface_offsets_packed [i];
2988 print_implemented_interfaces (MonoClass *klass) {
2991 GPtrArray *ifaces = NULL;
2993 int ancestor_level = 0;
2995 name = mono_type_get_full_name (klass);
2996 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2999 for (i = 0; i < klass->interface_offsets_count; i++)
3000 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3001 klass->interfaces_packed [i]->interface_id,
3002 klass->interface_offsets_packed [i],
3003 klass->interfaces_packed [i]->method.count,
3004 klass->interfaces_packed [i]->name_space,
3005 klass->interfaces_packed [i]->name );
3006 printf ("Interface flags: ");
3007 for (i = 0; i <= klass->max_interface_id; i++)
3008 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3009 printf ("(%d,T)", i);
3011 printf ("(%d,F)", i);
3013 printf ("Dump interface flags:");
3014 #ifdef COMPRESSED_INTERFACE_BITMAP
3016 const uint8_t* p = klass->interface_bitmap;
3017 i = klass->max_interface_id;
3019 printf (" %d x 00 %02X", p [0], p [1]);
3025 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3026 printf (" %02X", klass->interface_bitmap [i]);
3029 while (klass != NULL) {
3030 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3031 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3032 if (!mono_error_ok (&error)) {
3033 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3034 mono_error_cleanup (&error);
3035 } else if (ifaces) {
3036 for (i = 0; i < ifaces->len; i++) {
3037 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3038 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3039 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3041 mono_class_interface_offset (klass, ic),
3046 g_ptr_array_free (ifaces, TRUE);
3049 klass = klass->parent;
3054 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3057 args [0] = &arg0->byval_arg;
3059 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3063 array_class_get_if_rank (MonoClass *klass, guint rank)
3065 return rank ? mono_array_class_get (klass, rank) : klass;
3069 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3071 valuetype_types [0] = eclass;
3072 if (eclass == mono_defaults.int16_class)
3073 valuetype_types [1] = mono_defaults.uint16_class;
3074 else if (eclass == mono_defaults.uint16_class)
3075 valuetype_types [1] = mono_defaults.int16_class;
3076 else if (eclass == mono_defaults.int32_class)
3077 valuetype_types [1] = mono_defaults.uint32_class;
3078 else if (eclass == mono_defaults.uint32_class)
3079 valuetype_types [1] = mono_defaults.int32_class;
3080 else if (eclass == mono_defaults.int64_class)
3081 valuetype_types [1] = mono_defaults.uint64_class;
3082 else if (eclass == mono_defaults.uint64_class)
3083 valuetype_types [1] = mono_defaults.int64_class;
3084 else if (eclass == mono_defaults.byte_class)
3085 valuetype_types [1] = mono_defaults.sbyte_class;
3086 else if (eclass == mono_defaults.sbyte_class)
3087 valuetype_types [1] = mono_defaults.byte_class;
3088 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3089 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3092 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3093 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3094 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3095 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3096 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3098 /* this won't be needed once bug #325495 is completely fixed
3099 * though we'll need something similar to know which interfaces to allow
3100 * in arrays when they'll be lazyly created
3102 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3103 * MS returns diferrent types based on which instance is called. For example:
3104 * object obj = new byte[10][];
3105 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3106 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3109 * Fixing this should kill quite some code, save some bits and improve compatibility.
3112 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3114 MonoClass *eclass = klass->element_class;
3115 MonoClass* generic_icollection_class;
3116 MonoClass* generic_ienumerable_class;
3117 MonoClass* generic_ienumerator_class;
3118 MonoClass* generic_ireadonlylist_class;
3119 MonoClass* generic_ireadonlycollection_class;
3120 MonoClass *valuetype_types[2] = { NULL, NULL };
3121 MonoClass **interfaces = NULL;
3122 int i, nifaces, interface_count, real_count, original_rank;
3124 gboolean internal_enumerator;
3125 gboolean eclass_is_valuetype;
3127 if (!mono_defaults.generic_ilist_class) {
3131 internal_enumerator = FALSE;
3132 eclass_is_valuetype = FALSE;
3133 original_rank = eclass->rank;
3134 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3135 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
3136 if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3138 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3140 eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
3141 original_rank = eclass->rank;
3143 eclass = eclass->element_class;
3144 internal_enumerator = TRUE;
3145 *is_enumerator = TRUE;
3153 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3154 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3156 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3158 generic_icollection_class = mono_class_get_generic_icollection_class ();
3159 generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
3160 generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
3161 generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
3162 generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
3164 mono_class_init (eclass);
3167 * Arrays in 2.0 need to implement a number of generic interfaces
3168 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3169 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3170 * We collect the types needed to build the
3171 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3172 * the generic interfaces needed to implement.
3174 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3175 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3177 if (eclass->valuetype) {
3178 nifaces = generic_ireadonlylist_class ? 5 : 3;
3179 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3181 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3182 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3183 if (internal_enumerator) {
3185 if (valuetype_types [1])
3189 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3190 interfaces [0] = valuetype_types [0];
3191 if (valuetype_types [1])
3192 interfaces [nifaces] = valuetype_types [1];
3194 eclass_is_valuetype = TRUE;
3197 int idepth = eclass->idepth;
3198 if (!internal_enumerator)
3200 nifaces = generic_ireadonlylist_class ? 2 : 3;
3202 // FIXME: This doesn't seem to work/required for generic params
3203 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3204 mono_class_setup_interface_offsets (eclass);
3206 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3207 /* we add object for interfaces and the supertypes for the other
3208 * types. The last of the supertypes is the element class itself which we
3209 * already created the explicit interfaces for (so we include it for IEnumerator
3210 * and exclude it for arrays).
3212 if (MONO_CLASS_IS_INTERFACE (eclass))
3215 interface_count += idepth;
3216 if (eclass->rank && eclass->element_class->valuetype) {
3217 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3218 if (valuetype_types [1])
3221 /* IList, ICollection, IEnumerable, IReadOnlyList */
3222 interface_count *= nifaces;
3223 real_count = interface_count;
3224 if (internal_enumerator) {
3225 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3226 if (valuetype_types [1])
3229 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3230 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3231 interfaces [0] = mono_defaults.object_class;
3235 for (i = 0; i < idepth; i++) {
3236 mono_class_init (eclass->supertypes [i]);
3237 interfaces [j] = eclass->supertypes [i];
3241 if (all_interfaces) {
3242 for (i = 0; i < eclass->interface_offsets_count; i++) {
3243 interfaces [j] = eclass->interfaces_packed [i];
3247 for (i = 0; i < eclass->interface_count; i++) {
3248 interfaces [j] = eclass->interfaces [i];
3252 if (valuetype_types [1]) {
3253 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3258 /* instantiate the generic interfaces */
3259 for (i = 0; i < interface_count; i += nifaces) {
3260 MonoClass *iface = interfaces [i];
3262 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3263 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3265 if (eclass->valuetype) {
3266 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3267 if (generic_ireadonlylist_class) {
3268 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3269 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3272 if (!generic_ireadonlylist_class)
3273 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3276 if (internal_enumerator) {
3278 /* instantiate IEnumerator<iface> */
3279 for (i = 0; i < interface_count; i++) {
3280 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3282 j = interface_count;
3283 if (!eclass_is_valuetype) {
3284 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3285 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3288 for (i = 0; i < eclass->idepth; i++) {
3289 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3293 for (i = 0; i < eclass->interface_offsets_count; i++) {
3294 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3298 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3300 if (valuetype_types [1])
3301 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3305 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3306 for (i = 0; i < real_count; ++i) {
3307 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3308 g_print ("%s implements %s\n", type_name, name);
3319 find_array_interface (MonoClass *klass, const char *name)
3322 for (i = 0; i < klass->interface_count; ++i) {
3323 if (strcmp (klass->interfaces [i]->name, name) == 0)
3330 * Return the number of virtual methods.
3331 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3332 * Return -1 on failure.
3333 * FIXME It would be nice if this information could be cached somewhere.
3336 count_virtual_methods (MonoClass *klass)
3340 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3342 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3343 mono_class_setup_methods (klass);
3344 if (mono_class_has_failure (klass))
3347 for (i = 0; i < klass->method.count; ++i) {
3348 flags = klass->methods [i]->flags;
3349 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3353 for (i = 0; i < klass->method.count; ++i) {
3354 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3356 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3364 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3372 m = (l + num_ifaces) / 2;
3373 if (interfaces_full [m] == ic)
3375 if (l == num_ifaces)
3377 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3386 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3388 int i = find_interface (num_ifaces, interfaces_full, ic);
3390 return interface_offsets_full [i];
3395 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3397 int i = find_interface (num_ifaces, interfaces_full, ic);
3401 interface_offsets_full [i] = offset;
3404 for (i = 0; i < num_ifaces; ++i) {
3405 if (interfaces_full [i]) {
3407 if (interfaces_full [i]->interface_id < ic->interface_id)
3410 while (end < num_ifaces && interfaces_full [end]) end++;
3411 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3412 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3414 interfaces_full [i] = ic;
3415 interface_offsets_full [i] = offset;
3421 #ifdef COMPRESSED_INTERFACE_BITMAP
3424 * Compressed interface bitmap design.
3426 * Interface bitmaps take a large amount of memory, because their size is
3427 * linear with the maximum interface id assigned in the process (each interface
3428 * is assigned a unique id as it is loaded). The number of interface classes
3429 * is high because of the many implicit interfaces implemented by arrays (we'll
3430 * need to lazy-load them in the future).
3431 * Most classes implement a very small number of interfaces, so the bitmap is
3432 * sparse. This bitmap needs to be checked by interface casts, so access to the
3433 * needed bit must be fast and doable with few jit instructions.
3435 * The current compression format is as follows:
3436 * *) it is a sequence of one or more two-byte elements
3437 * *) the first byte in the element is the count of empty bitmap bytes
3438 * at the current bitmap position
3439 * *) the second byte in the element is an actual bitmap byte at the current
3442 * As an example, the following compressed bitmap bytes:
3443 * 0x07 0x01 0x00 0x7
3444 * correspond to the following bitmap:
3445 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3447 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3448 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3449 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3453 * mono_compress_bitmap:
3454 * @dest: destination buffer
3455 * @bitmap: bitmap buffer
3456 * @size: size of @bitmap in bytes
3458 * This is a mono internal function.
3459 * The @bitmap data is compressed into a format that is small but
3460 * still searchable in few instructions by the JIT and runtime.
3461 * The compressed data is stored in the buffer pointed to by the
3462 * @dest array. Passing a #NULL value for @dest allows to just compute
3463 * the size of the buffer.
3464 * This compression algorithm assumes the bits set in the bitmap are
3465 * few and far between, like in interface bitmaps.
3466 * Returns: The size of the compressed bitmap in bytes.
3469 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3473 const uint8_t *end = bitmap + size;
3474 while (bitmap < end) {
3475 if (*bitmap || numz == 255) {
3499 * mono_class_interface_match:
3500 * @bitmap: a compressed bitmap buffer
3501 * @id: the index to check in the bitmap
3503 * This is a mono internal function.
3504 * Checks if a bit is set in a compressed interface bitmap. @id must
3505 * be already checked for being smaller than the maximum id encoded in the
3508 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3512 mono_class_interface_match (const uint8_t *bitmap, int id)
3515 id -= bitmap [0] * 8;
3519 return bitmap [1] & (1 << id);
3528 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3529 * LOCKING: Acquires the loader lock.
3532 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3536 int i, j, max_iid, num_ifaces;
3537 MonoClass **interfaces_full = NULL;
3538 int *interface_offsets_full = NULL;
3540 GPtrArray **ifaces_array = NULL;
3541 int interface_offsets_count;
3542 MonoClass **array_interfaces = NULL;
3543 int num_array_interfaces;
3544 int is_enumerator = FALSE;
3546 mono_class_setup_supertypes (klass);
3548 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3549 * implicit interfaces have the property that they are assigned the same slot in the
3550 * vtables for compatible interfaces
3552 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3554 /* compute maximum number of slots and maximum interface id */
3556 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3557 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3558 for (j = 0; j < klass->idepth; j++) {
3559 k = klass->supertypes [j];
3560 num_ifaces += k->interface_count;
3561 for (i = 0; i < k->interface_count; i++) {
3562 ic = k->interfaces [i];
3564 mono_class_init (ic);
3566 if (max_iid < ic->interface_id)
3567 max_iid = ic->interface_id;
3569 ifaces = mono_class_get_implemented_interfaces (k, &error);
3570 if (!mono_error_ok (&error)) {
3571 char *name = mono_type_get_full_name (k);
3572 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3574 mono_error_cleanup (&error);
3579 num_ifaces += ifaces->len;
3580 for (i = 0; i < ifaces->len; ++i) {
3581 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3582 if (max_iid < ic->interface_id)
3583 max_iid = ic->interface_id;
3585 ifaces_array [j] = ifaces;
3589 for (i = 0; i < num_array_interfaces; ++i) {
3590 ic = array_interfaces [i];
3591 mono_class_init (ic);
3592 if (max_iid < ic->interface_id)
3593 max_iid = ic->interface_id;
3596 if (MONO_CLASS_IS_INTERFACE (klass)) {
3598 if (max_iid < klass->interface_id)
3599 max_iid = klass->interface_id;
3602 /* compute vtable offset for interfaces */
3603 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3604 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3606 for (i = 0; i < num_ifaces; i++)
3607 interface_offsets_full [i] = -1;
3609 /* skip the current class */
3610 for (j = 0; j < klass->idepth - 1; j++) {
3611 k = klass->supertypes [j];
3612 ifaces = ifaces_array [j];
3615 for (i = 0; i < ifaces->len; ++i) {
3617 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3619 /*Force the sharing of interface offsets between parent and subtypes.*/
3620 io = mono_class_interface_offset (k, ic);
3622 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3627 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3628 ifaces = ifaces_array [klass->idepth - 1];
3630 for (i = 0; i < ifaces->len; ++i) {
3632 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3633 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3635 count = count_virtual_methods (ic);
3637 char *name = mono_type_get_full_name (ic);
3638 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3647 if (MONO_CLASS_IS_INTERFACE (klass))
3648 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3650 if (num_array_interfaces) {
3651 if (is_enumerator) {
3652 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3653 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3654 g_assert (ienumerator_offset >= 0);
3655 for (i = 0; i < num_array_interfaces; ++i) {
3656 ic = array_interfaces [i];
3657 if (strcmp (ic->name, "IEnumerator`1") == 0)
3658 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3660 g_assert_not_reached ();
3661 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, interface_offsets_full [ic->interface_id], klass->interfaces [0]->name);*/
3664 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3665 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3666 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3667 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3668 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3669 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3670 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3671 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3672 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3673 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3674 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3675 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3676 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3677 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3678 for (i = 0; i < num_array_interfaces; ++i) {
3680 ic = array_interfaces [i];
3681 if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
3682 offset = ilist_offset;
3683 else if (strcmp (ic->name, "ICollection`1") == 0)
3684 offset = icollection_offset;
3685 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3686 offset = ienumerable_offset;
3687 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3688 offset = ireadonlylist_offset;
3689 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3690 offset = ireadonlycollection_offset;
3692 g_assert_not_reached ();
3693 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3694 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3699 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3700 if (interface_offsets_full [i] != -1)
3701 interface_offsets_count ++;
3704 /* Publish the data */
3705 mono_loader_lock ();
3707 klass->max_interface_id = max_iid;
3709 * We might get called multiple times:
3710 * - mono_class_init ()
3711 * - mono_class_setup_vtable ().
3712 * - mono_class_setup_interface_offsets ().
3713 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3714 * means we have to overwrite those when called from other places (#4440).
3716 if (klass->interfaces_packed) {
3718 g_assert (klass->interface_offsets_count == interface_offsets_count);
3722 klass->interface_offsets_count = interface_offsets_count;
3723 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3724 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3725 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3726 #ifdef COMPRESSED_INTERFACE_BITMAP
3727 bitmap = g_malloc0 (bsize);
3729 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3731 for (i = 0; i < interface_offsets_count; i++) {
3732 int id = interfaces_full [i]->interface_id;
3733 bitmap [id >> 3] |= (1 << (id & 7));
3734 klass->interfaces_packed [i] = interfaces_full [i];
3735 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3736 /*if (num_array_interfaces)
3737 g_print ("type %s has %s offset at %d\n", mono_type_get_name_full (&klass->byval_arg, 0), mono_type_get_name_full (&interfaces_full [i]->byval_arg, 0), interface_offsets_full [i]);*/
3739 #ifdef COMPRESSED_INTERFACE_BITMAP
3740 i = mono_compress_bitmap (NULL, bitmap, bsize);
3741 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3742 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3745 klass->interface_bitmap = bitmap;
3748 mono_loader_unlock ();
3751 g_free (interfaces_full);
3752 g_free (interface_offsets_full);
3753 g_free (array_interfaces);
3754 for (i = 0; i < klass->idepth; i++) {
3755 ifaces = ifaces_array [i];
3757 g_ptr_array_free (ifaces, TRUE);
3759 g_free (ifaces_array);
3761 //printf ("JUST DONE: ");
3762 //print_implemented_interfaces (klass);
3768 * Setup interface offsets for interfaces.
3770 * - klass->max_interface_id
3771 * - klass->interface_offsets_count
3772 * - klass->interfaces_packed
3773 * - klass->interface_offsets_packed
3774 * - klass->interface_bitmap
3776 * This function can fail @class.
3779 mono_class_setup_interface_offsets (MonoClass *klass)
3781 setup_interface_offsets (klass, 0, FALSE);
3784 /*Checks if @klass has @parent as one of it's parents type gtd
3788 * Bar<T> : Foo<Bar<Bar<T>>>
3792 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3794 klass = mono_class_get_generic_type_definition (klass);
3795 parent = mono_class_get_generic_type_definition (parent);
3796 mono_class_setup_supertypes (klass);
3797 mono_class_setup_supertypes (parent);
3799 return klass->idepth >= parent->idepth &&
3800 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3804 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3806 MonoGenericInst *ginst;
3809 if (!mono_class_is_ginst (klass)) {
3810 mono_class_setup_vtable_full (klass, in_setup);
3811 return !mono_class_has_failure (klass);
3814 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3815 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3818 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3819 for (i = 0; i < ginst->type_argc; ++i) {
3821 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3823 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3824 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3825 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3827 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3828 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3836 * mono_class_setup_vtable:
3838 * Creates the generic vtable of CLASS.
3839 * Initializes the following fields in MonoClass:
3842 * Plus all the fields initialized by setup_interface_offsets ().
3843 * If there is an error during vtable construction, klass->has_failure
3844 * is set and details are stored in a MonoErrorBoxed.
3846 * LOCKING: Acquires the loader lock.
3849 mono_class_setup_vtable (MonoClass *klass)
3851 mono_class_setup_vtable_full (klass, NULL);
3855 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3858 MonoMethod **overrides;
3859 MonoGenericContext *context;
3867 if (MONO_CLASS_IS_INTERFACE (klass)) {
3868 /* This sets method->slot for all methods if this is an interface */
3869 mono_class_setup_methods (klass);
3873 if (mono_class_has_failure (klass))
3876 if (g_list_find (in_setup, klass))
3879 mono_loader_lock ();
3881 if (klass->vtable) {
3882 mono_loader_unlock ();
3886 mono_stats.generic_vtable_count ++;
3887 in_setup = g_list_prepend (in_setup, klass);
3889 if (mono_class_is_ginst (klass)) {
3890 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3891 mono_loader_unlock ();
3892 g_list_remove (in_setup, klass);
3896 context = mono_class_get_context (klass);
3897 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3899 context = (MonoGenericContext *) klass->generic_container;
3900 type_token = klass->type_token;
3903 if (image_is_dynamic (klass->image)) {
3904 /* Generic instances can have zero method overrides without causing any harm.
3905 * This is true since we don't do layout all over again for them, we simply inflate
3906 * the layout of the parent.
3908 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3909 if (!is_ok (&error)) {
3910 mono_loader_unlock ();
3911 g_list_remove (in_setup, klass);
3912 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3913 mono_error_cleanup (&error);
3917 /* The following call fails if there are missing methods in the type */
3918 /* FIXME it's probably a good idea to avoid this for generic instances. */
3919 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3923 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3925 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3929 mono_loader_unlock ();
3930 g_list_remove (in_setup, klass);
3935 #define DEBUG_INTERFACE_VTABLE_CODE 0
3936 #define TRACE_INTERFACE_VTABLE_CODE 0
3937 #define VERIFY_INTERFACE_VTABLE_CODE 0
3938 #define VTABLE_SELECTOR (1)
3940 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3941 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3942 if (!(VTABLE_SELECTOR)) break; \
3946 #define DEBUG_INTERFACE_VTABLE(stmt)
3949 #if TRACE_INTERFACE_VTABLE_CODE
3950 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3951 if (!(VTABLE_SELECTOR)) break; \
3955 #define TRACE_INTERFACE_VTABLE(stmt)
3958 #if VERIFY_INTERFACE_VTABLE_CODE
3959 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3960 if (!(VTABLE_SELECTOR)) break; \
3964 #define VERIFY_INTERFACE_VTABLE(stmt)
3968 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3970 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3974 GString *res = g_string_new ("");
3976 g_string_append_c (res, '(');
3977 for (i = 0; i < sig->param_count; ++i) {
3979 g_string_append_c (res, ',');
3980 mono_type_get_desc (res, sig->params [i], include_namespace);
3982 g_string_append (res, ")=>");
3983 if (sig->ret != NULL) {
3984 mono_type_get_desc (res, sig->ret, include_namespace);
3986 g_string_append (res, "NULL");
3989 g_string_free (res, FALSE);
3993 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3994 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3995 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3996 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
4004 is_wcf_hack_disabled (void)
4006 static gboolean disabled;
4007 static gboolean inited = FALSE;
4009 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4016 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4018 MonoMethodSignature *cmsig, *imsig;
4019 if (strcmp (im->name, cm->name) == 0) {
4020 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4021 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4024 if (! slot_is_empty) {
4025 if (require_newslot) {
4026 if (! interface_is_explicitly_implemented_by_class) {
4027 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4030 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4031 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4035 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4038 cmsig = mono_method_signature (cm);
4039 imsig = mono_method_signature (im);
4040 if (!cmsig || !imsig) {
4041 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4045 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4046 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4047 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4048 TRACE_INTERFACE_VTABLE (printf ("]"));
4051 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4052 if (mono_security_core_clr_enabled ())
4053 mono_security_core_clr_check_override (klass, cm, im);
4055 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4056 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4057 char *body_name = mono_method_full_name (cm, TRUE);
4058 char *decl_name = mono_method_full_name (im, TRUE);
4059 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4067 MonoClass *ic = im->klass;
4068 const char *ic_name_space = ic->name_space;
4069 const char *ic_name = ic->name;
4072 if (! require_newslot) {
4073 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4076 if (cm->klass->rank == 0) {
4077 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4080 cmsig = mono_method_signature (cm);
4081 imsig = mono_method_signature (im);
4082 if (!cmsig || !imsig) {
4083 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4087 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4088 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4089 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4090 TRACE_INTERFACE_VTABLE (printf ("]"));
4093 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4094 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4097 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4098 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4101 if ((ic_name == NULL) || ((strcmp (ic_name, "IEnumerable`1") != 0) && (strcmp (ic_name, "ICollection`1") != 0) && (strcmp (ic_name, "IList`1") != 0) && (strcmp (ic_name, "IReadOnlyList`1") != 0) && (strcmp (ic_name, "IReadOnlyCollection`1") != 0))) {
4102 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4106 subname = strstr (cm->name, ic_name_space);
4107 if (subname != cm->name) {
4108 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4111 subname += strlen (ic_name_space);
4112 if (subname [0] != '.') {
4113 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4117 if (strstr (subname, ic_name) != subname) {
4118 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4121 subname += strlen (ic_name);
4122 if (subname [0] != '.') {
4123 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4127 if (strcmp (subname, im->name) != 0) {
4128 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4132 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4133 if (mono_security_core_clr_enabled ())
4134 mono_security_core_clr_check_override (klass, cm, im);
4136 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4137 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4138 char *body_name = mono_method_full_name (cm, TRUE);
4139 char *decl_name = mono_method_full_name (im, TRUE);
4140 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4150 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4152 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4153 MonoMethod *method = key;
4154 MonoMethod *override = value;
4155 MonoClass *method_class = mono_method_get_class (method);
4156 MonoClass *override_class = mono_method_get_class (override);
4158 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4159 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4160 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4163 print_overrides (GHashTable *override_map, const char *message) {
4165 printf ("Override map \"%s\" START:\n", message);
4166 g_hash_table_foreach (override_map, foreach_override, NULL);
4167 printf ("Override map \"%s\" END.\n", message);
4169 printf ("Override map \"%s\" EMPTY.\n", message);
4173 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4174 char *full_name = mono_type_full_name (&klass->byval_arg);
4178 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4180 if (print_interfaces) {
4181 print_implemented_interfaces (klass);
4182 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4185 if (klass->parent) {
4186 parent_size = klass->parent->vtable_size;
4190 for (i = 0; i < size; ++i) {
4191 MonoMethod *cm = vtable [i];
4192 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4193 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4195 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4203 #if VERIFY_INTERFACE_VTABLE_CODE
4205 mono_method_try_get_vtable_index (MonoMethod *method)
4207 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4208 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4209 if (imethod->declaring->is_generic)
4210 return imethod->declaring->slot;
4212 return method->slot;
4216 mono_class_verify_vtable (MonoClass *klass)
4219 char *full_name = mono_type_full_name (&klass->byval_arg);
4221 printf ("*** Verifying VTable of class '%s' \n", full_name);
4225 if (!klass->methods)
4228 for (i = 0; i < klass->method.count; ++i) {
4229 MonoMethod *cm = klass->methods [i];
4232 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4236 full_name = mono_method_full_name (cm, TRUE);
4238 slot = mono_method_try_get_vtable_index (cm);
4240 if (slot >= klass->vtable_size) {
4241 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4245 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4246 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4247 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4248 g_free (other_name);
4251 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4258 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4260 char *method_signature;
4263 for (index = 0; index < onum; ++index) {
4264 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4265 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4267 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4268 type_name = mono_type_full_name (&klass->byval_arg);
4269 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4270 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4271 g_free (method_signature);
4273 mono_class_setup_methods (klass);
4274 if (mono_class_has_failure (klass)) {
4275 char *name = mono_type_get_full_name (klass);
4276 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4280 for (index = 0; index < klass->method.count; ++index) {
4281 MonoMethod *cm = klass->methods [index];
4282 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4284 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4285 g_free (method_signature);
4290 mono_method_get_method_definition (MonoMethod *method)
4292 while (method->is_inflated)
4293 method = ((MonoMethodInflated*)method)->declaring;
4298 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4302 for (i = 0; i < onum; ++i) {
4303 MonoMethod *decl = overrides [i * 2];
4304 MonoMethod *body = overrides [i * 2 + 1];
4306 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4307 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4311 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4312 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4313 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4315 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4319 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4320 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4321 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4323 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4327 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4328 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4332 body = mono_method_get_method_definition (body);
4333 decl = mono_method_get_method_definition (decl);
4335 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4336 char *body_name = mono_method_full_name (body, TRUE);
4337 char *decl_name = mono_method_full_name (decl, TRUE);
4338 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4348 mono_class_need_stelemref_method (MonoClass *klass)
4350 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4354 * LOCKING: this is supposed to be called with the loader lock held.
4357 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4361 MonoMethod **vtable;
4362 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4363 GPtrArray *ifaces = NULL;
4364 GHashTable *override_map = NULL;
4366 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4367 int first_non_interface_slot;
4369 GSList *virt_methods = NULL, *l;
4370 int stelemref_slot = 0;
4375 if (overrides && !verify_class_overrides (klass, overrides, onum))
4378 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4379 if (!mono_error_ok (&error)) {
4380 char *name = mono_type_get_full_name (klass);
4381 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4383 mono_error_cleanup (&error);
4385 } else if (ifaces) {
4386 for (i = 0; i < ifaces->len; i++) {
4387 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4388 max_vtsize += ic->method.count;
4390 g_ptr_array_free (ifaces, TRUE);
4394 if (klass->parent) {
4395 mono_class_init (klass->parent);
4396 mono_class_setup_vtable_full (klass->parent, in_setup);
4398 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4401 max_vtsize += klass->parent->vtable_size;
4402 cur_slot = klass->parent->vtable_size;
4405 max_vtsize += klass->method.count;
4407 /*Array have a slot for stelemref*/
4408 if (mono_class_need_stelemref_method (klass)) {
4409 stelemref_slot = cur_slot;
4414 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4415 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4417 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4419 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4420 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4423 max_iid = klass->max_interface_id;
4424 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4426 /* Optimized version for generic instances */
4427 if (mono_class_is_ginst (klass)) {
4429 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4432 mono_class_setup_vtable_full (gklass, in_setup);
4433 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4436 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4437 klass->vtable_size = gklass->vtable_size;
4438 for (i = 0; i < gklass->vtable_size; ++i)
4439 if (gklass->vtable [i]) {
4440 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4441 if (!mono_error_ok (&error)) {
4442 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4443 mono_error_cleanup (&error);
4447 tmp [i]->slot = gklass->vtable [i]->slot;
4449 mono_memory_barrier ();
4450 klass->vtable = tmp;
4452 /* Have to set method->slot for abstract virtual methods */
4453 if (klass->methods && gklass->methods) {
4454 for (i = 0; i < klass->method.count; ++i)
4455 if (klass->methods [i]->slot == -1)
4456 klass->methods [i]->slot = gklass->methods [i]->slot;
4462 if (klass->parent && klass->parent->vtable_size) {
4463 MonoClass *parent = klass->parent;
4466 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4468 // Also inherit parent interface vtables, just as a starting point.
4469 // This is needed otherwise bug-77127.exe fails when the property methods
4470 // have different names in the iterface and the class, because for child
4471 // classes the ".override" information is not used anymore.
4472 for (i = 0; i < parent->interface_offsets_count; i++) {
4473 MonoClass *parent_interface = parent->interfaces_packed [i];
4474 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4475 /*FIXME this is now dead code as this condition will never hold true.
4476 Since interface offsets are inherited then the offset of an interface implemented
4477 by a parent will never be the out of it's vtable boundary.
4479 if (interface_offset >= parent->vtable_size) {
4480 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4483 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4484 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4485 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4486 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4487 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4488 parent_interface_offset + j, parent_interface_offset, j,
4489 interface_offset + j, interface_offset, j));
4496 /*Array have a slot for stelemref*/
4497 if (mono_class_need_stelemref_method (klass)) {
4498 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4500 method->slot = stelemref_slot;
4502 g_assert (method->slot == stelemref_slot);
4504 vtable [stelemref_slot] = method;
4507 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4508 /* override interface methods */
4509 for (i = 0; i < onum; i++) {
4510 MonoMethod *decl = overrides [i*2];
4511 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4513 dslot = mono_method_get_vtable_slot (decl);
4515 mono_class_set_type_load_failure (klass, "");
4519 dslot += mono_class_interface_offset (klass, decl->klass);
4520 vtable [dslot] = overrides [i*2 + 1];
4521 vtable [dslot]->slot = dslot;
4523 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4525 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4527 if (mono_security_core_clr_enabled ())
4528 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4531 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4532 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4535 * Create a list of virtual methods to avoid calling
4536 * mono_class_get_virtual_methods () which is slow because of the metadata
4540 gpointer iter = NULL;
4543 virt_methods = NULL;
4544 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4545 virt_methods = g_slist_prepend (virt_methods, cm);
4547 if (mono_class_has_failure (klass))
4551 // Loop on all implemented interfaces...
4552 for (i = 0; i < klass->interface_offsets_count; i++) {
4553 MonoClass *parent = klass->parent;
4555 gboolean interface_is_explicitly_implemented_by_class;
4558 ic = klass->interfaces_packed [i];
4559 ic_offset = mono_class_interface_offset (klass, ic);
4561 mono_class_setup_methods (ic);
4562 if (mono_class_has_failure (ic))
4565 // Check if this interface is explicitly implemented (instead of just inherited)
4566 if (parent != NULL) {
4567 int implemented_interfaces_index;
4568 interface_is_explicitly_implemented_by_class = FALSE;
4569 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4570 if (ic == klass->interfaces [implemented_interfaces_index]) {
4571 interface_is_explicitly_implemented_by_class = TRUE;
4576 interface_is_explicitly_implemented_by_class = TRUE;
4579 // Loop on all interface methods...
4580 for (im_index = 0; im_index < ic->method.count; im_index++) {
4581 MonoMethod *im = ic->methods [im_index];
4582 int im_slot = ic_offset + im->slot;
4583 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4585 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4588 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4590 // If there is an explicit implementation, just use it right away,
4591 // otherwise look for a matching method
4592 if (override_im == NULL) {
4596 // First look for a suitable method among the class methods
4597 for (l = virt_methods; l; l = l->next) {
4598 cm = (MonoMethod *)l->data;
4599 TRACE_INTERFACE_VTABLE (printf (" For slot %d ('%s'.'%s':'%s'), trying method '%s'.'%s':'%s'... [EXPLICIT IMPLEMENTATION = %d][SLOT IS NULL = %d]", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL)));
4600 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4601 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4602 vtable [im_slot] = cm;
4603 /* Why do we need this? */
4608 TRACE_INTERFACE_VTABLE (printf ("\n"));
4609 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4613 // If the slot is still empty, look in all the inherited virtual methods...
4614 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4615 MonoClass *parent = klass->parent;
4616 // Reverse order, so that last added methods are preferred
4617 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4618 MonoMethod *cm = parent->vtable [cm_index];
4620 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf (" For slot %d ('%s'.'%s':'%s'), trying (ancestor) method '%s'.'%s':'%s'... ", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name));
4621 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4622 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4623 vtable [im_slot] = cm;
4624 /* Why do we need this? */
4630 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4632 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4636 g_assert (vtable [im_slot] == override_im);
4641 // If the class is not abstract, check that all its interface slots are full.
4642 // The check is done here and not directly at the end of the loop above because
4643 // it can happen (for injected generic array interfaces) that the same slot is
4644 // processed multiple times (those interfaces have overlapping slots), and it
4645 // will not always be the first pass the one that fills the slot.
4646 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4647 for (i = 0; i < klass->interface_offsets_count; i++) {
4651 ic = klass->interfaces_packed [i];
4652 ic_offset = mono_class_interface_offset (klass, ic);
4654 for (im_index = 0; im_index < ic->method.count; im_index++) {
4655 MonoMethod *im = ic->methods [im_index];
4656 int im_slot = ic_offset + im->slot;
4658 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4661 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4662 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4663 if (vtable [im_slot] == NULL) {
4664 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4671 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4672 for (l = virt_methods; l; l = l->next) {
4673 cm = (MonoMethod *)l->data;
4675 * If the method is REUSE_SLOT, we must check in the
4676 * base class for a method to override.
4678 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4680 for (k = klass->parent; k ; k = k->parent) {
4685 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4686 MonoMethodSignature *cmsig, *m1sig;
4688 cmsig = mono_method_signature (cm);
4689 m1sig = mono_method_signature (m1);
4691 if (!cmsig || !m1sig) {
4692 /* FIXME proper error message */
4693 mono_class_set_type_load_failure (klass, "");
4697 if (!strcmp(cm->name, m1->name) &&
4698 mono_metadata_signature_equal (cmsig, m1sig)) {
4700 if (mono_security_core_clr_enabled ())
4701 mono_security_core_clr_check_override (klass, cm, m1);
4703 slot = mono_method_get_vtable_slot (m1);
4707 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4708 char *body_name = mono_method_full_name (cm, TRUE);
4709 char *decl_name = mono_method_full_name (m1, TRUE);
4710 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4716 g_assert (cm->slot < max_vtsize);
4718 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4719 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4720 mono_method_full_name (m1, 1), m1,
4721 mono_method_full_name (cm, 1), cm));
4722 g_hash_table_insert (override_map, m1, cm);
4726 if (mono_class_has_failure (k))
4736 /*Non final newslot methods must be given a non-interface vtable slot*/
4737 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4741 cm->slot = cur_slot++;
4743 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4744 vtable [cm->slot] = cm;
4747 /* override non interface methods */
4748 for (i = 0; i < onum; i++) {
4749 MonoMethod *decl = overrides [i*2];
4750 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4751 g_assert (decl->slot != -1);
4752 vtable [decl->slot] = overrides [i*2 + 1];
4753 overrides [i * 2 + 1]->slot = decl->slot;
4755 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4756 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4757 mono_method_full_name (decl, 1), decl,
4758 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4759 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4761 if (mono_security_core_clr_enabled ())
4762 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4767 * If a method occupies more than one place in the vtable, and it is
4768 * overriden, then change the other occurances too.
4773 for (i = 0; i < max_vtsize; ++i)
4775 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4777 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4782 g_hash_table_destroy (override_map);
4783 override_map = NULL;
4786 g_slist_free (virt_methods);
4787 virt_methods = NULL;
4789 /* Ensure that all vtable slots are filled with concrete instance methods */
4790 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4791 for (i = 0; i < cur_slot; ++i) {
4792 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4793 char *type_name = mono_type_get_full_name (klass);
4794 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4795 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4797 g_free (method_name);
4803 if (mono_class_is_ginst (klass)) {
4804 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4806 mono_class_init (gklass);
4808 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4810 /* Check that the vtable_size value computed in mono_class_init () is correct */
4811 if (klass->vtable_size)
4812 g_assert (cur_slot == klass->vtable_size);
4813 klass->vtable_size = cur_slot;
4816 /* Try to share the vtable with our parent. */
4817 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4818 mono_memory_barrier ();
4819 klass->vtable = klass->parent->vtable;
4821 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4822 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4823 mono_memory_barrier ();
4824 klass->vtable = tmp;
4827 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4828 if (mono_print_vtable) {
4831 print_implemented_interfaces (klass);
4833 for (i = 0; i <= max_iid; i++)
4834 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4837 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4838 klass->vtable_size, icount);
4840 for (i = 0; i < cur_slot; ++i) {
4845 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4846 mono_method_full_name (cm, TRUE));
4852 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4853 klass->name, max_iid);
4855 for (i = 0; i < klass->interface_count; i++) {
4856 ic = klass->interfaces [i];
4857 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4858 mono_class_interface_offset (klass, ic),
4859 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4862 for (k = klass->parent; k ; k = k->parent) {
4863 for (i = 0; i < k->interface_count; i++) {
4864 ic = k->interfaces [i];
4865 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4866 mono_class_interface_offset (klass, ic),
4867 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4873 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4878 char *name = mono_type_get_full_name (klass);
4879 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4882 g_hash_table_destroy (override_map);
4884 g_slist_free (virt_methods);
4889 * mono_method_get_vtable_slot:
4891 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4892 * LOCKING: Acquires the loader lock.
4894 * FIXME Use proper MonoError machinery here.
4897 mono_method_get_vtable_slot (MonoMethod *method)
4899 if (method->slot == -1) {
4900 mono_class_setup_vtable (method->klass);
4901 if (mono_class_has_failure (method->klass))
4903 if (method->slot == -1) {
4907 if (!mono_class_is_ginst (method->klass)) {
4908 g_assert (method->is_inflated);
4909 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4912 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4913 g_assert (mono_class_is_ginst (method->klass));
4914 gklass = mono_class_get_generic_class (method->klass)->container_class;
4915 mono_class_setup_methods (method->klass);
4916 g_assert (method->klass->methods);
4917 for (i = 0; i < method->klass->method.count; ++i) {
4918 if (method->klass->methods [i] == method)
4921 g_assert (i < method->klass->method.count);
4922 g_assert (gklass->methods);
4923 method->slot = gklass->methods [i]->slot;
4925 g_assert (method->slot != -1);
4927 return method->slot;
4931 * mono_method_get_vtable_index:
4934 * Returns the index into the runtime vtable to access the method or,
4935 * in the case of a virtual generic method, the virtual generic method
4936 * thunk. Returns -1 on failure.
4938 * FIXME Use proper MonoError machinery here.
4941 mono_method_get_vtable_index (MonoMethod *method)
4943 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4944 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4945 if (imethod->declaring->is_generic)
4946 return mono_method_get_vtable_slot (imethod->declaring);
4948 return mono_method_get_vtable_slot (method);
4951 static MonoMethod *default_ghc = NULL;
4952 static MonoMethod *default_finalize = NULL;
4953 static int finalize_slot = -1;
4954 static int ghc_slot = -1;
4957 initialize_object_slots (MonoClass *klass)
4962 if (klass == mono_defaults.object_class) {
4963 mono_class_setup_vtable (klass);
4964 for (i = 0; i < klass->vtable_size; ++i) {
4965 MonoMethod *cm = klass->vtable [i];
4967 if (!strcmp (cm->name, "GetHashCode"))
4969 else if (!strcmp (cm->name, "Finalize"))
4973 g_assert (ghc_slot > 0);
4974 default_ghc = klass->vtable [ghc_slot];
4976 g_assert (finalize_slot > 0);
4977 default_finalize = klass->vtable [finalize_slot];
4982 MonoMethod *array_method;
4984 } GenericArrayMethodInfo;
4986 static int generic_array_method_num = 0;
4987 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4990 generic_array_methods (MonoClass *klass)
4992 int i, count_generic = 0;
4993 GList *list = NULL, *tmp;
4994 if (generic_array_method_num)
4995 return generic_array_method_num;
4996 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4997 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4998 for (i = 0; i < klass->parent->method.count; i++) {
4999 MonoMethod *m = klass->parent->methods [i];
5000 if (!strncmp (m->name, "InternalArray__", 15)) {
5002 list = g_list_prepend (list, m);
5005 list = g_list_reverse (list);
5006 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
5008 for (tmp = list; tmp; tmp = tmp->next) {
5009 const char *mname, *iname;
5011 MonoMethod *m = (MonoMethod *)tmp->data;
5012 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5013 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5015 generic_array_method_info [i].array_method = m;
5016 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5017 iname = "System.Collections.Generic.ICollection`1.";
5018 mname = m->name + 27;
5019 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5020 iname = "System.Collections.Generic.IEnumerable`1.";
5021 mname = m->name + 27;
5022 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5023 iname = "System.Collections.Generic.IReadOnlyList`1.";
5024 mname = m->name + strlen (ireadonlylist_prefix);
5025 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5026 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5027 mname = m->name + strlen (ireadonlycollection_prefix);
5028 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5029 iname = "System.Collections.Generic.IList`1.";
5030 mname = m->name + 15;
5032 g_assert_not_reached ();
5035 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5036 strcpy (name, iname);
5037 strcpy (name + strlen (iname), mname);
5038 generic_array_method_info [i].name = name;
5041 /*g_print ("array generic methods: %d\n", count_generic);*/
5043 generic_array_method_num = count_generic;
5045 return generic_array_method_num;
5049 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5051 MonoGenericContext tmp_context;
5054 tmp_context.class_inst = NULL;
5055 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
5056 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5058 for (i = 0; i < generic_array_method_num; i++) {
5060 MonoMethod *m = generic_array_method_info [i].array_method;
5061 MonoMethod *inflated;
5063 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5064 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5065 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5070 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5072 int null_length = strlen ("(null)");
5073 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5074 char *s = (char *)mono_image_alloc (image, len);
5077 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5078 g_assert (result == len - 1);
5085 * @klass: the class to initialize
5087 * Compute the instance_size, class_size and other infos that cannot be
5088 * computed at mono_class_get() time. Also compute vtable_size if possible.
5089 * Returns TRUE on success or FALSE if there was a problem in loading
5090 * the type (incorrect assemblies, missing assemblies, methods, etc).
5091 * Initializes the following fields in @klass:
5092 * - all the fields initialized by mono_class_init_sizes ()
5097 * LOCKING: Acquires the loader lock.
5100 mono_class_init (MonoClass *klass)
5102 int i, vtable_size = 0, array_method_count = 0;
5103 MonoCachedClassInfo cached_info;
5104 gboolean has_cached_info;
5105 gboolean locked = FALSE;
5106 gboolean ghcimpl = FALSE;
5107 gboolean has_cctor = FALSE;
5108 int first_iface_slot = 0;
5112 /* Double-checking locking pattern */
5113 if (klass->inited || mono_class_has_failure (klass))
5114 return !mono_class_has_failure (klass);
5116 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5119 * This function can recursively call itself.
5121 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
5122 if (g_slist_find (init_list, klass)) {
5123 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5126 init_list = g_slist_prepend (init_list, klass);
5127 mono_native_tls_set_value (init_pending_tls_id, init_list);
5130 * We want to avoid doing complicated work inside locks, so we compute all the required
5131 * information and write it to @klass inside a lock.
5134 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5135 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5139 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5140 MonoClass *element_class = klass->element_class;
5141 if (!element_class->inited)
5142 mono_class_init (element_class);
5143 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5147 mono_stats.initialized_class_count++;
5149 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5150 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5152 mono_class_init (gklass);
5153 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5156 mono_class_setup_interface_id (klass);
5159 if (klass->parent && !klass->parent->inited)
5160 mono_class_init (klass->parent);
5162 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5164 /* Compute instance size etc. */
5165 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
5166 if (mono_class_has_failure (klass))
5169 mono_class_setup_supertypes (klass);
5172 initialize_object_slots (klass);
5175 * Initialize the rest of the data without creating a generic vtable if possible.
5176 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5177 * also avoid computing a generic vtable.
5179 if (has_cached_info) {
5181 vtable_size = cached_info.vtable_size;
5182 ghcimpl = cached_info.ghcimpl;
5183 has_cctor = cached_info.has_cctor;
5184 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5185 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5186 * The first slot if for array with.
5188 static int szarray_vtable_size[2] = { 0 };
5190 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5193 if (!szarray_vtable_size [slot]) {
5194 mono_class_setup_vtable (klass);
5195 szarray_vtable_size [slot] = klass->vtable_size;
5196 vtable_size = klass->vtable_size;
5198 vtable_size = szarray_vtable_size[slot];
5200 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
5201 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5203 /* Generic instance case */
5204 ghcimpl = gklass->ghcimpl;
5205 has_cctor = gklass->has_cctor;
5207 mono_class_setup_vtable (gklass);
5208 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5211 vtable_size = gklass->vtable_size;
5215 /* ghcimpl is not currently used
5217 if (klass->parent) {
5218 MonoMethod *cmethod = klass->vtable [ghc_slot];
5219 if (cmethod->is_inflated)
5220 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5221 if (cmethod == default_ghc) {
5227 /* C# doesn't allow interfaces to have cctors */
5228 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5229 MonoMethod *cmethod = NULL;
5231 if (klass->type_token && !image_is_dynamic(klass->image)) {
5232 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5233 /* The find_method function ignores the 'flags' argument */
5234 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5237 mono_class_setup_methods (klass);
5238 if (mono_class_has_failure (klass))
5241 for (i = 0; i < klass->method.count; ++i) {
5242 MonoMethod *method = klass->methods [i];
5243 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5244 (strcmp (".cctor", method->name) == 0)) {
5254 array_method_count = 3 + (klass->rank > 1? 2: 1);
5256 if (klass->interface_count) {
5257 int count_generic = generic_array_methods (klass);
5258 array_method_count += klass->interface_count * count_generic;
5262 if (klass->parent) {
5263 if (!klass->parent->vtable_size)
5264 mono_class_setup_vtable (klass->parent);
5265 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5267 g_assert (klass->parent->vtable_size);
5268 first_iface_slot = klass->parent->vtable_size;
5269 if (mono_class_need_stelemref_method (klass))
5274 * Do the actual changes to @klass inside the loader lock
5276 mono_loader_lock ();
5279 if (klass->inited || mono_class_has_failure (klass)) {
5280 mono_loader_unlock ();
5281 /* Somebody might have gotten in before us */
5282 return !mono_class_has_failure (klass);
5285 mono_stats.initialized_class_count++;
5287 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5288 MonoClass *gklass = klass->generic_class->container_class;
5290 mono_stats.generic_class_count++;
5292 klass->method = gklass->method;
5293 klass->field = gklass->field;
5296 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5297 klass->nested_classes_inited = TRUE;
5298 klass->ghcimpl = ghcimpl;
5299 klass->has_cctor = has_cctor;
5301 klass->vtable_size = vtable_size;
5302 if (has_cached_info) {
5303 klass->has_finalize = cached_info.has_finalize;
5304 klass->has_finalize_inited = TRUE;
5307 klass->method.count = array_method_count;
5309 mono_loader_unlock ();
5312 setup_interface_offsets (klass, first_iface_slot, TRUE);
5314 if (mono_security_core_clr_enabled ())
5315 mono_security_core_clr_check_inheritance (klass);
5317 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5318 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5323 init_list = g_slist_remove (init_list, klass);
5324 mono_native_tls_set_value (init_pending_tls_id, init_list);
5326 /* Because of the double-checking locking pattern */
5327 mono_memory_barrier ();
5331 mono_loader_unlock ();
5333 return !mono_class_has_failure (klass);
5337 * mono_class_has_finalizer:
5339 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5343 mono_class_has_finalizer (MonoClass *klass)
5345 gboolean has_finalize = FALSE;
5347 if (klass->has_finalize_inited)
5348 return klass->has_finalize;
5350 /* Interfaces and valuetypes are not supposed to have finalizers */
5351 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5352 MonoMethod *cmethod = NULL;
5354 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5355 } else if (mono_class_is_ginst (klass)) {
5356 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5358 has_finalize = mono_class_has_finalizer (gklass);
5359 } else if (klass->parent && klass->parent->has_finalize) {
5360 has_finalize = TRUE;
5362 if (klass->parent) {
5364 * Can't search in metadata for a method named Finalize, because that
5365 * ignores overrides.
5367 mono_class_setup_vtable (klass);
5368 if (mono_class_has_failure (klass))
5371 cmethod = klass->vtable [finalize_slot];
5375 g_assert (klass->vtable_size > finalize_slot);
5377 if (klass->parent) {
5378 if (cmethod->is_inflated)
5379 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5380 if (cmethod != default_finalize)
5381 has_finalize = TRUE;
5387 mono_image_lock (klass->image);
5389 if (!klass->has_finalize_inited) {
5390 klass->has_finalize = has_finalize ? 1 : 0;
5392 mono_memory_barrier ();
5393 klass->has_finalize_inited = TRUE;
5396 mono_image_unlock (klass->image);
5398 return klass->has_finalize;
5402 mono_is_corlib_image (MonoImage *image)
5404 return image == mono_defaults.corlib;
5408 * LOCKING: this assumes the loader lock is held
5411 mono_class_setup_mono_type (MonoClass *klass)
5413 const char *name = klass->name;
5414 const char *nspace = klass->name_space;
5415 gboolean is_corlib = mono_is_corlib_image (klass->image);
5417 klass->this_arg.byref = 1;
5418 klass->this_arg.data.klass = klass;
5419 klass->this_arg.type = MONO_TYPE_CLASS;
5420 klass->byval_arg.data.klass = klass;
5421 klass->byval_arg.type = MONO_TYPE_CLASS;
5423 if (is_corlib && !strcmp (nspace, "System")) {
5424 if (!strcmp (name, "ValueType")) {
5426 * do not set the valuetype bit for System.ValueType.
5427 * klass->valuetype = 1;
5429 klass->blittable = TRUE;
5430 } else if (!strcmp (name, "Enum")) {
5432 * do not set the valuetype bit for System.Enum.
5433 * klass->valuetype = 1;
5435 klass->valuetype = 0;
5436 klass->enumtype = 0;
5437 } else if (!strcmp (name, "Object")) {
5438 klass->byval_arg.type = MONO_TYPE_OBJECT;
5439 klass->this_arg.type = MONO_TYPE_OBJECT;
5440 } else if (!strcmp (name, "String")) {
5441 klass->byval_arg.type = MONO_TYPE_STRING;
5442 klass->this_arg.type = MONO_TYPE_STRING;
5443 } else if (!strcmp (name, "TypedReference")) {
5444 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5445 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5449 if (klass->valuetype) {
5450 int t = MONO_TYPE_VALUETYPE;
5452 if (is_corlib && !strcmp (nspace, "System")) {
5455 if (!strcmp (name, "Boolean")) {
5456 t = MONO_TYPE_BOOLEAN;
5457 } else if (!strcmp(name, "Byte")) {
5459 klass->blittable = TRUE;
5463 if (!strcmp (name, "Char")) {
5468 if (!strcmp (name, "Double")) {
5470 klass->blittable = TRUE;
5474 if (!strcmp (name, "Int32")) {
5476 klass->blittable = TRUE;
5477 } else if (!strcmp(name, "Int16")) {
5479 klass->blittable = TRUE;
5480 } else if (!strcmp(name, "Int64")) {
5482 klass->blittable = TRUE;
5483 } else if (!strcmp(name, "IntPtr")) {
5485 klass->blittable = TRUE;
5489 if (!strcmp (name, "Single")) {
5491 klass->blittable = TRUE;
5492 } else if (!strcmp(name, "SByte")) {
5494 klass->blittable = TRUE;
5498 if (!strcmp (name, "UInt32")) {
5500 klass->blittable = TRUE;
5501 } else if (!strcmp(name, "UInt16")) {
5503 klass->blittable = TRUE;
5504 } else if (!strcmp(name, "UInt64")) {
5506 klass->blittable = TRUE;
5507 } else if (!strcmp(name, "UIntPtr")) {
5509 klass->blittable = TRUE;
5513 if (!strcmp (name, "TypedReference")) {
5514 t = MONO_TYPE_TYPEDBYREF;
5515 klass->blittable = TRUE;
5519 if (!strcmp (name, "Void")) {
5527 klass->byval_arg.type = (MonoTypeEnum)t;
5528 klass->this_arg.type = (MonoTypeEnum)t;
5531 if (MONO_CLASS_IS_INTERFACE (klass))
5532 klass->interface_id = mono_get_unique_iid (klass);
5537 * COM initialization is delayed until needed.
5538 * However when a [ComImport] attribute is present on a type it will trigger
5539 * the initialization. This is not a problem unless the BCL being executed
5540 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5543 init_com_from_comimport (MonoClass *klass)
5545 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5546 if (mono_security_core_clr_enabled ()) {
5547 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5548 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5549 /* but it can not be made available for application (i.e. user code) since all COM calls
5550 * are considered native calls. In this case we fail with a TypeLoadException (just like
5551 * Silverlight 2 does */
5552 mono_class_set_type_load_failure (klass, "");
5557 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5559 #endif /*DISABLE_COM*/
5562 * LOCKING: this assumes the loader lock is held
5565 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5567 gboolean system_namespace;
5568 gboolean is_corlib = mono_is_corlib_image (klass->image);
5570 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5572 /* if root of the hierarchy */
5573 if (system_namespace && !strcmp (klass->name, "Object")) {
5574 klass->parent = NULL;
5575 klass->instance_size = sizeof (MonoObject);
5578 if (!strcmp (klass->name, "<Module>")) {
5579 klass->parent = NULL;
5580 klass->instance_size = 0;
5584 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5585 /* Imported COM Objects always derive from __ComObject. */
5587 if (MONO_CLASS_IS_IMPORT (klass)) {
5588 init_com_from_comimport (klass);
5589 if (parent == mono_defaults.object_class)
5590 parent = mono_class_get_com_object_class ();
5594 /* set the parent to something useful and safe, but mark the type as broken */
5595 parent = mono_defaults.object_class;
5596 mono_class_set_type_load_failure (klass, "");
5600 klass->parent = parent;
5602 if (mono_class_is_ginst (parent) && !parent->name) {
5604 * If the parent is a generic instance, we may get
5605 * called before it is fully initialized, especially
5606 * before it has its name.
5611 #ifndef DISABLE_REMOTING
5612 klass->marshalbyref = parent->marshalbyref;
5613 klass->contextbound = parent->contextbound;
5616 klass->delegate = parent->delegate;
5618 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5619 mono_class_set_is_com_object (klass);
5621 if (system_namespace) {
5622 #ifndef DISABLE_REMOTING
5623 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5624 klass->marshalbyref = 1;
5626 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5627 klass->contextbound = 1;
5629 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5630 klass->delegate = 1;
5633 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5634 (strcmp (klass->parent->name_space, "System") == 0)))
5635 klass->valuetype = 1;
5636 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5637 klass->valuetype = klass->enumtype = 1;
5639 /*klass->enumtype = klass->parent->enumtype; */
5641 /* initialize com types if COM interfaces are present */
5643 if (MONO_CLASS_IS_IMPORT (klass))
5644 init_com_from_comimport (klass);
5646 klass->parent = NULL;
5652 * mono_class_setup_supertypes:
5655 * Build the data structure needed to make fast type checks work.
5656 * This currently sets two fields in @class:
5657 * - idepth: distance between @class and System.Object in the type
5659 * - supertypes: array of classes: each element has a class in the hierarchy
5660 * starting from @class up to System.Object
5662 * LOCKING: This function is atomic, in case of contention we waste memory.
5665 mono_class_setup_supertypes (MonoClass *klass)
5668 MonoClass **supertypes;
5670 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5674 if (klass->parent && !klass->parent->supertypes)
5675 mono_class_setup_supertypes (klass->parent);
5677 klass->idepth = klass->parent->idepth + 1;
5681 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5682 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5684 if (klass->parent) {
5685 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5688 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5689 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5691 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5694 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5698 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5700 MonoClass *gtd = (MonoClass*)user_data;
5701 /* Only try to fix generic instances of @gtd */
5702 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5705 /* Check if the generic instance has no parent. */
5706 if (gtd->parent && !gclass->parent)
5707 mono_generic_class_setup_parent (gclass, gtd);
5713 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5715 mono_class_set_type_load_failure (klass, "%s", msg);
5716 mono_error_set_type_load_class (error, klass, "%s", msg);
5720 * mono_class_create_from_typedef:
5721 * @image: image where the token is valid
5722 * @type_token: typedef token
5723 * @error: used to return any error found while creating the type
5725 * Create the MonoClass* representing the specified type token.
5726 * @type_token must be a TypeDef token.
5728 * FIXME: don't return NULL on failure, just the the caller figure it out.
5731 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5733 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5734 MonoClass *klass, *parent = NULL;
5735 guint32 cols [MONO_TYPEDEF_SIZE];
5736 guint32 cols_next [MONO_TYPEDEF_SIZE];
5737 guint tidx = mono_metadata_token_index (type_token);
5738 MonoGenericContext *context = NULL;
5739 const char *name, *nspace;
5741 MonoClass **interfaces;
5742 guint32 field_last, method_last;
5743 guint32 nesting_tokeen;
5745 mono_error_init (error);
5747 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5748 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5752 mono_loader_lock ();
5754 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5755 mono_loader_unlock ();
5759 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5761 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5762 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5764 if (mono_metadata_has_generic_params (image, type_token)) {
5765 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5766 klass->class_kind = MONO_CLASS_GTD;
5767 classes_size += sizeof (MonoClassGtd);
5769 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5770 klass->class_kind = MONO_CLASS_DEF;
5771 classes_size += sizeof (MonoClassDef);
5775 klass->name_space = nspace;
5777 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5779 klass->image = image;
5780 klass->type_token = type_token;
5781 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5783 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5786 * Check whether we're a generic type definition.
5788 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5789 if (klass->generic_container) {
5790 klass->generic_container->owner.klass = klass;
5791 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5792 context = &klass->generic_container->context;
5795 if (klass->generic_container)
5796 enable_gclass_recording ();
5798 if (cols [MONO_TYPEDEF_EXTENDS]) {
5800 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5802 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5803 /*WARNING: this must satisfy mono_metadata_type_hash*/
5804 klass->this_arg.byref = 1;
5805 klass->this_arg.data.klass = klass;
5806 klass->this_arg.type = MONO_TYPE_CLASS;
5807 klass->byval_arg.data.klass = klass;
5808 klass->byval_arg.type = MONO_TYPE_CLASS;
5810 parent = mono_class_get_checked (image, parent_token, error);
5811 if (parent && context) /* Always inflate */
5812 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5814 if (parent == NULL) {
5815 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5816 goto parent_failure;
5819 for (tmp = parent; tmp; tmp = tmp->parent) {
5821 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5822 goto parent_failure;
5824 if (klass->generic_container && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5825 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5826 goto parent_failure;
5831 mono_class_setup_parent (klass, parent);
5833 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5834 mono_class_setup_mono_type (klass);
5836 if (klass->generic_container)
5837 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5840 * This might access klass->byval_arg for recursion generated by generic constraints,
5841 * so it has to come after setup_mono_type ().
5843 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5844 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5845 if (!mono_error_ok (error)) {
5846 /*FIXME implement a mono_class_set_failure_from_mono_error */
5847 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5848 mono_loader_unlock ();
5849 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5854 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5858 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5862 klass->cast_class = klass->element_class = klass;
5864 if (!klass->enumtype) {
5865 if (!mono_metadata_interfaces_from_typedef_full (
5866 image, type_token, &interfaces, &icount, FALSE, context, error)){
5868 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5869 mono_loader_unlock ();
5870 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5874 klass->interfaces = interfaces;
5875 klass->interface_count = icount;
5876 klass->interfaces_inited = 1;
5879 /*g_print ("Load class %s\n", name);*/
5882 * Compute the field and method lists
5884 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5885 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5887 if (tt->rows > tidx){
5888 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5889 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5890 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5892 field_last = image->tables [MONO_TABLE_FIELD].rows;
5893 method_last = image->tables [MONO_TABLE_METHOD].rows;
5896 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5897 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5898 klass->field.count = field_last - klass->field.first;
5900 klass->field.count = 0;
5902 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5903 klass->method.count = method_last - klass->method.first;
5905 klass->method.count = 0;
5907 /* reserve space to store vector pointer in arrays */
5908 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5909 klass->instance_size += 2 * sizeof (gpointer);
5910 g_assert (klass->field.count == 0);
5913 if (klass->enumtype) {
5914 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5915 if (!enum_basetype) {
5916 /*set it to a default value as the whole runtime can't handle this to be null*/
5917 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5918 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5919 mono_loader_unlock ();
5920 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5923 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5927 * If we're a generic type definition, load the constraints.
5928 * We must do this after the class has been constructed to make certain recursive scenarios
5931 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5932 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5933 mono_loader_unlock ();
5934 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5938 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5939 if (!strncmp (name, "Vector", 6))
5940 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");
5943 mono_loader_unlock ();
5945 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5950 mono_class_setup_mono_type (klass);
5951 mono_loader_unlock ();
5952 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5956 /** Is klass a Nullable<T> ginst? */
5958 mono_class_is_nullable (MonoClass *klass)
5960 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5961 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5965 /** if klass is T? return T */
5967 mono_class_get_nullable_param (MonoClass *klass)
5969 g_assert (mono_class_is_nullable (klass));
5970 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5974 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5978 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5980 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5981 if (!mono_error_ok (&error)) {
5982 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5983 klass->parent = mono_defaults.object_class;
5984 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5985 mono_error_cleanup (&error);
5989 mono_class_setup_parent (klass, klass->parent);
5991 if (klass->enumtype) {
5992 klass->cast_class = gtd->cast_class;
5993 klass->element_class = gtd->element_class;
5999 * Create the `MonoClass' for an instantiation of a generic type.
6000 * We only do this if we actually need it.
6003 mono_generic_class_get_class (MonoGenericClass *gclass)
6005 MonoClass *klass, *gklass;
6007 if (gclass->cached_class)
6008 return gclass->cached_class;
6010 mono_loader_lock ();
6011 if (gclass->cached_class) {
6012 mono_loader_unlock ();
6013 return gclass->cached_class;
6016 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6018 gklass = gclass->container_class;
6020 if (record_gclass_instantiation > 0)
6021 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6023 if (gklass->nested_in) {
6024 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6025 klass->nested_in = gklass->nested_in;
6028 klass->name = gklass->name;
6029 klass->name_space = gklass->name_space;
6031 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6033 klass->image = gklass->image;
6034 klass->flags = gklass->flags;
6035 klass->type_token = gklass->type_token;
6036 klass->field.count = gklass->field.count;
6038 klass->class_kind = MONO_CLASS_GINST;
6040 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6042 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6043 klass->this_arg.type = klass->byval_arg.type;
6044 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6045 klass->this_arg.byref = TRUE;
6046 klass->enumtype = gklass->enumtype;
6047 klass->valuetype = gklass->valuetype;
6049 klass->cast_class = klass->element_class = klass;
6051 if (mono_class_is_nullable (klass))
6052 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6055 * We're not interested in the nested classes of a generic instance.
6056 * We use the generic type definition to look for nested classes.
6059 mono_generic_class_setup_parent (klass, gklass);
6061 if (gclass->is_dynamic) {
6063 * 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.
6064 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6065 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6067 if (!gklass->wastypebuilder)
6070 mono_class_setup_supertypes (klass);
6072 if (klass->enumtype) {
6074 * For enums, gklass->fields might not been set, but instance_size etc. is
6075 * already set in mono_reflection_create_internal_class (). For non-enums,
6076 * these will be computed normally in mono_class_layout_fields ().
6078 klass->instance_size = gklass->instance_size;
6079 klass->sizes.class_size = gklass->sizes.class_size;
6080 mono_memory_barrier ();
6081 klass->size_inited = 1;
6085 mono_memory_barrier ();
6086 gclass->cached_class = klass;
6088 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6090 inflated_classes ++;
6091 inflated_classes_size += sizeof (MonoClassGenericInst);
6093 mono_loader_unlock ();
6099 get_image_for_container (MonoGenericContainer *container)
6102 if (container->is_anonymous) {
6103 result = container->owner.image;
6106 if (container->is_method) {
6107 MonoMethod *method = container->owner.method;
6108 g_assert_checked (method);
6109 klass = method->klass;
6111 klass = container->owner.klass;
6113 g_assert_checked (klass);
6114 result = klass->image;
6121 get_image_for_generic_param (MonoGenericParam *param)
6123 MonoGenericContainer *container = mono_generic_param_owner (param);
6124 g_assert_checked (container);
6125 return get_image_for_container (container);
6128 // Make a string in the designated image consisting of a single integer.
6129 #define INT_STRING_SIZE 16
6131 make_generic_name_string (MonoImage *image, int num)
6133 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6134 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6138 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6139 // pinfo is derived from param by the caller for us.
6141 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6143 MonoClass *klass, **ptr;
6145 MonoGenericContainer *container = mono_generic_param_owner (param);
6146 g_assert_checked (container);
6148 MonoImage *image = get_image_for_container (container);
6149 gboolean is_mvar = container->is_method;
6150 gboolean is_anonymous = container->is_anonymous;
6152 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6153 klass->class_kind = MONO_CLASS_GPARAM;
6154 classes_size += sizeof (MonoClassGenericParam);
6157 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6159 int n = mono_generic_param_num (param);
6160 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6164 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6165 } else if (is_mvar) {
6166 MonoMethod *omethod = container->owner.method;
6167 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6169 MonoClass *oklass = container->owner.klass;
6170 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6173 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6175 // Count non-NULL items in pinfo->constraints
6178 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6182 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6183 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6185 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6186 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6188 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6191 if (count - pos > 0) {
6192 klass->interface_count = count - pos;
6193 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6194 klass->interfaces_inited = TRUE;
6195 for (i = pos; i < count; i++)
6196 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6199 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6201 klass->inited = TRUE;
6202 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6203 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6204 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6206 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6207 klass->this_arg.type = klass->byval_arg.type;
6208 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6209 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6210 klass->this_arg.byref = TRUE;
6212 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6213 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6215 /*Init these fields to sane values*/
6216 klass->min_align = 1;
6218 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6219 * constrained to, the JIT depends on this.
6221 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6222 mono_memory_barrier ();
6223 klass->size_inited = 1;
6225 mono_class_setup_supertypes (klass);
6227 if (count - pos > 0) {
6228 mono_class_setup_vtable (klass->parent);
6229 if (mono_class_has_failure (klass->parent))
6230 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6232 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6238 #define FAST_CACHE_SIZE 16
6241 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6242 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6243 * we cache the MonoClasses.
6244 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6245 * LOCKING: Takes the image lock depending on @take_lock.
6248 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6250 int n = mono_generic_param_num (param);
6251 MonoImage *image = get_image_for_generic_param (param);
6252 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6253 MonoClass *klass = NULL;
6258 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6259 // For high numbers or constraints we have to use pointer hashes.
6260 if (param->gshared_constraint) {
6261 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6264 mono_image_lock (image);
6265 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6267 mono_image_unlock (image);
6272 if (n < FAST_CACHE_SIZE) {
6274 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6276 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6278 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6281 mono_image_lock (image);
6282 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6284 mono_image_unlock (image);
6291 * LOCKING: Image lock (param->image) must be held
6294 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6296 int n = mono_generic_param_num (param);
6297 MonoImage *image = get_image_for_generic_param (param);
6298 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6302 if (param->gshared_constraint) {
6303 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6305 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6306 mono_memory_barrier ();
6308 image->mvar_cache_constrained = ht;
6310 image->var_cache_constrained = ht;
6312 g_hash_table_insert (ht, param, klass);
6313 } else if (n < FAST_CACHE_SIZE) {
6315 /* Requires locking to avoid droping an already published class */
6316 if (!image->mvar_cache_fast)
6317 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6318 image->mvar_cache_fast [n] = klass;
6320 if (!image->var_cache_fast)
6321 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6322 image->var_cache_fast [n] = klass;
6325 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6327 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6329 ht = g_hash_table_new (NULL, NULL);
6330 mono_memory_barrier ();
6332 image->mvar_cache_slow = ht;
6334 image->var_cache_slow = ht;
6337 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6342 * LOCKING: Acquires the image lock (@image).
6345 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6347 MonoImage *image = get_image_for_generic_param (param);
6348 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6349 MonoClass *klass, *klass2;
6351 // If a klass already exists for this object and is cached, return it.
6352 if (pinfo) // Non-anonymous
6353 klass = pinfo->pklass;
6355 klass = get_anon_gparam_class (param, TRUE);
6360 // Create a new klass
6361 klass = make_generic_param_class (param, pinfo);
6363 // Now we need to cache the klass we created.
6364 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6365 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6366 // and allow our newly-created klass object to just leak.
6367 mono_memory_barrier ();
6369 mono_image_lock (image);
6371 // Here "klass2" refers to the klass potentially created by the other thread.
6372 if (pinfo) // Repeat check from above
6373 klass2 = pinfo->pklass;
6375 klass2 = get_anon_gparam_class (param, FALSE);
6382 pinfo->pklass = klass;
6384 set_anon_gparam_class (param, klass);
6386 mono_image_unlock (image);
6388 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6390 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6392 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6398 * mono_class_from_generic_parameter:
6399 * @param: Parameter to find/construct a class for.
6400 * @arg2: Is ignored.
6401 * @arg3: Is ignored.
6404 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6406 return mono_class_from_generic_parameter_internal (param);
6411 mono_ptr_class_get (MonoType *type)
6414 MonoClass *el_class;
6418 el_class = mono_class_from_mono_type (type);
6419 image = el_class->image;
6421 mono_image_lock (image);
6422 if (image->ptr_cache) {
6423 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6424 mono_image_unlock (image);
6428 mono_image_unlock (image);
6430 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6432 classes_size += sizeof (MonoClassPointer);
6434 result->parent = NULL; /* no parent for PTR types */
6435 result->name_space = el_class->name_space;
6436 name = g_strdup_printf ("%s*", el_class->name);
6437 result->name = mono_image_strdup (image, name);
6438 result->class_kind = MONO_CLASS_POINTER;
6441 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6443 result->image = el_class->image;
6444 result->inited = TRUE;
6445 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6446 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6447 result->cast_class = result->element_class = el_class;
6448 result->blittable = TRUE;
6450 result->byval_arg.type = MONO_TYPE_PTR;
6451 result->this_arg.type = result->byval_arg.type;
6452 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6453 result->this_arg.byref = TRUE;
6455 mono_class_setup_supertypes (result);
6457 mono_image_lock (image);
6458 if (image->ptr_cache) {
6460 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6461 mono_image_unlock (image);
6462 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6466 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6468 g_hash_table_insert (image->ptr_cache, el_class, result);
6469 mono_image_unlock (image);
6471 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6477 mono_fnptr_class_get (MonoMethodSignature *sig)
6480 static GHashTable *ptr_hash = NULL;
6482 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6484 mono_loader_lock ();
6487 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6489 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6490 mono_loader_unlock ();
6493 result = g_new0 (MonoClass, 1);
6495 result->parent = NULL; /* no parent for PTR types */
6496 result->name_space = "System";
6497 result->name = "MonoFNPtrFakeClass";
6498 result->class_kind = MONO_CLASS_POINTER;
6500 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6502 result->image = mono_defaults.corlib; /* need to fix... */
6503 result->inited = TRUE;
6504 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6505 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6506 result->cast_class = result->element_class = result;
6507 result->blittable = TRUE;
6509 result->byval_arg.type = MONO_TYPE_FNPTR;
6510 result->this_arg.type = result->byval_arg.type;
6511 result->this_arg.data.method = result->byval_arg.data.method = sig;
6512 result->this_arg.byref = TRUE;
6513 result->blittable = TRUE;
6515 mono_class_setup_supertypes (result);
6517 g_hash_table_insert (ptr_hash, sig, result);
6519 mono_loader_unlock ();
6521 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6527 * mono_class_from_mono_type:
6528 * @type: describes the type to return
6530 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6533 mono_class_from_mono_type (MonoType *type)
6535 switch (type->type) {
6536 case MONO_TYPE_OBJECT:
6537 return type->data.klass? type->data.klass: mono_defaults.object_class;
6538 case MONO_TYPE_VOID:
6539 return type->data.klass? type->data.klass: mono_defaults.void_class;
6540 case MONO_TYPE_BOOLEAN:
6541 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6542 case MONO_TYPE_CHAR:
6543 return type->data.klass? type->data.klass: mono_defaults.char_class;
6545 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6547 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6549 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6551 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6553 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6555 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6557 return type->data.klass? type->data.klass: mono_defaults.int_class;
6559 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6561 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6563 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6565 return type->data.klass? type->data.klass: mono_defaults.single_class;
6567 return type->data.klass? type->data.klass: mono_defaults.double_class;
6568 case MONO_TYPE_STRING:
6569 return type->data.klass? type->data.klass: mono_defaults.string_class;
6570 case MONO_TYPE_TYPEDBYREF:
6571 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6572 case MONO_TYPE_ARRAY:
6573 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6575 return mono_ptr_class_get (type->data.type);
6576 case MONO_TYPE_FNPTR:
6577 return mono_fnptr_class_get (type->data.method);
6578 case MONO_TYPE_SZARRAY:
6579 return mono_array_class_get (type->data.klass, 1);
6580 case MONO_TYPE_CLASS:
6581 case MONO_TYPE_VALUETYPE:
6582 return type->data.klass;
6583 case MONO_TYPE_GENERICINST:
6584 return mono_generic_class_get_class (type->data.generic_class);
6585 case MONO_TYPE_MVAR:
6587 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6589 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6590 g_assert_not_reached ();
6593 // Yes, this returns NULL, even if it is documented as not doing so, but there
6594 // is no way for the code to make it this far, due to the assert above.
6599 * mono_type_retrieve_from_typespec
6600 * @image: context where the image is created
6601 * @type_spec: typespec token
6602 * @context: the generic context used to evaluate generic instantiations in
6605 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6607 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6609 *did_inflate = FALSE;
6614 if (context && (context->class_inst || context->method_inst)) {
6615 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6617 if (!mono_error_ok (error)) {
6623 *did_inflate = TRUE;
6630 * mono_class_create_from_typespec
6631 * @image: context where the image is created
6632 * @type_spec: typespec token
6633 * @context: the generic context used to evaluate generic instantiations in
6636 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6639 gboolean inflated = FALSE;
6640 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6641 return_val_if_nok (error, NULL);
6642 ret = mono_class_from_mono_type (t);
6644 mono_metadata_free_type (t);
6649 * mono_bounded_array_class_get:
6650 * @element_class: element class
6651 * @rank: the dimension of the array class
6652 * @bounded: whenever the array has non-zero bounds
6654 * Returns: A class object describing the array with element type @element_type and
6658 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6662 MonoClass *parent = NULL;
6663 GSList *list, *rootlist = NULL;
6667 g_assert (rank <= 255);
6670 /* bounded only matters for one-dimensional arrays */
6673 image = eclass->image;
6675 if (rank == 1 && !bounded) {
6677 * This case is very frequent not just during compilation because of calls
6678 * from mono_class_from_mono_type (), mono_array_new (),
6679 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6681 mono_os_mutex_lock (&image->szarray_cache_lock);
6682 if (!image->szarray_cache)
6683 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6684 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6685 mono_os_mutex_unlock (&image->szarray_cache_lock);
6689 mono_loader_lock ();
6691 mono_loader_lock ();
6693 if (!image->array_cache)
6694 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6696 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6697 for (; list; list = list->next) {
6698 klass = (MonoClass *)list->data;
6699 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6700 mono_loader_unlock ();
6707 parent = mono_defaults.array_class;
6708 if (!parent->inited)
6709 mono_class_init (parent);
6711 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6713 klass->image = image;
6714 klass->name_space = eclass->name_space;
6715 klass->class_kind = MONO_CLASS_ARRAY;
6717 nsize = strlen (eclass->name);
6718 name = (char *)g_malloc (nsize + 2 + rank + 1);
6719 memcpy (name, eclass->name, nsize);
6722 memset (name + nsize + 1, ',', rank - 1);
6724 name [nsize + rank] = '*';
6725 name [nsize + rank + bounded] = ']';
6726 name [nsize + rank + bounded + 1] = 0;
6727 klass->name = mono_image_strdup (image, name);
6730 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6732 classes_size += sizeof (MonoClassArray);
6734 klass->type_token = 0;
6735 /* all arrays are marked serializable and sealed, bug #42779 */
6736 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6737 klass->parent = parent;
6738 klass->instance_size = mono_class_instance_size (klass->parent);
6740 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6741 /*Arrays of those two types are invalid.*/
6742 MonoError prepared_error;
6743 mono_error_init (&prepared_error);
6744 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6745 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6746 mono_error_cleanup (&prepared_error);
6747 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6748 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6749 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6750 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6752 /* element_size -1 is ok as this is not an instantitable type*/
6753 klass->sizes.element_size = -1;
6755 klass->sizes.element_size = mono_class_array_element_size (eclass);
6757 mono_class_setup_supertypes (klass);
6759 if (mono_class_is_ginst (eclass))
6760 mono_class_init (eclass);
6761 mono_class_init_sizes (eclass);
6762 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6763 /*FIXME we fail the array type, but we have to let other fields be set.*/
6765 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6769 if (eclass->enumtype)
6770 klass->cast_class = eclass->element_class;
6772 klass->cast_class = eclass;
6774 switch (klass->cast_class->byval_arg.type) {
6776 klass->cast_class = mono_defaults.byte_class;
6779 klass->cast_class = mono_defaults.int16_class;
6782 #if SIZEOF_VOID_P == 4
6786 klass->cast_class = mono_defaults.int32_class;
6789 #if SIZEOF_VOID_P == 8
6793 klass->cast_class = mono_defaults.int64_class;
6799 klass->element_class = eclass;
6801 if ((rank > 1) || bounded) {
6802 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6803 klass->byval_arg.type = MONO_TYPE_ARRAY;
6804 klass->byval_arg.data.array = at;
6805 at->eklass = eclass;
6807 /* FIXME: complete.... */
6809 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6810 klass->byval_arg.data.klass = eclass;
6812 klass->this_arg = klass->byval_arg;
6813 klass->this_arg.byref = 1;
6815 klass->generic_container = eclass->generic_container;
6817 if (rank == 1 && !bounded) {
6818 MonoClass *prev_class;
6820 mono_os_mutex_lock (&image->szarray_cache_lock);
6821 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6823 /* Someone got in before us */
6826 g_hash_table_insert (image->szarray_cache, eclass, klass);
6827 mono_os_mutex_unlock (&image->szarray_cache_lock);
6829 list = g_slist_append (rootlist, klass);
6830 g_hash_table_insert (image->array_cache, eclass, list);
6833 mono_loader_unlock ();
6835 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6841 * mono_array_class_get:
6842 * @element_class: element class
6843 * @rank: the dimension of the array class
6845 * Returns: A class object describing the array with element type @element_type and
6849 mono_array_class_get (MonoClass *eclass, guint32 rank)
6851 return mono_bounded_array_class_get (eclass, rank, FALSE);
6855 * mono_class_instance_size:
6858 * Use to get the size of a class in bytes.
6860 * Returns: The size of an object instance
6863 mono_class_instance_size (MonoClass *klass)
6865 if (!klass->size_inited)
6866 mono_class_init_sizes (klass);
6868 return klass->instance_size;
6872 * mono_class_min_align:
6875 * Use to get the computed minimum alignment requirements for the specified class.
6877 * Returns: minimum alignment requirements
6880 mono_class_min_align (MonoClass *klass)
6882 if (!klass->size_inited)
6883 mono_class_init_sizes (klass);
6885 return klass->min_align;
6889 * mono_class_value_size:
6892 * This function is used for value types, and return the
6893 * space and the alignment to store that kind of value object.
6895 * Returns: the size of a value of kind @klass
6898 mono_class_value_size (MonoClass *klass, guint32 *align)
6902 /* fixme: check disable, because we still have external revereces to
6903 * mscorlib and Dummy Objects
6905 /*g_assert (klass->valuetype);*/
6907 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6910 *align = klass->min_align;
6916 * mono_class_data_size:
6919 * Returns: The size of the static class data
6922 mono_class_data_size (MonoClass *klass)
6925 mono_class_init (klass);
6926 /* This can happen with dynamically created types */
6927 if (!klass->size_inited)
6928 mono_class_init_sizes (klass);
6930 /* in arrays, sizes.class_size is unioned with element_size
6931 * and arrays have no static fields
6935 return klass->sizes.class_size;
6939 * Auxiliary routine to mono_class_get_field
6941 * Takes a field index instead of a field token.
6943 static MonoClassField *
6944 mono_class_get_field_idx (MonoClass *klass, int idx)
6946 mono_class_setup_fields (klass);
6947 if (mono_class_has_failure (klass))
6951 if (klass->image->uncompressed_metadata) {
6953 * klass->field.first points to the FieldPtr table, while idx points into the
6954 * Field table, so we have to do a search.
6956 /*FIXME this is broken for types with multiple fields with the same name.*/
6957 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6960 for (i = 0; i < klass->field.count; ++i)
6961 if (mono_field_get_name (&klass->fields [i]) == name)
6962 return &klass->fields [i];
6963 g_assert_not_reached ();
6965 if (klass->field.count) {
6966 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6967 return &klass->fields [idx - klass->field.first];
6971 klass = klass->parent;
6977 * mono_class_get_field:
6978 * @class: the class to lookup the field.
6979 * @field_token: the field token
6981 * Returns: A MonoClassField representing the type and offset of
6982 * the field, or a NULL value if the field does not belong to this
6986 mono_class_get_field (MonoClass *klass, guint32 field_token)
6988 int idx = mono_metadata_token_index (field_token);
6990 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6992 return mono_class_get_field_idx (klass, idx - 1);
6996 * mono_class_get_field_from_name:
6997 * @klass: the class to lookup the field.
6998 * @name: the field name
7000 * Search the class @klass and it's parents for a field with the name @name.
7002 * Returns: The MonoClassField pointer of the named field or NULL
7005 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7007 return mono_class_get_field_from_name_full (klass, name, NULL);
7011 * mono_class_get_field_from_name_full:
7012 * @klass: the class to lookup the field.
7013 * @name: the field name
7014 * @type: the type of the fields. This optional.
7016 * Search the class @klass and it's parents for a field with the name @name and type @type.
7018 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7019 * of its generic type definition.
7021 * Returns: The MonoClassField pointer of the named field or NULL
7024 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7028 mono_class_setup_fields (klass);
7029 if (mono_class_has_failure (klass))
7033 for (i = 0; i < klass->field.count; ++i) {
7034 MonoClassField *field = &klass->fields [i];
7036 if (strcmp (name, mono_field_get_name (field)) != 0)
7040 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7041 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7046 klass = klass->parent;
7052 * mono_class_get_field_token:
7053 * @field: the field we need the token of
7055 * Get the token of a field. Note that the tokesn is only valid for the image
7056 * the field was loaded from. Don't use this function for fields in dynamic types.
7058 * Returns: The token representing the field in the image it was loaded from.
7061 mono_class_get_field_token (MonoClassField *field)
7063 MonoClass *klass = field->parent;
7066 mono_class_setup_fields (klass);
7071 for (i = 0; i < klass->field.count; ++i) {
7072 if (&klass->fields [i] == field) {
7073 int idx = klass->field.first + i + 1;
7075 if (klass->image->uncompressed_metadata)
7076 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7077 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7080 klass = klass->parent;
7083 g_assert_not_reached ();
7088 mono_field_get_index (MonoClassField *field)
7090 int index = field - field->parent->fields;
7092 g_assert (index >= 0 && index < field->parent->field.count);
7098 * mono_class_get_field_default_value:
7100 * Return the default value of the field as a pointer into the metadata blob.
7103 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7106 guint32 constant_cols [MONO_CONSTANT_SIZE];
7108 MonoClass *klass = field->parent;
7110 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7112 if (!klass->ext || !klass->ext->field_def_values) {
7113 MonoFieldDefaultValue *def_values;
7115 mono_class_alloc_ext (klass);
7117 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7119 mono_image_lock (klass->image);
7120 mono_memory_barrier ();
7121 if (!klass->ext->field_def_values)
7122 klass->ext->field_def_values = def_values;
7123 mono_image_unlock (klass->image);
7126 field_index = mono_field_get_index (field);
7128 if (!klass->ext->field_def_values [field_index].data) {
7129 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7133 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7135 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7136 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7137 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7140 *def_type = klass->ext->field_def_values [field_index].def_type;
7141 return klass->ext->field_def_values [field_index].data;
7145 mono_property_get_index (MonoProperty *prop)
7147 int index = prop - prop->parent->ext->properties;
7149 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7155 * mono_class_get_property_default_value:
7157 * Return the default value of the field as a pointer into the metadata blob.
7160 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7163 guint32 constant_cols [MONO_CONSTANT_SIZE];
7164 MonoClass *klass = property->parent;
7166 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7168 * We don't cache here because it is not used by C# so it's quite rare, but
7169 * we still do the lookup in klass->ext because that is where the data
7170 * is stored for dynamic assemblies.
7173 if (image_is_dynamic (klass->image)) {
7174 int prop_index = mono_property_get_index (property);
7175 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7176 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7177 return klass->ext->prop_def_values [prop_index].data;
7181 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7185 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7186 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7187 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7191 mono_class_get_event_token (MonoEvent *event)
7193 MonoClass *klass = event->parent;
7198 for (i = 0; i < klass->ext->event.count; ++i) {
7199 if (&klass->ext->events [i] == event)
7200 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7203 klass = klass->parent;
7206 g_assert_not_reached ();
7211 * mono_class_get_property_from_name:
7213 * @name: name of the property to lookup in the specified class
7215 * Use this method to lookup a property in a class
7216 * Returns: the MonoProperty with the given name, or NULL if the property
7217 * does not exist on the @klass.
7220 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7224 gpointer iter = NULL;
7225 while ((p = mono_class_get_properties (klass, &iter))) {
7226 if (! strcmp (name, p->name))
7229 klass = klass->parent;
7235 * mono_class_get_property_token:
7236 * @prop: MonoProperty to query
7238 * Returns: The ECMA token for the specified property.
7241 mono_class_get_property_token (MonoProperty *prop)
7243 MonoClass *klass = prop->parent;
7247 gpointer iter = NULL;
7248 while ((p = mono_class_get_properties (klass, &iter))) {
7249 if (&klass->ext->properties [i] == prop)
7250 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7254 klass = klass->parent;
7257 g_assert_not_reached ();
7262 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7264 const char *name, *nspace;
7265 if (image_is_dynamic (image))
7266 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7268 switch (type_token & 0xff000000){
7269 case MONO_TOKEN_TYPE_DEF: {
7270 guint32 cols [MONO_TYPEDEF_SIZE];
7271 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7272 guint tidx = mono_metadata_token_index (type_token);
7274 if (tidx > tt->rows)
7275 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7277 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7278 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7279 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7280 if (strlen (nspace) == 0)
7281 return g_strdup_printf ("%s", name);
7283 return g_strdup_printf ("%s.%s", nspace, name);
7286 case MONO_TOKEN_TYPE_REF: {
7288 guint32 cols [MONO_TYPEREF_SIZE];
7289 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7290 guint tidx = mono_metadata_token_index (type_token);
7293 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7295 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7296 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7297 mono_error_cleanup (&error);
7301 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7302 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7303 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7304 if (strlen (nspace) == 0)
7305 return g_strdup_printf ("%s", name);
7307 return g_strdup_printf ("%s.%s", nspace, name);
7310 case MONO_TOKEN_TYPE_SPEC:
7311 return g_strdup_printf ("Typespec 0x%08x", type_token);
7313 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7318 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7320 if (image_is_dynamic (image))
7321 return g_strdup_printf ("DynamicAssembly %s", image->name);
7323 switch (type_token & 0xff000000){
7324 case MONO_TOKEN_TYPE_DEF:
7325 if (image->assembly)
7326 return mono_stringify_assembly_name (&image->assembly->aname);
7327 else if (image->assembly_name)
7328 return g_strdup (image->assembly_name);
7329 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7330 case MONO_TOKEN_TYPE_REF: {
7332 MonoAssemblyName aname;
7333 guint32 cols [MONO_TYPEREF_SIZE];
7334 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7335 guint32 idx = mono_metadata_token_index (type_token);
7338 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7340 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7341 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7342 mono_error_cleanup (&error);
7345 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7347 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7348 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7349 case MONO_RESOLUTION_SCOPE_MODULE:
7351 return g_strdup ("");
7352 case MONO_RESOLUTION_SCOPE_MODULEREF:
7354 return g_strdup ("");
7355 case MONO_RESOLUTION_SCOPE_TYPEREF:
7357 return g_strdup ("");
7358 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7359 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7360 return mono_stringify_assembly_name (&aname);
7362 g_assert_not_reached ();
7366 case MONO_TOKEN_TYPE_SPEC:
7368 return g_strdup ("");
7370 g_assert_not_reached ();
7377 * mono_class_get_full:
7378 * @image: the image where the class resides
7379 * @type_token: the token for the class
7380 * @context: the generic context used to evaluate generic instantiations in
7381 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7383 * Returns: The MonoClass that represents @type_token in @image
7386 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7390 klass = mono_class_get_checked (image, type_token, &error);
7392 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7393 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7395 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7401 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7405 mono_error_init (error);
7406 klass = mono_class_get_checked (image, type_token, error);
7408 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7409 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7414 * mono_class_get_checked:
7415 * @image: the image where the class resides
7416 * @type_token: the token for the class
7417 * @error: error object to return any error
7419 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7422 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7424 MonoClass *klass = NULL;
7426 mono_error_init (error);
7428 if (image_is_dynamic (image)) {
7429 int table = mono_metadata_token_table (type_token);
7431 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7432 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7435 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7439 switch (type_token & 0xff000000){
7440 case MONO_TOKEN_TYPE_DEF:
7441 klass = mono_class_create_from_typedef (image, type_token, error);
7443 case MONO_TOKEN_TYPE_REF:
7444 klass = mono_class_from_typeref_checked (image, type_token, error);
7446 case MONO_TOKEN_TYPE_SPEC:
7447 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7450 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7454 /* Generic case, should be avoided for when a better error is possible. */
7455 if (!klass && mono_error_ok (error)) {
7456 char *name = mono_class_name_from_token (image, type_token);
7457 char *assembly = mono_assembly_name_from_token (image, type_token);
7458 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7466 * mono_type_get_checked:
7467 * @image: the image where the type resides
7468 * @type_token: the token for the type
7469 * @context: the generic context used to evaluate generic instantiations in
7470 * @error: Error handling context
7472 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7474 * Returns: The MonoType that represents @type_token in @image
7477 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7479 MonoType *type = NULL;
7480 gboolean inflated = FALSE;
7482 mono_error_init (error);
7484 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7485 if (image_is_dynamic (image)) {
7486 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7487 return_val_if_nok (error, NULL);
7488 return mono_class_get_type (klass);
7491 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7492 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7499 return mono_class_get_type (klass);
7502 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7509 MonoType *tmp = type;
7510 type = mono_class_get_type (mono_class_from_mono_type (type));
7511 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7512 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7513 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7515 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7517 if (type->type != tmp->type)
7520 mono_metadata_free_type (tmp);
7527 * @image: image where the class token will be looked up.
7528 * @type_token: a type token from the image
7530 * Returns the MonoClass with the given @type_token on the @image
7533 mono_class_get (MonoImage *image, guint32 type_token)
7535 return mono_class_get_full (image, type_token, NULL);
7539 * mono_image_init_name_cache:
7541 * Initializes the class name cache stored in image->name_cache.
7543 * LOCKING: Acquires the corresponding image lock.
7546 mono_image_init_name_cache (MonoImage *image)
7548 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7549 guint32 cols [MONO_TYPEDEF_SIZE];
7552 guint32 i, visib, nspace_index;
7553 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7555 if (image->name_cache)
7558 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7560 if (image_is_dynamic (image)) {
7561 mono_image_lock (image);
7562 if (image->name_cache) {
7563 /* Somebody initialized it before us */
7564 g_hash_table_destroy (the_name_cache);
7566 mono_atomic_store_release (&image->name_cache, the_name_cache);
7568 mono_image_unlock (image);
7572 /* Temporary hash table to avoid lookups in the nspace_table */
7573 name_cache2 = g_hash_table_new (NULL, NULL);
7575 for (i = 1; i <= t->rows; ++i) {
7576 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7577 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7579 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7580 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7582 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7584 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7585 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7587 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7588 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7589 if (!nspace_table) {
7590 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7591 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7592 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7595 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7598 /* Load type names from EXPORTEDTYPES table */
7600 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7601 guint32 cols [MONO_EXP_TYPE_SIZE];
7604 for (i = 0; i < t->rows; ++i) {
7605 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7607 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7608 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7612 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7613 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7615 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7616 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7617 if (!nspace_table) {
7618 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7619 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7620 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7623 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7627 g_hash_table_destroy (name_cache2);
7629 mono_image_lock (image);
7630 if (image->name_cache) {
7631 /* Somebody initialized it before us */
7632 g_hash_table_destroy (the_name_cache);
7634 mono_atomic_store_release (&image->name_cache, the_name_cache);
7636 mono_image_unlock (image);
7639 /*FIXME Only dynamic assemblies should allow this operation.*/
7641 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7642 const char *name, guint32 index)
7644 GHashTable *nspace_table;
7645 GHashTable *name_cache;
7648 mono_image_init_name_cache (image);
7649 mono_image_lock (image);
7651 name_cache = image->name_cache;
7652 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7653 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7654 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7657 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7658 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7660 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7662 mono_image_unlock (image);
7671 find_nocase (gpointer key, gpointer value, gpointer user_data)
7673 char *name = (char*)key;
7674 FindUserData *data = (FindUserData*)user_data;
7676 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7677 data->value = value;
7681 * mono_class_from_name_case:
7682 * @image: The MonoImage where the type is looked up in
7683 * @name_space: the type namespace
7684 * @name: the type short name.
7685 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7687 * Obtains a MonoClass with a given namespace and a given name which
7688 * is located in the given MonoImage. The namespace and name
7689 * lookups are case insensitive.
7692 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7695 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7696 mono_error_cleanup (&error);
7702 * mono_class_from_name_case:
7703 * @image: The MonoImage where the type is looked up in
7704 * @name_space: the type namespace
7705 * @name: the type short name.
7708 * Obtains a MonoClass with a given namespace and a given name which
7709 * is located in the given MonoImage. The namespace and name
7710 * lookups are case insensitive.
7712 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7713 * was not found. The @error object will contain information about the problem
7717 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7719 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7720 guint32 cols [MONO_TYPEDEF_SIZE];
7725 mono_error_init (error);
7727 if (image_is_dynamic (image)) {
7729 FindUserData user_data;
7731 mono_image_init_name_cache (image);
7732 mono_image_lock (image);
7734 user_data.key = name_space;
7735 user_data.value = NULL;
7736 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7738 if (user_data.value) {
7739 GHashTable *nspace_table = (GHashTable*)user_data.value;
7741 user_data.key = name;
7742 user_data.value = NULL;
7744 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7746 if (user_data.value)
7747 token = GPOINTER_TO_UINT (user_data.value);
7750 mono_image_unlock (image);
7753 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7759 /* add a cache if needed */
7760 for (i = 1; i <= t->rows; ++i) {
7761 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7762 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7764 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7765 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7767 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7769 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7770 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7771 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7772 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7778 return_nested_in (MonoClass *klass, char *nested)
7781 char *s = strchr (nested, '/');
7782 gpointer iter = NULL;
7789 while ((found = mono_class_get_nested_types (klass, &iter))) {
7790 if (strcmp (found->name, nested) == 0) {
7792 return return_nested_in (found, s);
7800 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7802 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7803 MonoImage *file_image;
7807 mono_error_init (error);
7810 * The EXPORTEDTYPES table only contains public types, so have to search the
7812 * Note: image->modules contains the contents of the MODULEREF table, while
7813 * the real module list is in the FILE table.
7815 for (i = 0; i < file_table->rows; i++) {
7816 guint32 cols [MONO_FILE_SIZE];
7817 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7818 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7821 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7823 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7824 if (klass || !is_ok (error))
7833 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7835 GHashTable *nspace_table;
7836 MonoImage *loaded_image;
7843 mono_error_init (error);
7845 // Checking visited images avoids stack overflows when cyclic references exist.
7846 if (g_hash_table_lookup (visited_images, image))
7849 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7851 if ((nested = strchr (name, '/'))) {
7852 int pos = nested - name;
7853 int len = strlen (name);
7856 memcpy (buf, name, len + 1);
7858 nested = buf + pos + 1;
7862 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7863 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7864 gboolean res = get_class_from_name (image, name_space, name, &klass);
7867 klass = search_modules (image, name_space, name, error);
7872 return klass ? return_nested_in (klass, nested) : NULL;
7878 mono_image_init_name_cache (image);
7879 mono_image_lock (image);
7881 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7884 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7886 mono_image_unlock (image);
7888 if (!token && image_is_dynamic (image) && image->modules) {
7889 /* Search modules as well */
7890 for (i = 0; i < image->module_count; ++i) {
7891 MonoImage *module = image->modules [i];
7893 klass = mono_class_from_name_checked (module, name_space, name, error);
7894 if (klass || !is_ok (error))
7900 klass = search_modules (image, name_space, name, error);
7901 if (klass || !is_ok (error))
7906 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7907 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7908 guint32 cols [MONO_EXP_TYPE_SIZE];
7911 idx = mono_metadata_token_index (token);
7913 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7915 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7916 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7917 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7920 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7922 return klass ? return_nested_in (klass, nested) : NULL;
7924 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7925 guint32 assembly_idx;
7927 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7929 mono_assembly_load_reference (image, assembly_idx - 1);
7930 g_assert (image->references [assembly_idx - 1]);
7931 if (image->references [assembly_idx - 1] == (gpointer)-1)
7933 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7935 return klass ? return_nested_in (klass, nested) : NULL;
7938 g_assert_not_reached ();
7942 token = MONO_TOKEN_TYPE_DEF | token;
7944 klass = mono_class_get_checked (image, token, error);
7946 return return_nested_in (klass, nested);
7951 * mono_class_from_name_checked:
7952 * @image: The MonoImage where the type is looked up in
7953 * @name_space: the type namespace
7954 * @name: the type short name.
7956 * Obtains a MonoClass with a given namespace and a given name which
7957 * is located in the given MonoImage.
7959 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7960 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7963 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7966 GHashTable *visited_images;
7968 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7970 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7972 g_hash_table_destroy (visited_images);
7978 * mono_class_from_name:
7979 * @image: The MonoImage where the type is looked up in
7980 * @name_space: the type namespace
7981 * @name: the type short name.
7983 * Obtains a MonoClass with a given namespace and a given name which
7984 * is located in the given MonoImage.
7986 * To reference nested classes, use the "/" character as a separator.
7987 * For example use "Foo/Bar" to reference the class Bar that is nested
7988 * inside Foo, like this: "class Foo { class Bar {} }".
7991 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7996 klass = mono_class_from_name_checked (image, name_space, name, &error);
7997 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8003 * mono_class_load_from_name:
8004 * @image: The MonoImage where the type is looked up in
8005 * @name_space: the type namespace
8006 * @name: the type short name.
8008 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8009 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8010 * If they are missing. Thing of System.Object or System.String.
8013 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8018 klass = mono_class_from_name_checked (image, name_space, name, &error);
8020 g_error ("Runtime critical type %s.%s not found", name_space, name);
8021 if (!mono_error_ok (&error))
8022 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8027 * mono_class_try_load_from_name:
8028 * @image: The MonoImage where the type is looked up in
8029 * @name_space: the type namespace
8030 * @name: the type short name.
8032 * This function tries to load a type, returning the class was found or NULL otherwise.
8033 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8035 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8036 * a type that we would otherwise assume to be available but was not due some error.
8040 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8045 klass = mono_class_from_name_checked (image, name_space, name, &error);
8046 if (!mono_error_ok (&error))
8047 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8053 * mono_class_is_subclass_of:
8054 * @klass: class to probe if it is a subclass of another one
8055 * @klassc: the class we suspect is the base class
8056 * @check_interfaces: whether we should perform interface checks
8058 * This method determines whether @klass is a subclass of @klassc.
8060 * If the @check_interfaces flag is set, then if @klassc is an interface
8061 * this method return TRUE if the @klass implements the interface or
8062 * if @klass is an interface, if one of its base classes is @klass.
8064 * If @check_interfaces is false then, then if @klass is not an interface
8065 * then it returns TRUE if the @klass is a subclass of @klassc.
8067 * if @klass is an interface and @klassc is System.Object, then this function
8072 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8073 gboolean check_interfaces)
8075 /* FIXME test for interfaces with variant generic arguments */
8076 mono_class_init (klass);
8077 mono_class_init (klassc);
8079 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8080 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8082 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8085 for (i = 0; i < klass->interface_count; i ++) {
8086 MonoClass *ic = klass->interfaces [i];
8091 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8096 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8099 if (klassc == mono_defaults.object_class)
8106 mono_type_is_generic_argument (MonoType *type)
8108 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8112 mono_class_has_variant_generic_params (MonoClass *klass)
8115 MonoGenericContainer *container;
8117 if (!mono_class_is_ginst (klass))
8120 container = mono_class_get_generic_class (klass)->container_class->generic_container;
8122 for (i = 0; i < container->type_argc; ++i)
8123 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8130 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8132 if (target == candidate)
8135 if (check_for_reference_conv &&
8136 mono_type_is_generic_argument (&target->byval_arg) &&
8137 mono_type_is_generic_argument (&candidate->byval_arg)) {
8138 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8139 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8141 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8144 if (!mono_class_is_assignable_from (target, candidate))
8150 * @container the generic container from the GTD
8151 * @klass: the class to be assigned to
8152 * @oklass: the source class
8154 * Both @klass and @oklass must be instances of the same generic interface.
8156 * Returns: TRUE if @klass can be assigned to a @klass variable
8159 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8162 MonoType **klass_argv, **oklass_argv;
8163 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8164 MonoGenericContainer *container = klass_gtd->generic_container;
8166 if (klass == oklass)
8169 /*Viable candidates are instances of the same generic interface*/
8170 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8173 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8174 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8176 for (j = 0; j < container->type_argc; ++j) {
8177 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8178 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8180 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8184 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8185 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8187 if (param1_class != param2_class) {
8188 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8189 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8191 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8192 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8202 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8204 MonoGenericParam *gparam, *ogparam;
8205 MonoGenericParamInfo *tinfo, *cinfo;
8206 MonoClass **candidate_class;
8207 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8210 if (target == candidate)
8212 if (target->byval_arg.type != candidate->byval_arg.type)
8215 gparam = target->byval_arg.data.generic_param;
8216 ogparam = candidate->byval_arg.data.generic_param;
8217 tinfo = mono_generic_param_info (gparam);
8218 cinfo = mono_generic_param_info (ogparam);
8220 class_constraint_satisfied = FALSE;
8221 valuetype_constraint_satisfied = FALSE;
8223 /*candidate must have a super set of target's special constraints*/
8224 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8225 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8227 if (cinfo->constraints) {
8228 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8229 MonoClass *cc = *candidate_class;
8231 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8232 class_constraint_satisfied = TRUE;
8233 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8234 valuetype_constraint_satisfied = TRUE;
8237 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8238 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8240 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8242 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8244 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8245 valuetype_constraint_satisfied)) {
8250 /*candidate type constraints must be a superset of target's*/
8251 if (tinfo->constraints) {
8252 MonoClass **target_class;
8253 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8254 MonoClass *tc = *target_class;
8257 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8258 * check it's constraints since it satisfy the constraint by itself.
8260 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8263 if (!cinfo->constraints)
8266 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8267 MonoClass *cc = *candidate_class;
8269 if (mono_class_is_assignable_from (tc, cc))
8273 * This happens when we have the following:
8275 * Bar<K> where K : IFace
8276 * Foo<T, U> where T : U where U : IFace
8278 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8281 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8282 if (mono_gparam_is_assignable_from (target, cc))
8286 if (!*candidate_class)
8291 /*candidate itself must have a constraint that satisfy target*/
8292 if (cinfo->constraints) {
8293 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8294 MonoClass *cc = *candidate_class;
8295 if (mono_class_is_assignable_from (target, cc))
8303 * mono_class_is_assignable_from:
8304 * @klass: the class to be assigned to
8305 * @oklass: the source class
8307 * Returns: TRUE if an instance of object oklass can be assigned to an
8308 * instance of object @klass
8311 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8314 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8316 mono_class_init (klass);
8318 if (!oklass->inited)
8319 mono_class_init (oklass);
8321 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8324 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8325 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8327 return mono_gparam_is_assignable_from (klass, oklass);
8330 if (MONO_CLASS_IS_INTERFACE (klass)) {
8331 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8332 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8333 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8337 for (i = 0; constraints [i]; ++i) {
8338 if (mono_class_is_assignable_from (klass, constraints [i]))
8346 /* interface_offsets might not be set for dynamic classes */
8347 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8349 * oklass might be a generic type parameter but they have
8350 * interface_offsets set.
8352 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8353 if (!is_ok (&error)) {
8354 mono_error_cleanup (&error);
8359 if (!oklass->interface_bitmap)
8360 /* Happens with generic instances of not-yet created dynamic types */
8362 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8365 if (mono_class_has_variant_generic_params (klass)) {
8367 mono_class_setup_interfaces (oklass, &error);
8368 if (!mono_error_ok (&error)) {
8369 mono_error_cleanup (&error);
8373 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8374 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8375 MonoClass *iface = oklass->interfaces_packed [i];
8377 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8382 } else if (klass->delegate) {
8383 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8385 }else if (klass->rank) {
8386 MonoClass *eclass, *eoclass;
8388 if (oklass->rank != klass->rank)
8391 /* vectors vs. one dimensional arrays */
8392 if (oklass->byval_arg.type != klass->byval_arg.type)
8395 eclass = klass->cast_class;
8396 eoclass = oklass->cast_class;
8399 * a is b does not imply a[] is b[] when a is a valuetype, and
8400 * b is a reference type.
8403 if (eoclass->valuetype) {
8404 if ((eclass == mono_defaults.enum_class) ||
8405 (eclass == mono_defaults.enum_class->parent) ||
8406 (eclass == mono_defaults.object_class))
8410 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8411 } else if (mono_class_is_nullable (klass)) {
8412 if (mono_class_is_nullable (oklass))
8413 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8415 return mono_class_is_assignable_from (klass->cast_class, oklass);
8416 } else if (klass == mono_defaults.object_class)
8419 return mono_class_has_parent (oklass, klass);
8422 /*Check if @oklass is variant compatible with @klass.*/
8424 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8427 MonoType **klass_argv, **oklass_argv;
8428 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8429 MonoGenericContainer *container = klass_gtd->generic_container;
8431 /*Viable candidates are instances of the same generic interface*/
8432 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8435 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8436 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8438 for (j = 0; j < container->type_argc; ++j) {
8439 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8440 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8442 if (param1_class->valuetype != param2_class->valuetype)
8446 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8447 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8449 if (param1_class != param2_class) {
8450 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8451 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8453 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8454 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8462 /*Check if @candidate implements the interface @target*/
8464 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8468 gboolean is_variant = mono_class_has_variant_generic_params (target);
8470 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8471 if (mono_class_is_variant_compatible_slow (target, candidate))
8476 if (candidate == target)
8479 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8480 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8481 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8483 if (tb && tb->interfaces) {
8484 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8485 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8486 MonoClass *iface_class;
8488 /* we can't realize the type here since it can do pretty much anything. */
8491 iface_class = mono_class_from_mono_type (iface->type);
8492 if (iface_class == target)
8494 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8496 if (mono_class_implement_interface_slow (target, iface_class))
8501 /*setup_interfaces don't mono_class_init anything*/
8502 /*FIXME this doesn't handle primitive type arrays.
8503 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8504 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8506 mono_class_setup_interfaces (candidate, &error);
8507 if (!mono_error_ok (&error)) {
8508 mono_error_cleanup (&error);
8512 for (i = 0; i < candidate->interface_count; ++i) {
8513 if (candidate->interfaces [i] == target)
8516 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8519 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8523 candidate = candidate->parent;
8524 } while (candidate);
8530 * Check if @oklass can be assigned to @klass.
8531 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8534 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8536 if (candidate == target)
8538 if (target == mono_defaults.object_class)
8541 if (mono_class_has_parent (candidate, target))
8544 /*If target is not an interface there is no need to check them.*/
8545 if (MONO_CLASS_IS_INTERFACE (target))
8546 return mono_class_implement_interface_slow (target, candidate);
8548 if (target->delegate && mono_class_has_variant_generic_params (target))
8549 return mono_class_is_variant_compatible (target, candidate, FALSE);
8552 MonoClass *eclass, *eoclass;
8554 if (target->rank != candidate->rank)
8557 /* vectors vs. one dimensional arrays */
8558 if (target->byval_arg.type != candidate->byval_arg.type)
8561 eclass = target->cast_class;
8562 eoclass = candidate->cast_class;
8565 * a is b does not imply a[] is b[] when a is a valuetype, and
8566 * b is a reference type.
8569 if (eoclass->valuetype) {
8570 if ((eclass == mono_defaults.enum_class) ||
8571 (eclass == mono_defaults.enum_class->parent) ||
8572 (eclass == mono_defaults.object_class))
8576 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8578 /*FIXME properly handle nullables */
8579 /*FIXME properly handle (M)VAR */
8584 * mono_class_get_cctor:
8585 * @klass: A MonoClass pointer
8587 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8590 mono_class_get_cctor (MonoClass *klass)
8592 MonoCachedClassInfo cached_info;
8594 if (image_is_dynamic (klass->image)) {
8596 * has_cctor is not set for these classes because mono_class_init () is
8599 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8602 if (!klass->has_cctor)
8605 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8607 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8608 if (!mono_error_ok (&error))
8609 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8613 if (mono_class_is_ginst (klass) && !klass->methods)
8614 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8616 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8620 * mono_class_get_finalizer:
8621 * @klass: The MonoClass pointer
8623 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8626 mono_class_get_finalizer (MonoClass *klass)
8628 MonoCachedClassInfo cached_info;
8631 mono_class_init (klass);
8632 if (!mono_class_has_finalizer (klass))
8635 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8637 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8638 if (!mono_error_ok (&error))
8639 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8642 mono_class_setup_vtable (klass);
8643 return klass->vtable [finalize_slot];
8648 * mono_class_needs_cctor_run:
8649 * @klass: the MonoClass pointer
8650 * @caller: a MonoMethod describing the caller
8652 * Determines whenever the class has a static constructor and whenever it
8653 * needs to be called when executing CALLER.
8656 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8660 method = mono_class_get_cctor (klass);
8662 return (method == caller) ? FALSE : TRUE;
8668 * mono_class_array_element_size:
8671 * Returns: The number of bytes an element of type @klass
8672 * uses when stored into an array.
8675 mono_class_array_element_size (MonoClass *klass)
8677 MonoType *type = &klass->byval_arg;
8680 switch (type->type) {
8683 case MONO_TYPE_BOOLEAN:
8687 case MONO_TYPE_CHAR:
8696 case MONO_TYPE_CLASS:
8697 case MONO_TYPE_STRING:
8698 case MONO_TYPE_OBJECT:
8699 case MONO_TYPE_SZARRAY:
8700 case MONO_TYPE_ARRAY:
8701 return sizeof (gpointer);
8706 case MONO_TYPE_VALUETYPE:
8707 if (type->data.klass->enumtype) {
8708 type = mono_class_enum_basetype (type->data.klass);
8709 klass = klass->element_class;
8712 return mono_class_instance_size (klass) - sizeof (MonoObject);
8713 case MONO_TYPE_GENERICINST:
8714 type = &type->data.generic_class->container_class->byval_arg;
8717 case MONO_TYPE_MVAR: {
8720 return mono_type_size (type, &align);
8722 case MONO_TYPE_VOID:
8726 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8732 * mono_array_element_size:
8733 * @ac: pointer to a #MonoArrayClass
8735 * Returns: The size of single array element.
8738 mono_array_element_size (MonoClass *ac)
8740 g_assert (ac->rank);
8741 return ac->sizes.element_size;
8745 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8746 MonoGenericContext *context)
8749 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8750 g_assert (mono_error_ok (&error));
8755 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8756 MonoGenericContext *context, MonoError *error)
8758 mono_error_init (error);
8760 if (image_is_dynamic (image)) {
8761 MonoClass *tmp_handle_class;
8762 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8764 mono_error_assert_ok (error);
8765 g_assert (tmp_handle_class);
8767 *handle_class = tmp_handle_class;
8769 if (tmp_handle_class == mono_defaults.typehandle_class)
8770 return &((MonoClass*)obj)->byval_arg;
8775 switch (token & 0xff000000) {
8776 case MONO_TOKEN_TYPE_DEF:
8777 case MONO_TOKEN_TYPE_REF:
8778 case MONO_TOKEN_TYPE_SPEC: {
8781 *handle_class = mono_defaults.typehandle_class;
8782 type = mono_type_get_checked (image, token, context, error);
8786 mono_class_init (mono_class_from_mono_type (type));
8787 /* We return a MonoType* as handle */
8790 case MONO_TOKEN_FIELD_DEF: {
8792 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8794 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8798 *handle_class = mono_defaults.fieldhandle_class;
8799 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8803 mono_class_init (klass);
8804 return mono_class_get_field (klass, token);
8806 case MONO_TOKEN_METHOD_DEF:
8807 case MONO_TOKEN_METHOD_SPEC: {
8809 meth = mono_get_method_checked (image, token, NULL, context, error);
8811 *handle_class = mono_defaults.methodhandle_class;
8817 case MONO_TOKEN_MEMBER_REF: {
8818 guint32 cols [MONO_MEMBERREF_SIZE];
8820 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8821 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8822 mono_metadata_decode_blob_size (sig, &sig);
8823 if (*sig == 0x6) { /* it's a field */
8825 MonoClassField *field;
8826 field = mono_field_from_token_checked (image, token, &klass, context, error);
8828 *handle_class = mono_defaults.fieldhandle_class;
8832 meth = mono_get_method_checked (image, token, NULL, context, error);
8834 *handle_class = mono_defaults.methodhandle_class;
8839 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8845 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8847 MonoClass *handle_class;
8848 mono_error_init (error);
8849 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8853 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8855 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8858 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8861 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8863 get_cached_class_info = func;
8867 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8869 if (!get_cached_class_info)
8872 return get_cached_class_info (klass, res);
8876 mono_install_get_class_from_name (MonoGetClassFromName func)
8878 get_class_from_name = func;
8882 * mono_class_get_image:
8884 * Use this method to get the `MonoImage*` where this class came from.
8886 * Returns: The image where this class is defined.
8889 mono_class_get_image (MonoClass *klass)
8891 return klass->image;
8895 * mono_class_get_element_class:
8896 * @klass: the MonoClass to act on
8898 * Use this function to get the element class of an array.
8900 * Returns: The element class of an array.
8903 mono_class_get_element_class (MonoClass *klass)
8905 return klass->element_class;
8909 * mono_class_is_valuetype:
8910 * @klass: the MonoClass to act on
8912 * Use this method to determine if the provided `MonoClass*` represents a value type,
8913 * or a reference type.
8915 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8918 mono_class_is_valuetype (MonoClass *klass)
8920 return klass->valuetype;
8924 * mono_class_is_enum:
8925 * @klass: the MonoClass to act on
8927 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8929 * Returns: TRUE if the MonoClass represents an enumeration.
8932 mono_class_is_enum (MonoClass *klass)
8934 return klass->enumtype;
8938 * mono_class_enum_basetype:
8939 * @klass: the MonoClass to act on
8941 * Use this function to get the underlying type for an enumeration value.
8943 * Returns: The underlying type representation for an enumeration.
8946 mono_class_enum_basetype (MonoClass *klass)
8948 if (klass->element_class == klass)
8949 /* SRE or broken types */
8952 return &klass->element_class->byval_arg;
8956 * mono_class_get_parent
8957 * @klass: the MonoClass to act on
8959 * Returns: The parent class for this class.
8962 mono_class_get_parent (MonoClass *klass)
8964 return klass->parent;
8968 * mono_class_get_nesting_type:
8969 * @klass: the MonoClass to act on
8971 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8973 * If the return is NULL, this indicates that this class is not nested.
8975 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8978 mono_class_get_nesting_type (MonoClass *klass)
8980 return klass->nested_in;
8984 * mono_class_get_rank:
8985 * @klass: the MonoClass to act on
8987 * Returns: The rank for the array (the number of dimensions).
8990 mono_class_get_rank (MonoClass *klass)
8996 * mono_class_get_flags:
8997 * @klass: the MonoClass to act on
8999 * The type flags from the TypeDef table from the metadata.
9000 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
9003 * Returns: The flags from the TypeDef table.
9006 mono_class_get_flags (MonoClass *klass)
9008 return klass->flags;
9012 * mono_class_get_name
9013 * @klass: the MonoClass to act on
9015 * Returns: The name of the class.
9018 mono_class_get_name (MonoClass *klass)
9024 * mono_class_get_namespace:
9025 * @klass: the MonoClass to act on
9027 * Returns: The namespace of the class.
9030 mono_class_get_namespace (MonoClass *klass)
9032 return klass->name_space;
9036 * mono_class_get_type:
9037 * @klass: the MonoClass to act on
9039 * This method returns the internal Type representation for the class.
9041 * Returns: The MonoType from the class.
9044 mono_class_get_type (MonoClass *klass)
9046 return &klass->byval_arg;
9050 * mono_class_get_type_token:
9051 * @klass: the MonoClass to act on
9053 * This method returns type token for the class.
9055 * Returns: The type token for the class.
9058 mono_class_get_type_token (MonoClass *klass)
9060 return klass->type_token;
9064 * mono_class_get_byref_type:
9065 * @klass: the MonoClass to act on
9070 mono_class_get_byref_type (MonoClass *klass)
9072 return &klass->this_arg;
9076 * mono_class_num_fields:
9077 * @klass: the MonoClass to act on
9079 * Returns: The number of static and instance fields in the class.
9082 mono_class_num_fields (MonoClass *klass)
9084 return klass->field.count;
9088 * mono_class_num_methods:
9089 * @klass: the MonoClass to act on
9091 * Returns: The number of methods in the class.
9094 mono_class_num_methods (MonoClass *klass)
9096 return klass->method.count;
9100 * mono_class_num_properties
9101 * @klass: the MonoClass to act on
9103 * Returns: The number of properties in the class.
9106 mono_class_num_properties (MonoClass *klass)
9108 mono_class_setup_properties (klass);
9110 return klass->ext->property.count;
9114 * mono_class_num_events:
9115 * @klass: the MonoClass to act on
9117 * Returns: The number of events in the class.
9120 mono_class_num_events (MonoClass *klass)
9122 mono_class_setup_events (klass);
9124 return klass->ext->event.count;
9128 * mono_class_get_fields:
9129 * @klass: the MonoClass to act on
9131 * This routine is an iterator routine for retrieving the fields in a class.
9133 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9134 * iterate over all of the elements. When no more values are
9135 * available, the return value is NULL.
9137 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9140 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9142 MonoClassField* field;
9146 mono_class_setup_fields (klass);
9147 if (mono_class_has_failure (klass))
9149 /* start from the first */
9150 if (klass->field.count) {
9151 *iter = &klass->fields [0];
9152 return &klass->fields [0];
9158 field = (MonoClassField *)*iter;
9160 if (field < &klass->fields [klass->field.count]) {
9168 * mono_class_get_methods
9169 * @klass: the MonoClass to act on
9171 * This routine is an iterator routine for retrieving the fields in a class.
9173 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9174 * iterate over all of the elements. When no more values are
9175 * available, the return value is NULL.
9177 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9180 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9182 MonoMethod** method;
9186 mono_class_setup_methods (klass);
9189 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9190 * FIXME we should better report this error to the caller
9192 if (!klass->methods)
9194 /* start from the first */
9195 if (klass->method.count) {
9196 *iter = &klass->methods [0];
9197 return klass->methods [0];
9203 method = (MonoMethod **)*iter;
9205 if (method < &klass->methods [klass->method.count]) {
9213 * mono_class_get_virtual_methods:
9215 * Iterate over the virtual methods of KLASS.
9217 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9220 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9222 MonoMethod** method;
9225 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9227 mono_class_setup_methods (klass);
9229 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9230 * FIXME we should better report this error to the caller
9232 if (!klass->methods)
9234 /* start from the first */
9235 method = &klass->methods [0];
9237 method = (MonoMethod **)*iter;
9240 while (method < &klass->methods [klass->method.count]) {
9241 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9245 if (method < &klass->methods [klass->method.count]) {
9252 /* Search directly in metadata to avoid calling setup_methods () */
9253 MonoMethod *res = NULL;
9259 start_index = GPOINTER_TO_UINT (*iter);
9262 for (i = start_index; i < klass->method.count; ++i) {
9265 /* klass->method.first points into the methodptr table */
9266 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9268 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9272 if (i < klass->method.count) {
9274 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9275 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9277 /* Add 1 here so the if (*iter) check fails */
9278 *iter = GUINT_TO_POINTER (i + 1);
9287 * mono_class_get_properties:
9288 * @klass: the MonoClass to act on
9290 * This routine is an iterator routine for retrieving the properties in a class.
9292 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9293 * iterate over all of the elements. When no more values are
9294 * available, the return value is NULL.
9296 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9299 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9301 MonoProperty* property;
9305 mono_class_setup_properties (klass);
9306 /* start from the first */
9307 if (klass->ext->property.count) {
9308 *iter = &klass->ext->properties [0];
9309 return (MonoProperty *)*iter;
9315 property = (MonoProperty *)*iter;
9317 if (property < &klass->ext->properties [klass->ext->property.count]) {
9319 return (MonoProperty *)*iter;
9325 * mono_class_get_events:
9326 * @klass: the MonoClass to act on
9328 * This routine is an iterator routine for retrieving the properties in a class.
9330 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9331 * iterate over all of the elements. When no more values are
9332 * available, the return value is NULL.
9334 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9337 mono_class_get_events (MonoClass* klass, gpointer *iter)
9343 mono_class_setup_events (klass);
9344 /* start from the first */
9345 if (klass->ext->event.count) {
9346 *iter = &klass->ext->events [0];
9347 return (MonoEvent *)*iter;
9353 event = (MonoEvent *)*iter;
9355 if (event < &klass->ext->events [klass->ext->event.count]) {
9357 return (MonoEvent *)*iter;
9363 * mono_class_get_interfaces
9364 * @klass: the MonoClass to act on
9366 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9368 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9369 * iterate over all of the elements. When no more values are
9370 * available, the return value is NULL.
9372 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9375 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9383 mono_class_init (klass);
9384 if (!klass->interfaces_inited) {
9385 mono_class_setup_interfaces (klass, &error);
9386 if (!mono_error_ok (&error)) {
9387 mono_error_cleanup (&error);
9391 /* start from the first */
9392 if (klass->interface_count) {
9393 *iter = &klass->interfaces [0];
9394 return klass->interfaces [0];
9400 iface = (MonoClass **)*iter;
9402 if (iface < &klass->interfaces [klass->interface_count]) {
9410 setup_nested_types (MonoClass *klass)
9413 GList *classes, *nested_classes, *l;
9416 if (klass->nested_classes_inited)
9419 if (!klass->type_token)
9420 klass->nested_classes_inited = TRUE;
9422 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9426 guint32 cols [MONO_NESTED_CLASS_SIZE];
9427 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9428 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9429 if (!mono_error_ok (&error)) {
9430 /*FIXME don't swallow the error message*/
9431 mono_error_cleanup (&error);
9433 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9437 classes = g_list_prepend (classes, nclass);
9439 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9442 mono_class_alloc_ext (klass);
9444 nested_classes = NULL;
9445 for (l = classes; l; l = l->next)
9446 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9447 g_list_free (classes);
9449 mono_image_lock (klass->image);
9451 mono_memory_barrier ();
9452 if (!klass->nested_classes_inited) {
9453 klass->ext->nested_classes = nested_classes;
9454 mono_memory_barrier ();
9455 klass->nested_classes_inited = TRUE;
9458 mono_image_unlock (klass->image);
9462 * mono_class_get_nested_types
9463 * @klass: the MonoClass to act on
9465 * This routine is an iterator routine for retrieving the nested types of a class.
9466 * This works only if @klass is non-generic, or a generic type definition.
9468 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9469 * iterate over all of the elements. When no more values are
9470 * available, the return value is NULL.
9472 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9475 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9481 if (!klass->nested_classes_inited)
9482 setup_nested_types (klass);
9485 /* start from the first */
9486 if (klass->ext && klass->ext->nested_classes) {
9487 *iter = klass->ext->nested_classes;
9488 return (MonoClass *)klass->ext->nested_classes->data;
9490 /* no nested types */
9494 item = (GList *)*iter;
9498 return (MonoClass *)item->data;
9505 * mono_class_is_delegate
9506 * @klass: the MonoClass to act on
9508 * Returns: TRUE if the MonoClass represents a System.Delegate.
9511 mono_class_is_delegate (MonoClass *klass)
9513 return klass->delegate;
9517 * mono_class_implements_interface
9518 * @klass: The MonoClass to act on
9519 * @interface: The interface to check if @klass implements.
9521 * Returns: TRUE if @klass implements @interface.
9524 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9526 return mono_class_is_assignable_from (iface, klass);
9530 * mono_field_get_name:
9531 * @field: the MonoClassField to act on
9533 * Returns: The name of the field.
9536 mono_field_get_name (MonoClassField *field)
9542 * mono_field_get_type:
9543 * @field: the MonoClassField to act on
9545 * Returns: MonoType of the field.
9548 mono_field_get_type (MonoClassField *field)
9551 MonoType *type = mono_field_get_type_checked (field, &error);
9552 if (!mono_error_ok (&error)) {
9553 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9554 mono_error_cleanup (&error);
9561 * mono_field_get_type_checked:
9562 * @field: the MonoClassField to act on
9563 * @error: used to return any erro found while retrieving @field type
9565 * Returns: MonoType of the field.
9568 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9570 mono_error_init (error);
9572 mono_field_resolve_type (field, error);
9577 * mono_field_get_parent:
9578 * @field: the MonoClassField to act on
9580 * Returns: MonoClass where the field was defined.
9583 mono_field_get_parent (MonoClassField *field)
9585 return field->parent;
9589 * mono_field_get_flags;
9590 * @field: the MonoClassField to act on
9592 * The metadata flags for a field are encoded using the
9593 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9595 * Returns: The flags for the field.
9598 mono_field_get_flags (MonoClassField *field)
9601 return mono_field_resolve_flags (field);
9602 return field->type->attrs;
9606 * mono_field_get_offset:
9607 * @field: the MonoClassField to act on
9609 * Returns: The field offset.
9612 mono_field_get_offset (MonoClassField *field)
9614 return field->offset;
9618 mono_field_get_rva (MonoClassField *field)
9622 MonoClass *klass = field->parent;
9623 MonoFieldDefaultValue *field_def_values;
9625 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9627 if (!klass->ext || !klass->ext->field_def_values) {
9628 mono_class_alloc_ext (klass);
9630 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9632 mono_image_lock (klass->image);
9633 if (!klass->ext->field_def_values)
9634 klass->ext->field_def_values = field_def_values;
9635 mono_image_unlock (klass->image);
9638 field_index = mono_field_get_index (field);
9640 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9641 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9643 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9644 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9647 return klass->ext->field_def_values [field_index].data;
9651 * mono_field_get_data:
9652 * @field: the MonoClassField to act on
9654 * Returns: A pointer to the metadata constant value or to the field
9655 * data if it has an RVA flag.
9658 mono_field_get_data (MonoClassField *field)
9660 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9661 MonoTypeEnum def_type;
9663 return mono_class_get_field_default_value (field, &def_type);
9664 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9665 return mono_field_get_rva (field);
9672 * mono_property_get_name:
9673 * @prop: the MonoProperty to act on
9675 * Returns: The name of the property
9678 mono_property_get_name (MonoProperty *prop)
9684 * mono_property_get_set_method
9685 * @prop: the MonoProperty to act on.
9687 * Returns: The setter method of the property (A MonoMethod)
9690 mono_property_get_set_method (MonoProperty *prop)
9696 * mono_property_get_get_method
9697 * @prop: the MonoProperty to act on.
9699 * Returns: The setter method of the property (A MonoMethod)
9702 mono_property_get_get_method (MonoProperty *prop)
9708 * mono_property_get_parent:
9709 * @prop: the MonoProperty to act on.
9711 * Returns: The MonoClass where the property was defined.
9714 mono_property_get_parent (MonoProperty *prop)
9716 return prop->parent;
9720 * mono_property_get_flags:
9721 * @prop: the MonoProperty to act on.
9723 * The metadata flags for a property are encoded using the
9724 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9726 * Returns: The flags for the property.
9729 mono_property_get_flags (MonoProperty *prop)
9735 * mono_event_get_name:
9736 * @event: the MonoEvent to act on
9738 * Returns: The name of the event.
9741 mono_event_get_name (MonoEvent *event)
9747 * mono_event_get_add_method:
9748 * @event: The MonoEvent to act on.
9750 * Returns: The @add' method for the event (a MonoMethod).
9753 mono_event_get_add_method (MonoEvent *event)
9759 * mono_event_get_remove_method:
9760 * @event: The MonoEvent to act on.
9762 * Returns: The @remove method for the event (a MonoMethod).
9765 mono_event_get_remove_method (MonoEvent *event)
9767 return event->remove;
9771 * mono_event_get_raise_method:
9772 * @event: The MonoEvent to act on.
9774 * Returns: The @raise method for the event (a MonoMethod).
9777 mono_event_get_raise_method (MonoEvent *event)
9779 return event->raise;
9783 * mono_event_get_parent:
9784 * @event: the MonoEvent to act on.
9786 * Returns: The MonoClass where the event is defined.
9789 mono_event_get_parent (MonoEvent *event)
9791 return event->parent;
9795 * mono_event_get_flags
9796 * @event: the MonoEvent to act on.
9798 * The metadata flags for an event are encoded using the
9799 * EVENT_* constants. See the tabledefs.h file for details.
9801 * Returns: The flags for the event.
9804 mono_event_get_flags (MonoEvent *event)
9806 return event->attrs;
9810 * mono_class_get_method_from_name:
9811 * @klass: where to look for the method
9812 * @name: name of the method
9813 * @param_count: number of parameters. -1 for any number.
9815 * Obtains a MonoMethod with a given name and number of parameters.
9816 * It only works if there are no multiple signatures for any given method name.
9819 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9821 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9825 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9827 MonoMethod *res = NULL;
9830 /* Search directly in the metadata to avoid calling setup_methods () */
9831 for (i = 0; i < klass->method.count; ++i) {
9833 guint32 cols [MONO_METHOD_SIZE];
9835 MonoMethodSignature *sig;
9837 /* klass->method.first points into the methodptr table */
9838 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9840 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9841 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9843 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9846 if (param_count == -1) {
9850 sig = mono_method_signature_checked (method, &error);
9852 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9855 if (sig->param_count == param_count) {
9866 * mono_class_get_method_from_name_flags:
9867 * @klass: where to look for the method
9868 * @name_space: name of the method
9869 * @param_count: number of parameters. -1 for any number.
9870 * @flags: flags which must be set in the method
9872 * Obtains a MonoMethod with a given name and number of parameters.
9873 * It only works if there are no multiple signatures for any given method name.
9876 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9878 MonoMethod *res = NULL;
9881 mono_class_init (klass);
9883 if (mono_class_is_ginst (klass) && !klass->methods) {
9884 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9887 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9888 if (!mono_error_ok (&error))
9889 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9894 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9895 mono_class_setup_methods (klass);
9897 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9898 See mono/tests/array_load_exception.il
9899 FIXME we should better report this error to the caller
9901 if (!klass->methods)
9903 for (i = 0; i < klass->method.count; ++i) {
9904 MonoMethod *method = klass->methods [i];
9906 if (method->name[0] == name [0] &&
9907 !strcmp (name, method->name) &&
9908 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9909 ((method->flags & flags) == flags)) {
9916 res = find_method_in_metadata (klass, name, param_count, flags);
9923 * mono_class_set_failure:
9924 * @klass: class in which the failure was detected
9925 * @ex_type: the kind of exception/error to be thrown (later)
9926 * @ex_data: exception data (specific to each type of exception/error)
9928 * Keep a detected failure informations in the class for later processing.
9929 * Note that only the first failure is kept.
9931 * LOCKING: Acquires the loader lock.
9934 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9936 g_assert (boxed_error != NULL);
9938 if (mono_class_has_failure (klass))
9941 mono_loader_lock ();
9942 klass->has_failure = 1;
9943 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9944 mono_loader_unlock ();
9950 mono_class_has_failure (const MonoClass *klass)
9952 g_assert (klass != NULL);
9953 return klass->has_failure != 0;
9958 * mono_class_set_type_load_failure:
9959 * @klass: class in which the failure was detected
9960 * @fmt: Printf-style error message string.
9962 * Collect detected failure informaion in the class for later processing.
9963 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9964 * Note that only the first failure is kept.
9966 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9968 * LOCKING: Acquires the loader lock.
9971 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9973 MonoError prepare_error;
9976 if (mono_class_has_failure (klass))
9979 mono_error_init (&prepare_error);
9981 va_start (args, fmt);
9982 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9985 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9986 mono_error_cleanup (&prepare_error);
9987 return mono_class_set_failure (klass, box);
9991 * mono_class_get_exception_data:
9993 * Return the exception_data property of KLASS.
9995 * LOCKING: Acquires the loader lock.
9998 mono_class_get_exception_data (const MonoClass *klass)
10000 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
10004 * mono_classes_init:
10006 * Initialize the resources used by this module.
10009 mono_classes_init (void)
10011 mono_os_mutex_init (&classes_mutex);
10013 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10014 mono_native_tls_alloc (&init_pending_tls_id, NULL);
10016 mono_counters_register ("Inflated methods size",
10017 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10018 mono_counters_register ("Inflated classes",
10019 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
10020 mono_counters_register ("Inflated classes size",
10021 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10022 mono_counters_register ("MonoClass size",
10023 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10024 mono_counters_register ("MonoClassExt size",
10025 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10029 * mono_classes_cleanup:
10031 * Free the resources used by this module.
10034 mono_classes_cleanup (void)
10036 mono_native_tls_free (setup_fields_tls_id);
10037 mono_native_tls_free (init_pending_tls_id);
10039 if (global_interface_bitset)
10040 mono_bitset_free (global_interface_bitset);
10041 global_interface_bitset = NULL;
10042 mono_os_mutex_destroy (&classes_mutex);
10046 * mono_class_get_exception_for_failure:
10047 * @klass: class in which the failure was detected
10049 * Return a constructed MonoException than the caller can then throw
10050 * using mono_raise_exception - or NULL if no failure is present (or
10051 * doesn't result in an exception).
10054 mono_class_get_exception_for_failure (MonoClass *klass)
10056 if (!mono_class_has_failure (klass))
10058 MonoError unboxed_error;
10059 mono_error_init (&unboxed_error);
10060 mono_error_set_for_class_failure (&unboxed_error, klass);
10061 return mono_error_convert_to_exception (&unboxed_error);
10065 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10067 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10068 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10070 if (outer_klass == inner_klass)
10072 inner_klass = inner_klass->nested_in;
10073 } while (inner_klass);
10078 mono_class_get_generic_type_definition (MonoClass *klass)
10080 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10081 return gklass ? gklass->container_class : klass;
10085 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10087 * Generic instantiations are ignored for all super types of @klass.
10089 * Visibility checks ignoring generic instantiations.
10092 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10095 klass = mono_class_get_generic_type_definition (klass);
10096 parent = mono_class_get_generic_type_definition (parent);
10097 mono_class_setup_supertypes (klass);
10099 for (i = 0; i < klass->idepth; ++i) {
10100 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10106 * Subtype can only access parent members with family protection if the site object
10107 * is subclass of Subtype. For example:
10108 * class A { protected int x; }
10110 * void valid_access () {
10114 * void invalid_access () {
10121 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10123 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10126 if (context_klass == NULL)
10128 /*if access_klass is not member_klass context_klass must be type compat*/
10129 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10135 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10138 if (accessing == accessed)
10140 if (!accessed || !accessing)
10143 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10144 * anywhere so untrusted friends are not safe to access platform's code internals */
10145 if (mono_security_core_clr_enabled ()) {
10146 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10150 mono_assembly_load_friends (accessed);
10151 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10152 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10153 /* Be conservative with checks */
10154 if (!friend_->name)
10156 if (strcmp (accessing->aname.name, friend_->name))
10158 if (friend_->public_key_token [0]) {
10159 if (!accessing->aname.public_key_token [0])
10161 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10170 * If klass is a generic type or if it is derived from a generic type, return the
10171 * MonoClass of the generic definition
10172 * Returns NULL if not found
10175 get_generic_definition_class (MonoClass *klass)
10178 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10179 if (gklass && gklass->container_class)
10180 return gklass->container_class;
10181 klass = klass->parent;
10187 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10190 for (i = 0; i < ginst->type_argc; ++i) {
10191 MonoType *type = ginst->type_argv[i];
10192 switch (type->type) {
10193 case MONO_TYPE_SZARRAY:
10194 if (!can_access_type (access_klass, type->data.klass))
10197 case MONO_TYPE_ARRAY:
10198 if (!can_access_type (access_klass, type->data.array->eklass))
10201 case MONO_TYPE_PTR:
10202 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10205 case MONO_TYPE_CLASS:
10206 case MONO_TYPE_VALUETYPE:
10207 case MONO_TYPE_GENERICINST:
10208 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10218 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10222 if (access_klass == member_klass)
10225 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10228 if (access_klass->element_class && !access_klass->enumtype)
10229 access_klass = access_klass->element_class;
10231 if (member_klass->element_class && !member_klass->enumtype)
10232 member_klass = member_klass->element_class;
10234 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10236 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10239 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10242 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10245 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10248 /*Non nested type with nested visibility. We just fail it.*/
10249 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10252 switch (access_level) {
10253 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10254 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10256 case TYPE_ATTRIBUTE_PUBLIC:
10259 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10262 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10263 return is_nesting_type (member_klass, access_klass);
10265 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10266 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10268 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10269 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10271 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10272 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10273 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10275 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10276 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10277 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10282 /* FIXME: check visibility of type, too */
10284 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10286 MonoClass *member_generic_def;
10287 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10290 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10291 if (((access_gklass && access_gklass->container_class) ||
10292 access_klass->generic_container) &&
10293 (member_generic_def = get_generic_definition_class (member_klass))) {
10294 MonoClass *access_container;
10296 if (access_klass->generic_container)
10297 access_container = access_klass;
10299 access_container = access_gklass->container_class;
10301 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10305 /* Partition I 8.5.3.2 */
10306 /* the access level values are the same for fields and methods */
10307 switch (access_level) {
10308 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10309 /* same compilation unit */
10310 return access_klass->image == member_klass->image;
10311 case FIELD_ATTRIBUTE_PRIVATE:
10312 return access_klass == member_klass;
10313 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10314 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10315 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10318 case FIELD_ATTRIBUTE_ASSEMBLY:
10319 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10320 case FIELD_ATTRIBUTE_FAMILY:
10321 if (is_valid_family_access (access_klass, member_klass, context_klass))
10324 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10325 if (is_valid_family_access (access_klass, member_klass, context_klass))
10327 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10328 case FIELD_ATTRIBUTE_PUBLIC:
10335 * mono_method_can_access_field:
10336 * @method: Method that will attempt to access the field
10337 * @field: the field to access
10339 * Used to determine if a method is allowed to access the specified field.
10341 * Returns: TRUE if the given @method is allowed to access the @field while following
10342 * the accessibility rules of the CLI.
10345 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10347 /* FIXME: check all overlapping fields */
10348 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10350 MonoClass *nested = method->klass->nested_in;
10352 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10355 nested = nested->nested_in;
10362 * mono_method_can_access_method:
10363 * @method: Method that will attempt to access the other method
10364 * @called: the method that we want to probe for accessibility.
10366 * Used to determine if the @method is allowed to access the specified @called method.
10368 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10369 * the accessibility rules of the CLI.
10372 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10374 method = mono_method_get_method_definition (method);
10375 called = mono_method_get_method_definition (called);
10376 return mono_method_can_access_method_full (method, called, NULL);
10380 * mono_method_can_access_method_full:
10381 * @method: The caller method
10382 * @called: The called method
10383 * @context_klass: The static type on stack of the owner @called object used
10385 * This function must be used with instance calls, as they have more strict family accessibility.
10386 * It can be used with static methods, but context_klass should be NULL.
10388 * Returns: TRUE if caller have proper visibility and acessibility to @called
10391 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10393 /* Wrappers are except from access checks */
10394 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10397 MonoClass *access_class = method->klass;
10398 MonoClass *member_class = called->klass;
10399 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10401 MonoClass *nested = access_class->nested_in;
10403 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10406 nested = nested->nested_in;
10413 can = can_access_type (access_class, member_class);
10415 MonoClass *nested = access_class->nested_in;
10417 can = can_access_type (nested, member_class);
10420 nested = nested->nested_in;
10427 if (called->is_inflated) {
10428 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10429 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10438 * mono_method_can_access_field_full:
10439 * @method: The caller method
10440 * @field: The accessed field
10441 * @context_klass: The static type on stack of the owner @field object used
10443 * This function must be used with instance fields, as they have more strict family accessibility.
10444 * It can be used with static fields, but context_klass should be NULL.
10446 * Returns: TRUE if caller have proper visibility and acessibility to @field
10449 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10451 MonoClass *access_class = method->klass;
10452 MonoClass *member_class = field->parent;
10453 /* FIXME: check all overlapping fields */
10454 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10456 MonoClass *nested = access_class->nested_in;
10458 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10461 nested = nested->nested_in;
10468 can = can_access_type (access_class, member_class);
10470 MonoClass *nested = access_class->nested_in;
10472 can = can_access_type (nested, member_class);
10475 nested = nested->nested_in;
10485 * mono_class_can_access_class:
10486 * @source_class: The source class
10487 * @target_class: The accessed class
10489 * This function returns is @target_class is visible to @source_class
10491 * Returns: TRUE if source have proper visibility and acessibility to target
10494 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10496 return can_access_type (source_class, target_class);
10500 * mono_type_is_valid_enum_basetype:
10501 * @type: The MonoType to check
10503 * Returns: TRUE if the type can be used as the basetype of an enum
10505 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10506 switch (type->type) {
10509 case MONO_TYPE_BOOLEAN:
10512 case MONO_TYPE_CHAR:
10526 * mono_class_is_valid_enum:
10527 * @klass: An enum class to be validated
10529 * This method verify the required properties an enum should have.
10531 * Returns: TRUE if the informed enum class is valid
10533 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10534 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10535 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10537 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10538 MonoClassField * field;
10539 gpointer iter = NULL;
10540 gboolean found_base_field = FALSE;
10542 g_assert (klass->enumtype);
10543 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10544 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10548 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10551 while ((field = mono_class_get_fields (klass, &iter))) {
10552 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10553 if (found_base_field)
10555 found_base_field = TRUE;
10556 if (!mono_type_is_valid_enum_basetype (field->type))
10561 if (!found_base_field)
10564 if (klass->method.count > 0)
10571 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10573 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10577 * mono_class_setup_interface_id:
10579 * Initializes MonoClass::interface_id if required.
10581 * LOCKING: Acquires the loader lock.
10584 mono_class_setup_interface_id (MonoClass *klass)
10586 mono_loader_lock ();
10587 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10588 klass->interface_id = mono_get_unique_iid (klass);
10589 mono_loader_unlock ();
10593 * mono_class_alloc_ext:
10595 * Allocate klass->ext if not already done.
10598 mono_class_alloc_ext (MonoClass *klass)
10605 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10606 mono_image_lock (klass->image);
10607 mono_memory_barrier ();
10610 class_ext_size += sizeof (MonoClassExt);
10611 mono_image_unlock (klass->image);
10615 * mono_class_setup_interfaces:
10617 * Initialize klass->interfaces/interfaces_count.
10618 * LOCKING: Acquires the loader lock.
10619 * This function can fail the type.
10622 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10624 int i, interface_count;
10625 MonoClass **interfaces;
10627 mono_error_init (error);
10629 if (klass->interfaces_inited)
10632 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10633 MonoType *args [1];
10635 /* generic IList, ICollection, IEnumerable */
10636 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10637 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10639 args [0] = &klass->element_class->byval_arg;
10640 interfaces [0] = mono_class_bind_generic_parameters (
10641 mono_defaults.generic_ilist_class, 1, args, FALSE);
10642 if (interface_count > 1)
10643 interfaces [1] = mono_class_bind_generic_parameters (
10644 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10645 } else if (mono_class_is_ginst (klass)) {
10646 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10648 mono_class_setup_interfaces (gklass, error);
10649 if (!mono_error_ok (error)) {
10650 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10654 interface_count = gklass->interface_count;
10655 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10656 for (i = 0; i < interface_count; i++) {
10657 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10658 if (!mono_error_ok (error)) {
10659 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10664 interface_count = 0;
10668 mono_image_lock (klass->image);
10670 if (!klass->interfaces_inited) {
10671 klass->interface_count = interface_count;
10672 klass->interfaces = interfaces;
10674 mono_memory_barrier ();
10676 klass->interfaces_inited = TRUE;
10679 mono_image_unlock (klass->image);
10683 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10685 MonoClass *klass = field->parent;
10686 MonoImage *image = klass->image;
10687 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10688 int field_idx = field - klass->fields;
10690 mono_error_init (error);
10693 MonoClassField *gfield = >d->fields [field_idx];
10694 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10695 if (!mono_error_ok (error)) {
10696 char *full_name = mono_type_get_full_name (gtd);
10697 mono_class_set_type_load_failure (klass, "Could not load generic type of field '%s:%s' (%d) due to: %s", full_name, gfield->name, field_idx, mono_error_get_message (error));
10698 g_free (full_name);
10701 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10702 if (!mono_error_ok (error)) {
10703 char *full_name = mono_type_get_full_name (klass);
10704 mono_class_set_type_load_failure (klass, "Could not load instantiated type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10705 g_free (full_name);
10709 guint32 cols [MONO_FIELD_SIZE];
10710 MonoGenericContainer *container = NULL;
10711 int idx = klass->field.first + field_idx;
10713 /*FIXME, in theory we do not lazy load SRE fields*/
10714 g_assert (!image_is_dynamic (image));
10716 if (klass->generic_container) {
10717 container = klass->generic_container;
10719 container = gtd->generic_container;
10720 g_assert (container);
10723 /* klass->field.first and idx points into the fieldptr table */
10724 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10726 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10727 char *full_name = mono_type_get_full_name (klass);
10728 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10729 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10730 g_free (full_name);
10734 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10736 mono_metadata_decode_value (sig, &sig);
10737 /* FIELD signature == 0x06 */
10738 g_assert (*sig == 0x06);
10740 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10741 if (!field->type) {
10742 char *full_name = mono_type_get_full_name (klass);
10743 mono_class_set_type_load_failure (klass, "Could not load type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10744 g_free (full_name);
10750 mono_field_resolve_flags (MonoClassField *field)
10752 MonoClass *klass = field->parent;
10753 MonoImage *image = klass->image;
10754 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10755 int field_idx = field - klass->fields;
10759 MonoClassField *gfield = >d->fields [field_idx];
10760 return mono_field_get_flags (gfield);
10762 int idx = klass->field.first + field_idx;
10764 /*FIXME, in theory we do not lazy load SRE fields*/
10765 g_assert (!image_is_dynamic (image));
10767 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10772 * mono_class_get_fields_lazy:
10773 * @klass: the MonoClass to act on
10775 * This routine is an iterator routine for retrieving the fields in a class.
10776 * Only minimal information about fields are loaded. Accessors must be used
10777 * for all MonoClassField returned.
10779 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10780 * iterate over all of the elements. When no more values are
10781 * available, the return value is NULL.
10783 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10786 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10788 MonoClassField* field;
10792 mono_class_setup_basic_field_info (klass);
10793 if (!klass->fields)
10795 /* start from the first */
10796 if (klass->field.count) {
10797 *iter = &klass->fields [0];
10798 return (MonoClassField *)*iter;
10804 field = (MonoClassField *)*iter;
10806 if (field < &klass->fields [klass->field.count]) {
10808 return (MonoClassField *)*iter;
10814 mono_class_full_name (MonoClass *klass)
10816 return mono_type_full_name (&klass->byval_arg);
10819 /* Declare all shared lazy type lookup functions */
10820 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)