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_size, inflated_methods_size;
58 guint32 classes_size, class_ext_size, class_ext_count;
59 guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
61 /* Low level lock which protects data structures in this module */
62 static mono_mutex_t classes_mutex;
64 /* Function supplied by the runtime to find classes by name using information from the AOT file */
65 static MonoGetClassFromName get_class_from_name = NULL;
67 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
68 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
69 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
70 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
71 static int generic_array_methods (MonoClass *klass);
72 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
74 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
75 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
76 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
77 static guint32 mono_field_resolve_flags (MonoClassField *field);
78 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
79 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
81 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
82 static gpointer mono_class_get_exception_data (const MonoClass *klass);
86 We use gclass recording to allow recursive system f types to be referenced by a parent.
88 Given the following type hierarchy:
90 class TextBox : TextBoxBase<TextBox> {}
91 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
92 class TextInput<T> : Input<T> where T: TextInput<T> {}
95 The runtime tries to load TextBoxBase<>.
96 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
97 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
98 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
100 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
101 at this point, iow, both are registered in the type map and both and a NULL parent. This means
102 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
104 To fix that what we do is to record all generic instantes created while resolving the parent of
105 any generic type definition and, after resolved, correct the parent field if needed.
108 static int record_gclass_instantiation;
109 static GSList *gclass_recorded_list;
110 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
112 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
113 static MonoNativeTlsKey setup_fields_tls_id;
115 static MonoNativeTlsKey init_pending_tls_id;
120 mono_locks_os_acquire (&classes_mutex, ClassesLock);
124 classes_unlock (void)
126 mono_locks_os_release (&classes_mutex, ClassesLock);
130 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
133 enable_gclass_recording (void)
135 ++record_gclass_instantiation;
139 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
142 disable_gclass_recording (gclass_record_func func, void *user_data)
144 GSList **head = &gclass_recorded_list;
146 g_assert (record_gclass_instantiation > 0);
147 --record_gclass_instantiation;
150 GSList *node = *head;
151 if (func ((MonoClass*)node->data, user_data)) {
153 g_slist_free_1 (node);
159 /* We automatically discard all recorded gclasses when disabled. */
160 if (!record_gclass_instantiation && gclass_recorded_list) {
161 g_slist_free (gclass_recorded_list);
162 gclass_recorded_list = NULL;
167 * mono_class_from_typeref:
168 * @image: a MonoImage
169 * @type_token: a TypeRef token
171 * Creates the MonoClass* structure representing the type defined by
172 * the typeref token valid inside @image.
173 * Returns: The MonoClass* representing the typeref token, NULL ifcould
177 mono_class_from_typeref (MonoImage *image, guint32 type_token)
180 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
181 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
186 * mono_class_from_typeref_checked:
187 * @image: a MonoImage
188 * @type_token: a TypeRef token
189 * @error: error return code, if any.
191 * Creates the MonoClass* structure representing the type defined by
192 * the typeref token valid inside @image.
194 * Returns: The MonoClass* representing the typeref token, NULL if it could
195 * not be loaded with the @error value filled with the information about the
199 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
201 guint32 cols [MONO_TYPEREF_SIZE];
202 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
204 const char *name, *nspace;
205 MonoClass *res = NULL;
208 mono_error_init (error);
210 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
213 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
215 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
216 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
218 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
219 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
220 case MONO_RESOLUTION_SCOPE_MODULE:
222 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
223 This is not the observed behavior of existing implementations.
224 The defacto behavior is that it's just a typedef in disguise.
226 /* a typedef in disguise */
227 res = mono_class_from_name_checked (image, nspace, name, error);
230 case MONO_RESOLUTION_SCOPE_MODULEREF:
231 module = mono_image_load_module_checked (image, idx, error);
233 res = mono_class_from_name_checked (module, nspace, name, error);
236 case MONO_RESOLUTION_SCOPE_TYPEREF: {
237 MonoClass *enclosing;
240 if (idx == mono_metadata_token_index (type_token)) {
241 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
245 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
246 return_val_if_nok (error, NULL);
248 if (enclosing->nested_classes_inited && enclosing->ext) {
249 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
250 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
251 res = (MonoClass *)tmp->data;
252 if (strcmp (res->name, name) == 0)
256 /* Don't call mono_class_init as we might've been called by it recursively */
257 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
259 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
260 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
261 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
263 if (strcmp (nname, name) == 0)
264 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
266 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
269 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
272 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
276 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
277 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
281 if (!image->references || !image->references [idx - 1])
282 mono_assembly_load_reference (image, idx - 1);
283 g_assert (image->references [idx - 1]);
285 /* If the assembly did not load, register this as a type load exception */
286 if (image->references [idx - 1] == REFERENCE_MISSING){
287 MonoAssemblyName aname;
290 mono_assembly_get_assemblyref (image, idx - 1, &aname);
291 human_name = mono_stringify_assembly_name (&aname);
292 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
296 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
299 /* Generic case, should be avoided for when a better error is possible. */
300 if (!res && mono_error_ok (error)) {
301 char *name = mono_class_name_from_token (image, type_token);
302 char *assembly = mono_assembly_name_from_token (image, type_token);
303 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
310 mono_image_memdup (MonoImage *image, void *data, guint size)
312 void *res = mono_image_alloc (image, size);
313 memcpy (res, data, size);
317 /* Copy everything mono_metadata_free_array free. */
319 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
322 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
324 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
326 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
328 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
330 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
332 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
337 /* Copy everything mono_metadata_free_method_signature free. */
339 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
343 sig = mono_metadata_signature_dup_full (image, sig);
345 sig->ret = mono_metadata_type_dup (image, sig->ret);
346 for (i = 0; i < sig->param_count; ++i)
347 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
353 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
355 MonoAssembly *ta = klass->image->assembly;
358 name = mono_stringify_assembly_name (&ta->aname);
359 g_string_append_printf (str, ", %s", name);
364 mono_type_name_check_byref (MonoType *type, GString *str)
367 g_string_append_c (str, '&');
371 * mono_identifier_escape_type_name_chars:
372 * @str: a destination string
373 * @identifier: an IDENTIFIER in internal form
377 * The displayed form of the identifier is appended to str.
379 * The displayed form of an identifier has the characters ,+&*[]\
380 * that have special meaning in type names escaped with a preceeding
381 * backslash (\) character.
384 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
390 // reserve space for common case: there will be no escaped characters.
391 g_string_set_size(str, n + strlen(identifier));
392 g_string_set_size(str, n);
394 for (const char* s = identifier; *s != 0 ; s++) {
403 g_string_append_c (str, '\\');
404 g_string_append_c (str, *s);
407 g_string_append_c (str, *s);
415 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
416 MonoTypeNameFormat format)
420 switch (type->type) {
421 case MONO_TYPE_ARRAY: {
422 int i, rank = type->data.array->rank;
423 MonoTypeNameFormat nested_format;
425 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
426 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
428 mono_type_get_name_recurse (
429 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
430 g_string_append_c (str, '[');
432 g_string_append_c (str, '*');
433 for (i = 1; i < rank; i++)
434 g_string_append_c (str, ',');
435 g_string_append_c (str, ']');
437 mono_type_name_check_byref (type, str);
439 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
440 _mono_type_get_assembly_name (type->data.array->eklass, str);
443 case MONO_TYPE_SZARRAY: {
444 MonoTypeNameFormat nested_format;
446 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
447 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
449 mono_type_get_name_recurse (
450 &type->data.klass->byval_arg, str, FALSE, nested_format);
451 g_string_append (str, "[]");
453 mono_type_name_check_byref (type, str);
455 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
456 _mono_type_get_assembly_name (type->data.klass, str);
459 case MONO_TYPE_PTR: {
460 MonoTypeNameFormat nested_format;
462 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
463 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
465 mono_type_get_name_recurse (
466 type->data.type, str, FALSE, nested_format);
467 g_string_append_c (str, '*');
469 mono_type_name_check_byref (type, str);
471 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
472 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
477 if (!mono_generic_param_info (type->data.generic_param))
478 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
480 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
482 mono_type_name_check_byref (type, str);
486 klass = mono_class_from_mono_type (type);
487 if (klass->nested_in) {
488 mono_type_get_name_recurse (
489 &klass->nested_in->byval_arg, str, TRUE, format);
490 if (format == MONO_TYPE_NAME_FORMAT_IL)
491 g_string_append_c (str, '.');
493 g_string_append_c (str, '+');
494 } else if (*klass->name_space) {
495 if (format == MONO_TYPE_NAME_FORMAT_IL)
496 g_string_append (str, klass->name_space);
498 mono_identifier_escape_type_name_chars (str, klass->name_space);
499 g_string_append_c (str, '.');
501 if (format == MONO_TYPE_NAME_FORMAT_IL) {
502 char *s = strchr (klass->name, '`');
503 int len = s ? s - klass->name : strlen (klass->name);
504 g_string_append_len (str, klass->name, len);
506 mono_identifier_escape_type_name_chars (str, klass->name);
510 if (mono_class_is_ginst (klass)) {
511 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
512 MonoGenericInst *inst = gclass->context.class_inst;
513 MonoTypeNameFormat nested_format;
516 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
517 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
519 if (format == MONO_TYPE_NAME_FORMAT_IL)
520 g_string_append_c (str, '<');
522 g_string_append_c (str, '[');
523 for (i = 0; i < inst->type_argc; i++) {
524 MonoType *t = inst->type_argv [i];
527 g_string_append_c (str, ',');
528 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
529 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
530 g_string_append_c (str, '[');
531 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
532 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
533 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
534 g_string_append_c (str, ']');
536 if (format == MONO_TYPE_NAME_FORMAT_IL)
537 g_string_append_c (str, '>');
539 g_string_append_c (str, ']');
540 } else if (mono_class_is_gtd (klass) &&
541 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
542 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
545 if (format == MONO_TYPE_NAME_FORMAT_IL)
546 g_string_append_c (str, '<');
548 g_string_append_c (str, '[');
549 for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
551 g_string_append_c (str, ',');
552 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
554 if (format == MONO_TYPE_NAME_FORMAT_IL)
555 g_string_append_c (str, '>');
557 g_string_append_c (str, ']');
560 mono_type_name_check_byref (type, str);
562 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
563 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
564 _mono_type_get_assembly_name (klass, str);
570 * mono_type_get_name_full:
572 * @format: the format for the return string.
575 * Returns: The string representation in a number of formats:
577 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
578 * returned in the formatrequired by System.Reflection, this is the
579 * inverse of mono_reflection_parse_type ().
581 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
582 * be used by the IL assembler.
584 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
586 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
589 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
593 result = g_string_new ("");
595 mono_type_get_name_recurse (type, result, FALSE, format);
597 return g_string_free (result, FALSE);
601 * mono_type_get_full_name:
604 * Returns: The string representation for type as required by System.Reflection.
605 * The inverse of mono_reflection_parse_type ().
608 mono_type_get_full_name (MonoClass *klass)
610 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
614 * mono_type_get_name:
617 * Returns: The string representation for type as it would be represented in IL code.
620 mono_type_get_name (MonoType *type)
622 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
626 * mono_type_get_underlying_type:
629 * Returns: The MonoType for the underlying integer type if @type
630 * is an enum and byref is false, otherwise the type itself.
633 mono_type_get_underlying_type (MonoType *type)
635 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
636 return mono_class_enum_basetype (type->data.klass);
637 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
638 return mono_class_enum_basetype (type->data.generic_class->container_class);
643 * mono_class_is_open_constructed_type:
646 * Returns: TRUE if type represents a generics open constructed type.
647 * IOW, not all type parameters required for the instantiation have
648 * been provided or it's a generic type definition.
650 * An open constructed type means it's a non realizable type. Not to
651 * be mixed up with an abstract type - we can't cast or dispatch to
652 * an open type, for example.
655 mono_class_is_open_constructed_type (MonoType *t)
661 case MONO_TYPE_SZARRAY:
662 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
663 case MONO_TYPE_ARRAY:
664 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
666 return mono_class_is_open_constructed_type (t->data.type);
667 case MONO_TYPE_GENERICINST:
668 return t->data.generic_class->context.class_inst->is_open;
669 case MONO_TYPE_CLASS:
670 case MONO_TYPE_VALUETYPE:
671 return mono_class_is_gtd (t->data.klass);
678 This is a simple function to catch the most common bad instances of generic types.
679 Specially those that might lead to further failures in the runtime.
682 is_valid_generic_argument (MonoType *type)
684 switch (type->type) {
686 //case MONO_TYPE_TYPEDBYREF:
694 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
696 mono_error_init (error);
698 switch (type->type) {
699 case MONO_TYPE_MVAR: {
701 int num = mono_type_get_generic_param_num (type);
702 MonoGenericInst *inst = context->method_inst;
705 if (num >= inst->type_argc) {
706 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
707 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
708 num, info ? info->name : "", inst->type_argc);
712 if (!is_valid_generic_argument (inst->type_argv [num])) {
713 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
714 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
715 num, info ? info->name : "", inst->type_argv [num]->type);
719 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
720 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
721 * ->byref and ->attrs from @type are propagated to the returned type.
723 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
724 nt->byref = type->byref;
725 nt->attrs = type->attrs;
728 case MONO_TYPE_VAR: {
730 int num = mono_type_get_generic_param_num (type);
731 MonoGenericInst *inst = context->class_inst;
734 if (num >= inst->type_argc) {
735 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
736 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
737 num, info ? info->name : "", inst->type_argc);
740 if (!is_valid_generic_argument (inst->type_argv [num])) {
741 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
742 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
743 num, info ? info->name : "", inst->type_argv [num]->type);
746 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
747 nt->byref = type->byref;
748 nt->attrs = type->attrs;
751 case MONO_TYPE_SZARRAY: {
752 MonoClass *eclass = type->data.klass;
753 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
754 if (!inflated || !mono_error_ok (error))
756 nt = mono_metadata_type_dup (image, type);
757 nt->data.klass = mono_class_from_mono_type (inflated);
758 mono_metadata_free_type (inflated);
761 case MONO_TYPE_ARRAY: {
762 MonoClass *eclass = type->data.array->eklass;
763 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
764 if (!inflated || !mono_error_ok (error))
766 nt = mono_metadata_type_dup (image, type);
767 nt->data.array->eklass = mono_class_from_mono_type (inflated);
768 mono_metadata_free_type (inflated);
771 case MONO_TYPE_GENERICINST: {
772 MonoGenericClass *gclass = type->data.generic_class;
773 MonoGenericInst *inst;
775 if (!gclass->context.class_inst->is_open)
778 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
779 return_val_if_nok (error, NULL);
781 if (inst != gclass->context.class_inst)
782 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
784 if (gclass == type->data.generic_class)
787 nt = mono_metadata_type_dup (image, type);
788 nt->data.generic_class = gclass;
791 case MONO_TYPE_CLASS:
792 case MONO_TYPE_VALUETYPE: {
793 MonoClass *klass = type->data.klass;
794 MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
795 MonoGenericInst *inst;
796 MonoGenericClass *gclass = NULL;
802 /* We can't use context->class_inst directly, since it can have more elements */
803 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
804 return_val_if_nok (error, NULL);
806 if (inst == container->context.class_inst)
809 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
811 nt = mono_metadata_type_dup (image, type);
812 nt->type = MONO_TYPE_GENERICINST;
813 nt->data.generic_class = gclass;
823 mono_generic_class_get_context (MonoGenericClass *gclass)
825 return &gclass->context;
829 mono_class_get_context (MonoClass *klass)
831 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
832 return gklass ? mono_generic_class_get_context (gklass) : NULL;
836 * mono_class_inflate_generic_type_with_mempool:
837 * @mempool: a mempool
839 * @context: a generics context
840 * @error: error context
842 * The same as mono_class_inflate_generic_type, but allocates the MonoType
843 * from mempool if it is non-NULL. If it is NULL, the MonoType is
844 * allocated on the heap and is owned by the caller.
845 * The returned type can potentially be the same as TYPE, so it should not be
846 * modified by the caller, and it should be freed using mono_metadata_free_type ().
849 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
851 MonoType *inflated = NULL;
852 mono_error_init (error);
855 inflated = inflate_generic_type (image, type, context, error);
856 return_val_if_nok (error, NULL);
859 MonoType *shared = mono_metadata_get_shared_type (type);
864 return mono_metadata_type_dup (image, type);
868 mono_stats.inflated_type_count++;
873 * mono_class_inflate_generic_type:
875 * @context: a generics context
877 * If @type is a generic type and @context is not NULL, instantiate it using the
878 * generics context @context.
880 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
881 * on the heap and is owned by the caller. Returns NULL on error.
883 * @deprecated Please use mono_class_inflate_generic_type_checked instead
886 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
890 result = mono_class_inflate_generic_type_checked (type, context, &error);
891 mono_error_cleanup (&error);
896 * mono_class_inflate_generic_type:
898 * @context: a generics context
899 * @error: error context to use
901 * If @type is a generic type and @context is not NULL, instantiate it using the
902 * generics context @context.
904 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
905 * on the heap and is owned by the caller.
908 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
910 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
914 * mono_class_inflate_generic_type_no_copy:
916 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
920 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
922 MonoType *inflated = NULL;
924 mono_error_init (error);
926 inflated = inflate_generic_type (image, type, context, error);
927 return_val_if_nok (error, NULL);
933 mono_stats.inflated_type_count++;
938 * mono_class_inflate_generic_class:
940 * Inflate the class @gklass with @context. Set @error on failure.
943 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
948 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
949 return_val_if_nok (error, NULL);
951 res = mono_class_from_mono_type (inflated);
952 mono_metadata_free_type (inflated);
957 static MonoGenericContext
958 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
960 MonoGenericInst *class_inst = NULL;
961 MonoGenericInst *method_inst = NULL;
962 MonoGenericContext res = { NULL, NULL };
964 mono_error_init (error);
966 if (context->class_inst) {
967 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
968 if (!mono_error_ok (error))
972 if (context->method_inst) {
973 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
974 if (!mono_error_ok (error))
978 res.class_inst = class_inst;
979 res.method_inst = method_inst;
985 * mono_class_inflate_generic_method:
986 * @method: a generic method
987 * @context: a generics context
989 * Instantiate the generic method @method using the generics context @context.
991 * Returns: The new instantiated method
994 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
996 return mono_class_inflate_generic_method_full (method, NULL, context);
1000 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1002 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1006 * mono_class_inflate_generic_method_full:
1008 * Instantiate method @method with the generic context @context.
1009 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1010 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1013 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1016 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1017 if (!mono_error_ok (&error))
1018 /*FIXME do proper error handling - on this case, kill this function. */
1019 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1025 * mono_class_inflate_generic_method_full_checked:
1026 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1029 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1032 MonoMethodInflated *iresult, *cached;
1033 MonoMethodSignature *sig;
1034 MonoGenericContext tmp_context;
1036 mono_error_init (error);
1038 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1039 while (method->is_inflated) {
1040 MonoGenericContext *method_context = mono_method_get_context (method);
1041 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1043 tmp_context = inflate_generic_context (method_context, context, error);
1044 return_val_if_nok (error, NULL);
1046 context = &tmp_context;
1048 if (mono_metadata_generic_context_equal (method_context, context))
1051 method = imethod->declaring;
1055 * A method only needs to be inflated if the context has argument for which it is
1058 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1059 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1062 if (!((method->is_generic && context->method_inst) ||
1063 (mono_class_is_gtd (method->klass) && context->class_inst)))
1066 iresult = g_new0 (MonoMethodInflated, 1);
1067 iresult->context = *context;
1068 iresult->declaring = method;
1070 if (!context->method_inst && method->is_generic)
1071 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1073 if (!context->class_inst) {
1074 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1075 if (mono_class_is_gtd (iresult->declaring->klass))
1076 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1078 /* This can happen with some callers like mono_object_get_virtual_method () */
1079 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1080 iresult->context.class_inst = NULL;
1082 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1085 mono_image_set_lock (set);
1086 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1087 mono_image_set_unlock (set);
1091 return (MonoMethod*)cached;
1094 mono_stats.inflated_method_count++;
1096 inflated_methods_size += sizeof (MonoMethodInflated);
1098 sig = mono_method_signature (method);
1100 char *name = mono_type_get_full_name (method->klass);
1101 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1107 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1109 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1112 result = (MonoMethod *) iresult;
1113 result->is_inflated = TRUE;
1114 result->is_generic = FALSE;
1115 result->sre_method = FALSE;
1116 result->signature = NULL;
1118 if (method->wrapper_type) {
1119 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1120 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1121 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1123 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1124 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1127 if (iresult->context.method_inst) {
1128 /* Set the generic_container of the result to the generic_container of method */
1129 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1131 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1132 result->is_generic = 1;
1133 mono_method_set_generic_container (result, generic_container);
1138 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1139 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1143 if (mono_class_is_gtd (method->klass))
1144 result->klass = klass_hint;
1146 if (!result->klass) {
1147 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1148 if (!mono_error_ok (error))
1151 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1153 mono_metadata_free_type (inflated);
1157 * FIXME: This should hold, but it doesn't:
1159 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1160 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1161 * g_assert (result->is_generic);
1164 * Fixing this here causes other things to break, hence a very
1165 * ugly hack in mini-trampolines.c - see
1166 * is_generic_method_definition().
1170 mono_image_set_lock (set);
1171 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1173 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1174 iresult->owner = set;
1177 mono_image_set_unlock (set);
1179 return (MonoMethod*)cached;
1187 * mono_get_inflated_method:
1189 * Obsolete. We keep it around since it's mentioned in the public API.
1192 mono_get_inflated_method (MonoMethod *method)
1198 * mono_method_get_context_general:
1200 * @uninflated: handle uninflated methods?
1202 * Returns the generic context of a method or NULL if it doesn't have
1203 * one. For an inflated method that's the context stored in the
1204 * method. Otherwise it's in the method's generic container or in the
1205 * generic container of the method's class.
1208 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1210 if (method->is_inflated) {
1211 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1212 return &imethod->context;
1216 if (method->is_generic)
1217 return &(mono_method_get_generic_container (method)->context);
1218 if (mono_class_is_gtd (method->klass))
1219 return &mono_class_get_generic_container (method->klass)->context;
1224 * mono_method_get_context:
1227 * Returns the generic context for method if it's inflated, otherwise
1231 mono_method_get_context (MonoMethod *method)
1233 return mono_method_get_context_general (method, FALSE);
1237 * mono_method_get_generic_container:
1239 * Returns the generic container of METHOD, which should be a generic method definition.
1240 * Returns NULL if METHOD is not a generic method definition.
1241 * LOCKING: Acquires the loader lock.
1243 MonoGenericContainer*
1244 mono_method_get_generic_container (MonoMethod *method)
1246 MonoGenericContainer *container;
1248 if (!method->is_generic)
1251 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1252 g_assert (container);
1258 * mono_method_set_generic_container:
1260 * Sets the generic container of METHOD to CONTAINER.
1261 * LOCKING: Acquires the image lock.
1264 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1266 g_assert (method->is_generic);
1268 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1272 * mono_class_find_enum_basetype:
1273 * @class: The enum class
1275 * Determine the basetype of an enum by iterating through its fields. We do this
1276 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1279 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1281 MonoGenericContainer *container = NULL;
1282 MonoImage *m = klass->image;
1283 const int top = klass->field.count;
1286 g_assert (klass->enumtype);
1288 mono_error_init (error);
1290 container = mono_class_try_get_generic_container (klass);
1291 if (mono_class_is_ginst (klass)) {
1292 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1294 container = mono_class_get_generic_container (gklass);
1295 g_assert (container);
1299 * Fetch all the field information.
1301 for (i = 0; i < top; i++){
1303 guint32 cols [MONO_FIELD_SIZE];
1304 int idx = klass->field.first + i;
1307 /* klass->field.first and idx points into the fieldptr table */
1308 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1310 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1313 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1314 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1318 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1319 mono_metadata_decode_value (sig, &sig);
1320 /* FIELD signature == 0x06 */
1322 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1326 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1330 if (mono_class_is_ginst (klass)) {
1331 //FIXME do we leak here?
1332 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1333 if (!mono_error_ok (error))
1335 ftype->attrs = cols [MONO_FIELD_FLAGS];
1340 mono_error_set_type_load_class (error, klass, "Could not find base type");
1347 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1350 mono_type_has_exceptions (MonoType *type)
1352 switch (type->type) {
1353 case MONO_TYPE_CLASS:
1354 case MONO_TYPE_VALUETYPE:
1355 case MONO_TYPE_SZARRAY:
1356 return mono_class_has_failure (type->data.klass);
1357 case MONO_TYPE_ARRAY:
1358 return mono_class_has_failure (type->data.array->eklass);
1359 case MONO_TYPE_GENERICINST:
1360 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1367 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1369 g_assert (mono_class_has_failure (klass));
1370 MonoErrorBoxed *box = (MonoErrorBoxed*)mono_class_get_exception_data (klass);
1371 mono_error_set_from_boxed (oerror, box);
1378 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1382 mono_class_alloc (MonoClass *klass, int size)
1384 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1386 return mono_image_set_alloc (gklass->owner, size);
1388 return mono_image_alloc (klass->image, size);
1392 mono_class_alloc0 (MonoClass *klass, int size)
1396 res = mono_class_alloc (klass, size);
1397 memset (res, 0, size);
1401 #define mono_class_new0(klass,struct_type, n_structs) \
1402 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1405 * mono_class_setup_basic_field_info:
1406 * @class: The class to initialize
1408 * Initializes the following fields in MonoClass:
1409 * * klass->fields (only field->parent and field->name)
1410 * * klass->field.count
1411 * * klass->field.first
1412 * LOCKING: Acquires the loader lock
1415 mono_class_setup_basic_field_info (MonoClass *klass)
1417 MonoGenericClass *gklass;
1418 MonoClassField *field;
1419 MonoClassField *fields;
1427 gklass = mono_class_try_get_generic_class (klass);
1428 gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1429 image = klass->image;
1432 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1434 * This happens when a generic instance of an unfinished generic typebuilder
1435 * is used as an element type for creating an array type. We can't initialize
1436 * the fields of this class using the fields of gklass, since gklass is not
1437 * finished yet, fields could be added to it later.
1443 mono_class_setup_basic_field_info (gtd);
1445 mono_loader_lock ();
1446 klass->field.first = gtd->field.first;
1447 klass->field.count = gtd->field.count;
1448 mono_loader_unlock ();
1451 top = klass->field.count;
1453 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1456 * Fetch all the field information.
1458 for (i = 0; i < top; i++){
1459 field = &fields [i];
1460 field->parent = klass;
1463 field->name = mono_field_get_name (>d->fields [i]);
1465 int idx = klass->field.first + i;
1466 /* klass->field.first and idx points into the fieldptr table */
1467 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1468 /* The name is needed for fieldrefs */
1469 field->name = mono_metadata_string_heap (image, name_idx);
1473 mono_memory_barrier ();
1475 mono_loader_lock ();
1477 klass->fields = fields;
1478 mono_loader_unlock ();
1482 * mono_class_set_failure_causedby_class:
1483 * @klass: the class that is failing
1484 * @caused_by: the class that caused the failure
1485 * @msg: Why @klass is failing.
1487 * If @caused_by has a failure, sets a TypeLoadException failure on
1488 * @klass with message "@msg, due to: {@caused_by message}".
1490 * Returns: TRUE if a failiure was set, or FALSE if @caused_by doesn't have a failure.
1493 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1495 if (mono_class_has_failure (caused_by)) {
1496 MonoError cause_error;
1497 mono_error_init (&cause_error);
1498 mono_error_set_for_class_failure (&cause_error, caused_by);
1499 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1500 mono_error_cleanup (&cause_error);
1509 * mono_class_setup_fields:
1510 * @klass: The class to initialize
1512 * Initializes klass->fields, computes class layout and sizes.
1513 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1514 * Sets the following fields in @klass:
1515 * - all the fields initialized by mono_class_init_sizes ()
1516 * - element_class/cast_class (for enums)
1517 * - field->type/offset for all fields
1520 * LOCKING: Acquires the loader lock.
1523 mono_class_setup_fields (MonoClass *klass)
1526 MonoImage *m = klass->image;
1528 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1530 guint32 real_size = 0;
1531 guint32 packing_size = 0;
1533 gboolean explicit_size;
1534 MonoClassField *field;
1535 MonoGenericContainer *container = NULL;
1536 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1537 MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1539 if (klass->fields_inited)
1542 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1544 * This happens when a generic instance of an unfinished generic typebuilder
1545 * is used as an element type for creating an array type. We can't initialize
1546 * the fields of this class using the fields of gklass, since gklass is not
1547 * finished yet, fields could be added to it later.
1552 mono_class_setup_basic_field_info (klass);
1553 top = klass->field.count;
1555 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1557 mono_class_setup_fields (gtd);
1558 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1563 if (klass->parent) {
1564 /* For generic instances, klass->parent might not have been initialized */
1565 mono_class_init (klass->parent);
1566 mono_class_setup_fields (klass->parent);
1567 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1569 instance_size = klass->parent->instance_size;
1571 instance_size = sizeof (MonoObject);
1574 /* Get the real size */
1575 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1577 instance_size += real_size;
1580 * This function can recursively call itself.
1581 * Prevent infinite recursion by using a list in TLS.
1583 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1584 if (g_slist_find (init_list, klass))
1586 init_list = g_slist_prepend (init_list, klass);
1587 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1590 * Fetch all the field information.
1592 for (i = 0; i < top; i++) {
1593 int idx = klass->field.first + i;
1594 field = &klass->fields [i];
1597 mono_field_resolve_type (field, &error);
1598 if (!mono_error_ok (&error)) {
1599 /*mono_field_resolve_type already failed class*/
1600 mono_error_cleanup (&error);
1604 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1605 g_assert (field->type);
1608 if (mono_field_is_deleted (field))
1610 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1612 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1613 int offset = uoffset;
1615 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1616 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1619 if (offset < -1) { /*-1 is used to encode special static fields */
1620 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1623 if (klass->generic_container) {
1624 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1628 if (mono_type_has_exceptions (field->type)) {
1629 char *class_name = mono_type_get_full_name (klass);
1630 char *type_name = mono_type_full_name (field->type);
1632 mono_class_set_type_load_failure (klass, "");
1633 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1634 g_free (class_name);
1638 /* The def_value of fields is compute lazily during vtable creation */
1641 if (!mono_class_has_failure (klass))
1642 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1644 init_list = g_slist_remove (init_list, klass);
1645 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1649 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1652 klass->instance_size = cached_info->instance_size;
1653 klass->sizes.class_size = cached_info->class_size;
1654 klass->packing_size = cached_info->packing_size;
1655 klass->min_align = cached_info->min_align;
1656 klass->blittable = cached_info->blittable;
1657 klass->has_references = cached_info->has_references;
1658 klass->has_static_refs = cached_info->has_static_refs;
1659 klass->no_special_static_fields = cached_info->no_special_static_fields;
1662 if (!klass->size_inited)
1663 mono_class_setup_fields (klass);
1668 * mono_class_init_sizes:
1670 * Initializes the size related fields of @klass without loading all field data if possible.
1671 * Sets the following fields in @klass:
1673 * - sizes.class_size
1680 * Can fail the class.
1682 * LOCKING: Acquires the loader lock.
1685 mono_class_init_sizes (MonoClass *klass)
1687 MonoCachedClassInfo cached_info;
1688 gboolean has_cached_info;
1690 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1692 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1696 * mono_type_get_basic_type_from_generic:
1699 * Returns a closed type corresponding to the possibly open type
1703 mono_type_get_basic_type_from_generic (MonoType *type)
1705 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1706 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1707 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1708 return &mono_defaults.object_class->byval_arg;
1713 class_has_references (MonoClass *klass)
1715 mono_class_init_sizes (klass);
1718 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1719 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1722 return klass->has_references;
1726 type_has_references (MonoClass *klass, MonoType *ftype)
1728 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1730 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1731 MonoGenericParam *gparam = ftype->data.generic_param;
1733 if (gparam->gshared_constraint)
1734 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1740 * mono_class_layout_fields:
1742 * @base_instance_size: base instance size
1745 * This contains the common code for computing the layout of classes and sizes.
1746 * This should only be called from mono_class_setup_fields () and
1747 * typebuilder_setup_fields ().
1749 * LOCKING: Acquires the loader lock
1752 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1755 const int top = klass->field.count;
1756 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1757 guint32 pass, passes, real_size;
1758 gboolean gc_aware_layout = FALSE;
1759 gboolean has_static_fields = FALSE;
1760 gboolean has_references = FALSE;
1761 gboolean has_static_refs = FALSE;
1762 MonoClassField *field;
1764 int instance_size = base_instance_size;
1765 int class_size, min_align;
1769 * We want to avoid doing complicated work inside locks, so we compute all the required
1770 * information and write it to @klass inside a lock.
1772 if (klass->fields_inited)
1775 if ((packing_size & 0xffffff00) != 0) {
1776 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1780 if (klass->parent) {
1781 min_align = klass->parent->min_align;
1782 /* we use | since it may have been set already */
1783 has_references = klass->has_references | klass->parent->has_references;
1787 /* We can't really enable 16 bytes alignment until the GC supports it.
1788 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1789 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1790 Bug #506144 is an example of this issue.
1792 if (klass->simd_type)
1797 * When we do generic sharing we need to have layout
1798 * information for open generic classes (either with a generic
1799 * context containing type variables or with a generic
1800 * container), so we don't return in that case anymore.
1803 if (klass->enumtype) {
1804 for (i = 0; i < top; i++) {
1805 field = &klass->fields [i];
1806 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1807 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1812 if (!mono_class_enum_basetype (klass)) {
1813 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1819 * Enable GC aware auto layout: in this mode, reference
1820 * fields are grouped together inside objects, increasing collector
1822 * Requires that all classes whose layout is known to native code be annotated
1823 * with [StructLayout (LayoutKind.Sequential)]
1824 * Value types have gc_aware_layout disabled by default, as per
1825 * what the default is for other runtimes.
1827 /* corlib is missing [StructLayout] directives in many places */
1828 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1829 if (!klass->valuetype)
1830 gc_aware_layout = TRUE;
1833 /* Compute klass->blittable */
1836 blittable = klass->parent->blittable;
1837 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1839 for (i = 0; i < top; i++) {
1840 field = &klass->fields [i];
1842 if (mono_field_is_deleted (field))
1844 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1847 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1850 MonoClass *field_class = mono_class_from_mono_type (field->type);
1852 mono_class_setup_fields (field_class);
1853 if (mono_class_has_failure (field_class)) {
1854 MonoError field_error;
1855 mono_error_init (&field_error);
1856 mono_error_set_for_class_failure (&field_error, field_class);
1857 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1858 mono_error_cleanup (&field_error);
1862 if (!field_class || !field_class->blittable)
1866 if (klass->enumtype)
1867 blittable = klass->element_class->blittable;
1869 if (mono_class_has_failure (klass))
1871 if (klass == mono_defaults.string_class)
1874 /* Compute klass->has_references */
1876 * Process non-static fields first, since static fields might recursively
1877 * refer to the class itself.
1879 for (i = 0; i < top; i++) {
1882 field = &klass->fields [i];
1884 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1885 ftype = mono_type_get_underlying_type (field->type);
1886 ftype = mono_type_get_basic_type_from_generic (ftype);
1887 if (type_has_references (klass, ftype))
1888 has_references = TRUE;
1893 * Compute field layout and total size (not considering static fields)
1895 field_offsets = g_new0 (int, top);
1897 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1898 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1899 if (gc_aware_layout)
1904 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1907 if (klass->parent) {
1908 mono_class_setup_fields (klass->parent);
1909 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1911 real_size = klass->parent->instance_size;
1913 real_size = sizeof (MonoObject);
1916 for (pass = 0; pass < passes; ++pass) {
1917 for (i = 0; i < top; i++){
1922 field = &klass->fields [i];
1924 if (mono_field_is_deleted (field))
1926 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1929 ftype = mono_type_get_underlying_type (field->type);
1930 ftype = mono_type_get_basic_type_from_generic (ftype);
1931 if (gc_aware_layout) {
1932 if (type_has_references (klass, ftype)) {
1941 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1942 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1943 /* This field is a hack inserted by MCS to empty structures */
1947 size = mono_type_size (field->type, &align);
1949 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1950 align = packing_size ? MIN (packing_size, align): align;
1951 /* if the field has managed references, we need to force-align it
1954 if (type_has_references (klass, ftype))
1955 align = MAX (align, sizeof (gpointer));
1957 min_align = MAX (align, min_align);
1958 field_offsets [i] = real_size;
1960 field_offsets [i] += align - 1;
1961 field_offsets [i] &= ~(align - 1);
1963 /*TypeBuilders produce all sort of weird things*/
1964 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1965 real_size = field_offsets [i] + size;
1968 instance_size = MAX (real_size, instance_size);
1970 if (instance_size & (min_align - 1)) {
1971 instance_size += min_align - 1;
1972 instance_size &= ~(min_align - 1);
1976 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1980 for (i = 0; i < top; i++) {
1985 field = &klass->fields [i];
1988 * There must be info about all the fields in a type if it
1989 * uses explicit layout.
1991 if (mono_field_is_deleted (field))
1993 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1996 size = mono_type_size (field->type, &align);
1997 align = packing_size ? MIN (packing_size, align): align;
1998 min_align = MAX (align, min_align);
2001 /* Already set by typebuilder_setup_fields () */
2002 field_offsets [i] = field->offset + sizeof (MonoObject);
2004 int idx = klass->field.first + i;
2006 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2007 field_offsets [i] = offset + sizeof (MonoObject);
2009 ftype = mono_type_get_underlying_type (field->type);
2010 ftype = mono_type_get_basic_type_from_generic (ftype);
2011 if (type_has_references (klass, ftype)) {
2012 if (field_offsets [i] % sizeof (gpointer)) {
2013 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2020 real_size = MAX (real_size, size + field_offsets [i]);
2023 if (klass->has_references) {
2024 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2026 /* Check for overlapping reference and non-reference fields */
2027 for (i = 0; i < top; i++) {
2030 field = &klass->fields [i];
2032 if (mono_field_is_deleted (field))
2034 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2036 ftype = mono_type_get_underlying_type (field->type);
2037 if (MONO_TYPE_IS_REFERENCE (ftype))
2038 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2040 for (i = 0; i < top; i++) {
2041 field = &klass->fields [i];
2043 if (mono_field_is_deleted (field))
2045 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2048 // FIXME: Too much code does this
2050 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2051 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]);
2055 g_free (ref_bitmap);
2058 instance_size = MAX (real_size, instance_size);
2059 if (instance_size & (min_align - 1)) {
2060 instance_size += min_align - 1;
2061 instance_size &= ~(min_align - 1);
2067 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2069 * This leads to all kinds of problems with nested structs, so only
2070 * enable it when a MONO_DEBUG property is set.
2072 * For small structs, set min_align to at least the struct size to improve
2073 * performance, and since the JIT memset/memcpy code assumes this and generates
2074 * unaligned accesses otherwise. See #78990 for a testcase.
2076 if (mono_align_small_structs && top) {
2077 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2078 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2082 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2083 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2084 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2085 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2087 /* Publish the data */
2088 mono_loader_lock ();
2089 if (klass->instance_size && !klass->image->dynamic) {
2090 /* Might be already set using cached info */
2091 g_assert (klass->instance_size == instance_size);
2093 klass->instance_size = instance_size;
2095 klass->blittable = blittable;
2096 klass->has_references = has_references;
2097 klass->packing_size = packing_size;
2098 klass->min_align = min_align;
2099 for (i = 0; i < top; ++i) {
2100 field = &klass->fields [i];
2101 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2102 klass->fields [i].offset = field_offsets [i];
2105 mono_memory_barrier ();
2106 klass->size_inited = 1;
2107 mono_loader_unlock ();
2110 * Compute static field layout and size
2111 * Static fields can reference the class itself, so this has to be
2112 * done after instance_size etc. are initialized.
2115 for (i = 0; i < top; i++) {
2119 field = &klass->fields [i];
2121 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2123 if (mono_field_is_deleted (field))
2126 if (mono_type_has_exceptions (field->type)) {
2127 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2131 has_static_fields = TRUE;
2133 size = mono_type_size (field->type, &align);
2134 field_offsets [i] = class_size;
2135 /*align is always non-zero here*/
2136 field_offsets [i] += align - 1;
2137 field_offsets [i] &= ~(align - 1);
2138 class_size = field_offsets [i] + size;
2141 if (has_static_fields && class_size == 0)
2142 /* Simplify code which depends on class_size != 0 if the class has static fields */
2145 /* Compute klass->has_static_refs */
2146 has_static_refs = FALSE;
2147 for (i = 0; i < top; i++) {
2150 field = &klass->fields [i];
2152 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2153 ftype = mono_type_get_underlying_type (field->type);
2154 ftype = mono_type_get_basic_type_from_generic (ftype);
2155 if (type_has_references (klass, ftype))
2156 has_static_refs = TRUE;
2160 /*valuetypes can't be neither bigger than 1Mb or empty. */
2161 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2162 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2164 /* Publish the data */
2165 mono_loader_lock ();
2167 klass->sizes.class_size = class_size;
2168 klass->has_static_refs = has_static_refs;
2169 for (i = 0; i < top; ++i) {
2170 field = &klass->fields [i];
2172 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2173 field->offset = field_offsets [i];
2176 mono_memory_barrier ();
2177 klass->fields_inited = 1;
2178 mono_loader_unlock ();
2180 g_free (field_offsets);
2184 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2188 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2189 method->klass = klass;
2190 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2191 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2192 method->signature = sig;
2193 method->name = name;
2196 if (name [0] == '.') {
2197 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2199 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2205 * mono_class_setup_methods:
2208 * Initializes the 'methods' array in CLASS.
2209 * Calling this method should be avoided if possible since it allocates a lot
2210 * of long-living MonoMethod structures.
2211 * Methods belonging to an interface are assigned a sequential slot starting
2214 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2217 mono_class_setup_methods (MonoClass *klass)
2220 MonoMethod **methods;
2225 if (mono_class_is_ginst (klass)) {
2227 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2229 mono_class_init (gklass);
2230 if (!mono_class_has_failure (gklass))
2231 mono_class_setup_methods (gklass);
2232 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2235 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2236 count = gklass->method.count;
2237 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2239 for (i = 0; i < count; i++) {
2240 methods [i] = mono_class_inflate_generic_method_full_checked (
2241 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2242 if (!mono_error_ok (&error)) {
2243 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2244 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2247 mono_error_cleanup (&error);
2251 } else if (klass->rank) {
2253 MonoMethod *amethod;
2254 MonoMethodSignature *sig;
2255 int count_generic = 0, first_generic = 0;
2257 gboolean jagged_ctor = FALSE;
2259 count = 3 + (klass->rank > 1? 2: 1);
2261 mono_class_setup_interfaces (klass, &error);
2262 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2264 if (klass->rank == 1 && klass->element_class->rank) {
2266 klass->method.count ++;
2269 if (klass->interface_count) {
2270 count_generic = generic_array_methods (klass);
2271 first_generic = count;
2272 count += klass->interface_count * count_generic;
2275 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2277 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2278 sig->ret = &mono_defaults.void_class->byval_arg;
2279 sig->pinvoke = TRUE;
2280 sig->hasthis = TRUE;
2281 for (i = 0; i < klass->rank; ++i)
2282 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2284 amethod = create_array_method (klass, ".ctor", sig);
2285 methods [method_num++] = amethod;
2286 if (klass->rank > 1) {
2287 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2288 sig->ret = &mono_defaults.void_class->byval_arg;
2289 sig->pinvoke = TRUE;
2290 sig->hasthis = TRUE;
2291 for (i = 0; i < klass->rank * 2; ++i)
2292 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2294 amethod = create_array_method (klass, ".ctor", sig);
2295 methods [method_num++] = amethod;
2299 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2300 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2301 sig->ret = &mono_defaults.void_class->byval_arg;
2302 sig->pinvoke = TRUE;
2303 sig->hasthis = TRUE;
2304 for (i = 0; i < klass->rank + 1; ++i)
2305 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2306 amethod = create_array_method (klass, ".ctor", sig);
2307 methods [method_num++] = amethod;
2310 /* element Get (idx11, [idx2, ...]) */
2311 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2312 sig->ret = &klass->element_class->byval_arg;
2313 sig->pinvoke = TRUE;
2314 sig->hasthis = TRUE;
2315 for (i = 0; i < klass->rank; ++i)
2316 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2317 amethod = create_array_method (klass, "Get", sig);
2318 methods [method_num++] = amethod;
2319 /* element& Address (idx11, [idx2, ...]) */
2320 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2321 sig->ret = &klass->element_class->this_arg;
2322 sig->pinvoke = TRUE;
2323 sig->hasthis = TRUE;
2324 for (i = 0; i < klass->rank; ++i)
2325 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2326 amethod = create_array_method (klass, "Address", sig);
2327 methods [method_num++] = amethod;
2328 /* void Set (idx11, [idx2, ...], element) */
2329 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2330 sig->ret = &mono_defaults.void_class->byval_arg;
2331 sig->pinvoke = TRUE;
2332 sig->hasthis = TRUE;
2333 for (i = 0; i < klass->rank; ++i)
2334 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2335 sig->params [i] = &klass->element_class->byval_arg;
2336 amethod = create_array_method (klass, "Set", sig);
2337 methods [method_num++] = amethod;
2339 for (i = 0; i < klass->interface_count; i++)
2340 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2344 count = klass->method.count;
2345 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2346 for (i = 0; i < count; ++i) {
2347 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2348 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2350 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2351 mono_error_cleanup (&error);
2356 if (MONO_CLASS_IS_INTERFACE (klass)) {
2358 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2359 for (i = 0; i < count; ++i) {
2360 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2361 methods [i]->slot = slot++;
2365 mono_image_lock (klass->image);
2367 if (!klass->methods) {
2368 klass->method.count = count;
2370 /* Needed because of the double-checking locking pattern */
2371 mono_memory_barrier ();
2373 klass->methods = methods;
2376 mono_image_unlock (klass->image);
2380 * mono_class_get_method_by_index:
2382 * Returns klass->methods [index], initializing klass->methods if neccesary.
2384 * LOCKING: Acquires the loader lock.
2387 mono_class_get_method_by_index (MonoClass *klass, int index)
2391 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2392 /* Avoid calling setup_methods () if possible */
2393 if (gklass && !klass->methods) {
2396 m = mono_class_inflate_generic_method_full_checked (
2397 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2398 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2400 * If setup_methods () is called later for this class, no duplicates are created,
2401 * since inflate_generic_method guarantees that only one instance of a method
2402 * is created for each context.
2405 mono_class_setup_methods (klass);
2406 g_assert (m == klass->methods [index]);
2410 mono_class_setup_methods (klass);
2411 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2413 g_assert (index >= 0 && index < klass->method.count);
2414 return klass->methods [index];
2419 * mono_class_get_inflated_method:
2421 * Given an inflated class CLASS and a method METHOD which should be a method of
2422 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2425 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2427 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2430 g_assert (method->klass == gklass);
2432 mono_class_setup_methods (gklass);
2433 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2435 for (i = 0; i < gklass->method.count; ++i) {
2436 if (gklass->methods [i] == method) {
2437 if (klass->methods) {
2438 return klass->methods [i];
2441 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2442 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2452 * mono_class_get_vtable_entry:
2454 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2455 * LOCKING: Acquires the loader lock.
2458 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2462 if (klass->rank == 1) {
2464 * szarrays do not overwrite any methods of Array, so we can avoid
2465 * initializing their vtables in some cases.
2467 mono_class_setup_vtable (klass->parent);
2468 if (offset < klass->parent->vtable_size)
2469 return klass->parent->vtable [offset];
2472 if (mono_class_is_ginst (klass)) {
2474 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2475 mono_class_setup_vtable (gklass);
2476 m = gklass->vtable [offset];
2478 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2479 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2481 mono_class_setup_vtable (klass);
2482 if (mono_class_has_failure (klass))
2484 m = klass->vtable [offset];
2491 * mono_class_get_vtable_size:
2493 * Return the vtable size for KLASS.
2496 mono_class_get_vtable_size (MonoClass *klass)
2498 mono_class_setup_vtable (klass);
2500 return klass->vtable_size;
2504 * mono_class_setup_properties:
2506 * Initialize klass->ext.property and klass->ext.properties.
2508 * This method can fail the class.
2511 mono_class_setup_properties (MonoClass *klass)
2513 guint startm, endm, i, j;
2514 guint32 cols [MONO_PROPERTY_SIZE];
2515 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2516 MonoProperty *properties;
2520 if (klass->ext && klass->ext->properties)
2523 if (mono_class_is_ginst (klass)) {
2524 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2526 mono_class_init (gklass);
2527 mono_class_setup_properties (gklass);
2528 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2531 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2533 for (i = 0; i < gklass->ext->property.count; i++) {
2535 MonoProperty *prop = &properties [i];
2537 *prop = gklass->ext->properties [i];
2540 prop->get = mono_class_inflate_generic_method_full_checked (
2541 prop->get, klass, mono_class_get_context (klass), &error);
2543 prop->set = mono_class_inflate_generic_method_full_checked (
2544 prop->set, klass, mono_class_get_context (klass), &error);
2546 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2547 prop->parent = klass;
2550 first = gklass->ext->property.first;
2551 count = gklass->ext->property.count;
2553 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2554 count = last - first;
2557 mono_class_setup_methods (klass);
2558 if (mono_class_has_failure (klass))
2562 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2563 for (i = first; i < last; ++i) {
2564 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2565 properties [i - first].parent = klass;
2566 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2567 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2569 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2570 for (j = startm; j < endm; ++j) {
2573 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2575 if (klass->image->uncompressed_metadata) {
2577 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2578 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2579 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2581 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2584 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2585 case METHOD_SEMANTIC_SETTER:
2586 properties [i - first].set = method;
2588 case METHOD_SEMANTIC_GETTER:
2589 properties [i - first].get = method;
2598 mono_class_alloc_ext (klass);
2600 mono_image_lock (klass->image);
2602 if (klass->ext->properties) {
2603 /* We leak 'properties' which was allocated from the image mempool */
2604 mono_image_unlock (klass->image);
2608 klass->ext->property.first = first;
2609 klass->ext->property.count = count;
2611 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2612 mono_memory_barrier ();
2614 /* Leave this assignment as the last op in the function */
2615 klass->ext->properties = properties;
2617 mono_image_unlock (klass->image);
2621 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2623 MonoMethod **om, **retval;
2626 for (om = methods, count = 0; *om; ++om, ++count)
2629 retval = g_new0 (MonoMethod*, count + 1);
2631 for (om = methods, count = 0; *om; ++om, ++count) {
2633 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2634 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2640 /*This method can fail the class.*/
2642 mono_class_setup_events (MonoClass *klass)
2645 guint startm, endm, i, j;
2646 guint32 cols [MONO_EVENT_SIZE];
2647 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2651 if (klass->ext && klass->ext->events)
2654 if (mono_class_is_ginst (klass)) {
2655 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2656 MonoGenericContext *context = NULL;
2658 mono_class_setup_events (gklass);
2659 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2662 first = gklass->ext->event.first;
2663 count = gklass->ext->event.count;
2665 events = mono_class_new0 (klass, MonoEvent, count);
2668 context = mono_class_get_context (klass);
2670 for (i = 0; i < count; i++) {
2672 MonoEvent *event = &events [i];
2673 MonoEvent *gevent = &gklass->ext->events [i];
2675 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2677 event->parent = klass;
2678 event->name = gevent->name;
2679 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2680 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2681 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2682 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2683 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2684 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2686 #ifndef MONO_SMALL_CONFIG
2687 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2689 event->attrs = gevent->attrs;
2692 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2693 count = last - first;
2696 mono_class_setup_methods (klass);
2697 if (mono_class_has_failure (klass)) {
2702 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2703 for (i = first; i < last; ++i) {
2704 MonoEvent *event = &events [i - first];
2706 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2707 event->parent = klass;
2708 event->attrs = cols [MONO_EVENT_FLAGS];
2709 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2711 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2712 for (j = startm; j < endm; ++j) {
2715 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2717 if (klass->image->uncompressed_metadata) {
2719 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2720 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2721 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2723 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2726 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2727 case METHOD_SEMANTIC_ADD_ON:
2728 event->add = method;
2730 case METHOD_SEMANTIC_REMOVE_ON:
2731 event->remove = method;
2733 case METHOD_SEMANTIC_FIRE:
2734 event->raise = method;
2736 case METHOD_SEMANTIC_OTHER: {
2737 #ifndef MONO_SMALL_CONFIG
2740 if (event->other == NULL) {
2741 event->other = g_new0 (MonoMethod*, 2);
2743 while (event->other [n])
2745 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2747 event->other [n] = method;
2748 /* NULL terminated */
2749 event->other [n + 1] = NULL;
2760 mono_class_alloc_ext (klass);
2762 mono_image_lock (klass->image);
2764 if (klass->ext->events) {
2765 mono_image_unlock (klass->image);
2769 klass->ext->event.first = first;
2770 klass->ext->event.count = count;
2772 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2773 mono_memory_barrier ();
2775 /* Leave this assignment as the last op in the function */
2776 klass->ext->events = events;
2778 mono_image_unlock (klass->image);
2782 * Global pool of interface IDs, represented as a bitset.
2783 * LOCKING: Protected by the classes lock.
2785 static MonoBitSet *global_interface_bitset = NULL;
2788 * mono_unload_interface_ids:
2789 * @bitset: bit set of interface IDs
2791 * When an image is unloaded, the interface IDs associated with
2792 * the image are put back in the global pool of IDs so the numbers
2796 mono_unload_interface_ids (MonoBitSet *bitset)
2799 mono_bitset_sub (global_interface_bitset, bitset);
2804 mono_unload_interface_id (MonoClass *klass)
2806 if (global_interface_bitset && klass->interface_id) {
2808 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2814 * mono_get_unique_iid:
2817 * Assign a unique integer ID to the interface represented by @class.
2818 * The ID will positive and as small as possible.
2819 * LOCKING: Acquires the classes lock.
2820 * Returns: The new ID.
2823 mono_get_unique_iid (MonoClass *klass)
2827 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2831 if (!global_interface_bitset) {
2832 global_interface_bitset = mono_bitset_new (128, 0);
2835 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2837 int old_size = mono_bitset_size (global_interface_bitset);
2838 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2839 mono_bitset_free (global_interface_bitset);
2840 global_interface_bitset = new_set;
2843 mono_bitset_set (global_interface_bitset, iid);
2844 /* set the bit also in the per-image set */
2845 if (!mono_class_is_ginst (klass)) {
2846 if (klass->image->interface_bitset) {
2847 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2848 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2849 mono_bitset_free (klass->image->interface_bitset);
2850 klass->image->interface_bitset = new_set;
2853 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2855 mono_bitset_set (klass->image->interface_bitset, iid);
2860 #ifndef MONO_SMALL_CONFIG
2861 if (mono_print_vtable) {
2863 char *type_name = mono_type_full_name (&klass->byval_arg);
2864 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2865 if (gklass && !gklass->context.class_inst->is_open) {
2866 generic_id = gklass->context.class_inst->id;
2867 g_assert (generic_id != 0);
2871 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2876 g_assert (iid <= 65535);
2881 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2886 mono_class_setup_interfaces (klass, error);
2887 return_if_nok (error);
2889 for (i = 0; i < klass->interface_count; i++) {
2890 ic = klass->interfaces [i];
2893 *res = g_ptr_array_new ();
2894 g_ptr_array_add (*res, ic);
2895 mono_class_init (ic);
2896 if (mono_class_has_failure (ic)) {
2897 mono_error_set_type_load_class (error, ic, "Error Loading class");
2901 collect_implemented_interfaces_aux (ic, res, error);
2902 return_if_nok (error);
2907 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2909 GPtrArray *res = NULL;
2911 collect_implemented_interfaces_aux (klass, &res, error);
2912 if (!mono_error_ok (error)) {
2914 g_ptr_array_free (res, TRUE);
2921 compare_interface_ids (const void *p_key, const void *p_element) {
2922 const MonoClass *key = (const MonoClass *)p_key;
2923 const MonoClass *element = *(const MonoClass **)p_element;
2925 return (key->interface_id - element->interface_id);
2928 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2930 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2931 MonoClass **result = (MonoClass **)mono_binary_search (
2933 klass->interfaces_packed,
2934 klass->interface_offsets_count,
2935 sizeof (MonoClass *),
2936 compare_interface_ids);
2938 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2945 * mono_class_interface_offset_with_variance:
2947 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2948 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2950 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2952 * FIXME figure out MS disambiguation rules and fix this function.
2955 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2956 int i = mono_class_interface_offset (klass, itf);
2957 *non_exact_match = FALSE;
2961 if (!mono_class_has_variant_generic_params (itf))
2964 for (i = 0; i < klass->interface_offsets_count; i++) {
2965 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2966 *non_exact_match = TRUE;
2967 return klass->interface_offsets_packed [i];
2975 print_implemented_interfaces (MonoClass *klass) {
2978 GPtrArray *ifaces = NULL;
2980 int ancestor_level = 0;
2982 name = mono_type_get_full_name (klass);
2983 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2986 for (i = 0; i < klass->interface_offsets_count; i++)
2987 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2988 klass->interfaces_packed [i]->interface_id,
2989 klass->interface_offsets_packed [i],
2990 klass->interfaces_packed [i]->method.count,
2991 klass->interfaces_packed [i]->name_space,
2992 klass->interfaces_packed [i]->name );
2993 printf ("Interface flags: ");
2994 for (i = 0; i <= klass->max_interface_id; i++)
2995 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2996 printf ("(%d,T)", i);
2998 printf ("(%d,F)", i);
3000 printf ("Dump interface flags:");
3001 #ifdef COMPRESSED_INTERFACE_BITMAP
3003 const uint8_t* p = klass->interface_bitmap;
3004 i = klass->max_interface_id;
3006 printf (" %d x 00 %02X", p [0], p [1]);
3012 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3013 printf (" %02X", klass->interface_bitmap [i]);
3016 while (klass != NULL) {
3017 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3018 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3019 if (!mono_error_ok (&error)) {
3020 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3021 mono_error_cleanup (&error);
3022 } else if (ifaces) {
3023 for (i = 0; i < ifaces->len; i++) {
3024 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3025 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3026 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3028 mono_class_interface_offset (klass, ic),
3033 g_ptr_array_free (ifaces, TRUE);
3036 klass = klass->parent;
3041 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3044 args [0] = &arg0->byval_arg;
3046 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3050 array_class_get_if_rank (MonoClass *klass, guint rank)
3052 return rank ? mono_array_class_get (klass, rank) : klass;
3056 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3058 valuetype_types [0] = eclass;
3059 if (eclass == mono_defaults.int16_class)
3060 valuetype_types [1] = mono_defaults.uint16_class;
3061 else if (eclass == mono_defaults.uint16_class)
3062 valuetype_types [1] = mono_defaults.int16_class;
3063 else if (eclass == mono_defaults.int32_class)
3064 valuetype_types [1] = mono_defaults.uint32_class;
3065 else if (eclass == mono_defaults.uint32_class)
3066 valuetype_types [1] = mono_defaults.int32_class;
3067 else if (eclass == mono_defaults.int64_class)
3068 valuetype_types [1] = mono_defaults.uint64_class;
3069 else if (eclass == mono_defaults.uint64_class)
3070 valuetype_types [1] = mono_defaults.int64_class;
3071 else if (eclass == mono_defaults.byte_class)
3072 valuetype_types [1] = mono_defaults.sbyte_class;
3073 else if (eclass == mono_defaults.sbyte_class)
3074 valuetype_types [1] = mono_defaults.byte_class;
3075 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3076 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3079 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3080 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3081 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3082 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3083 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3085 /* this won't be needed once bug #325495 is completely fixed
3086 * though we'll need something similar to know which interfaces to allow
3087 * in arrays when they'll be lazyly created
3089 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3090 * MS returns diferrent types based on which instance is called. For example:
3091 * object obj = new byte[10][];
3092 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3093 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3096 * Fixing this should kill quite some code, save some bits and improve compatibility.
3099 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3101 MonoClass *eclass = klass->element_class;
3102 MonoClass* generic_icollection_class;
3103 MonoClass* generic_ienumerable_class;
3104 MonoClass* generic_ienumerator_class;
3105 MonoClass* generic_ireadonlylist_class;
3106 MonoClass* generic_ireadonlycollection_class;
3107 MonoClass *valuetype_types[2] = { NULL, NULL };
3108 MonoClass **interfaces = NULL;
3109 int i, nifaces, interface_count, real_count, original_rank;
3111 gboolean internal_enumerator;
3112 gboolean eclass_is_valuetype;
3114 if (!mono_defaults.generic_ilist_class) {
3118 internal_enumerator = FALSE;
3119 eclass_is_valuetype = FALSE;
3120 original_rank = eclass->rank;
3121 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3122 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
3123 if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3125 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3127 eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
3128 original_rank = eclass->rank;
3130 eclass = eclass->element_class;
3131 internal_enumerator = TRUE;
3132 *is_enumerator = TRUE;
3140 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3141 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3143 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3145 generic_icollection_class = mono_class_get_generic_icollection_class ();
3146 generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
3147 generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
3148 generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
3149 generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
3151 mono_class_init (eclass);
3154 * Arrays in 2.0 need to implement a number of generic interfaces
3155 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3156 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3157 * We collect the types needed to build the
3158 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3159 * the generic interfaces needed to implement.
3161 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3162 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3164 if (eclass->valuetype) {
3165 nifaces = generic_ireadonlylist_class ? 5 : 3;
3166 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3168 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3169 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3170 if (internal_enumerator) {
3172 if (valuetype_types [1])
3176 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3177 interfaces [0] = valuetype_types [0];
3178 if (valuetype_types [1])
3179 interfaces [nifaces] = valuetype_types [1];
3181 eclass_is_valuetype = TRUE;
3184 int idepth = eclass->idepth;
3185 if (!internal_enumerator)
3187 nifaces = generic_ireadonlylist_class ? 2 : 3;
3189 // FIXME: This doesn't seem to work/required for generic params
3190 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3191 mono_class_setup_interface_offsets (eclass);
3193 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3194 /* we add object for interfaces and the supertypes for the other
3195 * types. The last of the supertypes is the element class itself which we
3196 * already created the explicit interfaces for (so we include it for IEnumerator
3197 * and exclude it for arrays).
3199 if (MONO_CLASS_IS_INTERFACE (eclass))
3202 interface_count += idepth;
3203 if (eclass->rank && eclass->element_class->valuetype) {
3204 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3205 if (valuetype_types [1])
3208 /* IList, ICollection, IEnumerable, IReadOnlyList */
3209 interface_count *= nifaces;
3210 real_count = interface_count;
3211 if (internal_enumerator) {
3212 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3213 if (valuetype_types [1])
3216 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3217 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3218 interfaces [0] = mono_defaults.object_class;
3222 for (i = 0; i < idepth; i++) {
3223 mono_class_init (eclass->supertypes [i]);
3224 interfaces [j] = eclass->supertypes [i];
3228 if (all_interfaces) {
3229 for (i = 0; i < eclass->interface_offsets_count; i++) {
3230 interfaces [j] = eclass->interfaces_packed [i];
3234 for (i = 0; i < eclass->interface_count; i++) {
3235 interfaces [j] = eclass->interfaces [i];
3239 if (valuetype_types [1]) {
3240 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3245 /* instantiate the generic interfaces */
3246 for (i = 0; i < interface_count; i += nifaces) {
3247 MonoClass *iface = interfaces [i];
3249 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3250 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3252 if (eclass->valuetype) {
3253 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3254 if (generic_ireadonlylist_class) {
3255 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3256 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3259 if (!generic_ireadonlylist_class)
3260 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3263 if (internal_enumerator) {
3265 /* instantiate IEnumerator<iface> */
3266 for (i = 0; i < interface_count; i++) {
3267 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3269 j = interface_count;
3270 if (!eclass_is_valuetype) {
3271 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3272 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3275 for (i = 0; i < eclass->idepth; i++) {
3276 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3280 for (i = 0; i < eclass->interface_offsets_count; i++) {
3281 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3285 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3287 if (valuetype_types [1])
3288 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3292 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3293 for (i = 0; i < real_count; ++i) {
3294 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3295 g_print ("%s implements %s\n", type_name, name);
3306 find_array_interface (MonoClass *klass, const char *name)
3309 for (i = 0; i < klass->interface_count; ++i) {
3310 if (strcmp (klass->interfaces [i]->name, name) == 0)
3317 * Return the number of virtual methods.
3318 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3319 * Return -1 on failure.
3320 * FIXME It would be nice if this information could be cached somewhere.
3323 count_virtual_methods (MonoClass *klass)
3327 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3329 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3330 mono_class_setup_methods (klass);
3331 if (mono_class_has_failure (klass))
3334 for (i = 0; i < klass->method.count; ++i) {
3335 flags = klass->methods [i]->flags;
3336 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3340 for (i = 0; i < klass->method.count; ++i) {
3341 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3343 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3351 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3359 m = (l + num_ifaces) / 2;
3360 if (interfaces_full [m] == ic)
3362 if (l == num_ifaces)
3364 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3373 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3375 int i = find_interface (num_ifaces, interfaces_full, ic);
3377 return interface_offsets_full [i];
3382 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3384 int i = find_interface (num_ifaces, interfaces_full, ic);
3388 interface_offsets_full [i] = offset;
3391 for (i = 0; i < num_ifaces; ++i) {
3392 if (interfaces_full [i]) {
3394 if (interfaces_full [i]->interface_id < ic->interface_id)
3397 while (end < num_ifaces && interfaces_full [end]) end++;
3398 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3399 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3401 interfaces_full [i] = ic;
3402 interface_offsets_full [i] = offset;
3408 #ifdef COMPRESSED_INTERFACE_BITMAP
3411 * Compressed interface bitmap design.
3413 * Interface bitmaps take a large amount of memory, because their size is
3414 * linear with the maximum interface id assigned in the process (each interface
3415 * is assigned a unique id as it is loaded). The number of interface classes
3416 * is high because of the many implicit interfaces implemented by arrays (we'll
3417 * need to lazy-load them in the future).
3418 * Most classes implement a very small number of interfaces, so the bitmap is
3419 * sparse. This bitmap needs to be checked by interface casts, so access to the
3420 * needed bit must be fast and doable with few jit instructions.
3422 * The current compression format is as follows:
3423 * *) it is a sequence of one or more two-byte elements
3424 * *) the first byte in the element is the count of empty bitmap bytes
3425 * at the current bitmap position
3426 * *) the second byte in the element is an actual bitmap byte at the current
3429 * As an example, the following compressed bitmap bytes:
3430 * 0x07 0x01 0x00 0x7
3431 * correspond to the following bitmap:
3432 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3434 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3435 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3436 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3440 * mono_compress_bitmap:
3441 * @dest: destination buffer
3442 * @bitmap: bitmap buffer
3443 * @size: size of @bitmap in bytes
3445 * This is a mono internal function.
3446 * The @bitmap data is compressed into a format that is small but
3447 * still searchable in few instructions by the JIT and runtime.
3448 * The compressed data is stored in the buffer pointed to by the
3449 * @dest array. Passing a #NULL value for @dest allows to just compute
3450 * the size of the buffer.
3451 * This compression algorithm assumes the bits set in the bitmap are
3452 * few and far between, like in interface bitmaps.
3453 * Returns: The size of the compressed bitmap in bytes.
3456 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3460 const uint8_t *end = bitmap + size;
3461 while (bitmap < end) {
3462 if (*bitmap || numz == 255) {
3486 * mono_class_interface_match:
3487 * @bitmap: a compressed bitmap buffer
3488 * @id: the index to check in the bitmap
3490 * This is a mono internal function.
3491 * Checks if a bit is set in a compressed interface bitmap. @id must
3492 * be already checked for being smaller than the maximum id encoded in the
3495 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3499 mono_class_interface_match (const uint8_t *bitmap, int id)
3502 id -= bitmap [0] * 8;
3506 return bitmap [1] & (1 << id);
3515 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3516 * LOCKING: Acquires the loader lock.
3519 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3523 int i, j, max_iid, num_ifaces;
3524 MonoClass **interfaces_full = NULL;
3525 int *interface_offsets_full = NULL;
3527 GPtrArray **ifaces_array = NULL;
3528 int interface_offsets_count;
3529 MonoClass **array_interfaces = NULL;
3530 int num_array_interfaces;
3531 int is_enumerator = FALSE;
3533 mono_class_setup_supertypes (klass);
3535 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3536 * implicit interfaces have the property that they are assigned the same slot in the
3537 * vtables for compatible interfaces
3539 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3541 /* compute maximum number of slots and maximum interface id */
3543 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3544 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3545 for (j = 0; j < klass->idepth; j++) {
3546 k = klass->supertypes [j];
3547 num_ifaces += k->interface_count;
3548 for (i = 0; i < k->interface_count; i++) {
3549 ic = k->interfaces [i];
3551 mono_class_init (ic);
3553 if (max_iid < ic->interface_id)
3554 max_iid = ic->interface_id;
3556 ifaces = mono_class_get_implemented_interfaces (k, &error);
3557 if (!mono_error_ok (&error)) {
3558 char *name = mono_type_get_full_name (k);
3559 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3561 mono_error_cleanup (&error);
3566 num_ifaces += ifaces->len;
3567 for (i = 0; i < ifaces->len; ++i) {
3568 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3569 if (max_iid < ic->interface_id)
3570 max_iid = ic->interface_id;
3572 ifaces_array [j] = ifaces;
3576 for (i = 0; i < num_array_interfaces; ++i) {
3577 ic = array_interfaces [i];
3578 mono_class_init (ic);
3579 if (max_iid < ic->interface_id)
3580 max_iid = ic->interface_id;
3583 if (MONO_CLASS_IS_INTERFACE (klass)) {
3585 if (max_iid < klass->interface_id)
3586 max_iid = klass->interface_id;
3589 /* compute vtable offset for interfaces */
3590 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3591 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3593 for (i = 0; i < num_ifaces; i++)
3594 interface_offsets_full [i] = -1;
3596 /* skip the current class */
3597 for (j = 0; j < klass->idepth - 1; j++) {
3598 k = klass->supertypes [j];
3599 ifaces = ifaces_array [j];
3602 for (i = 0; i < ifaces->len; ++i) {
3604 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3606 /*Force the sharing of interface offsets between parent and subtypes.*/
3607 io = mono_class_interface_offset (k, ic);
3609 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3614 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3615 ifaces = ifaces_array [klass->idepth - 1];
3617 for (i = 0; i < ifaces->len; ++i) {
3619 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3620 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3622 count = count_virtual_methods (ic);
3624 char *name = mono_type_get_full_name (ic);
3625 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3634 if (MONO_CLASS_IS_INTERFACE (klass))
3635 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3637 if (num_array_interfaces) {
3638 if (is_enumerator) {
3639 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3640 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3641 g_assert (ienumerator_offset >= 0);
3642 for (i = 0; i < num_array_interfaces; ++i) {
3643 ic = array_interfaces [i];
3644 if (strcmp (ic->name, "IEnumerator`1") == 0)
3645 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3647 g_assert_not_reached ();
3648 /*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);*/
3651 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3652 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3653 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3654 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3655 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3656 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3657 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3658 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3659 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3660 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3661 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3662 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3663 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3664 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3665 for (i = 0; i < num_array_interfaces; ++i) {
3667 ic = array_interfaces [i];
3668 if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
3669 offset = ilist_offset;
3670 else if (strcmp (ic->name, "ICollection`1") == 0)
3671 offset = icollection_offset;
3672 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3673 offset = ienumerable_offset;
3674 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3675 offset = ireadonlylist_offset;
3676 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3677 offset = ireadonlycollection_offset;
3679 g_assert_not_reached ();
3680 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3681 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3686 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3687 if (interface_offsets_full [i] != -1)
3688 interface_offsets_count ++;
3691 /* Publish the data */
3692 mono_loader_lock ();
3694 klass->max_interface_id = max_iid;
3696 * We might get called multiple times:
3697 * - mono_class_init ()
3698 * - mono_class_setup_vtable ().
3699 * - mono_class_setup_interface_offsets ().
3700 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3701 * means we have to overwrite those when called from other places (#4440).
3703 if (klass->interfaces_packed) {
3705 g_assert (klass->interface_offsets_count == interface_offsets_count);
3709 klass->interface_offsets_count = interface_offsets_count;
3710 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3711 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3712 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3713 #ifdef COMPRESSED_INTERFACE_BITMAP
3714 bitmap = g_malloc0 (bsize);
3716 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3718 for (i = 0; i < interface_offsets_count; i++) {
3719 int id = interfaces_full [i]->interface_id;
3720 bitmap [id >> 3] |= (1 << (id & 7));
3721 klass->interfaces_packed [i] = interfaces_full [i];
3722 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3723 /*if (num_array_interfaces)
3724 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]);*/
3726 #ifdef COMPRESSED_INTERFACE_BITMAP
3727 i = mono_compress_bitmap (NULL, bitmap, bsize);
3728 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3729 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3732 klass->interface_bitmap = bitmap;
3735 mono_loader_unlock ();
3738 g_free (interfaces_full);
3739 g_free (interface_offsets_full);
3740 g_free (array_interfaces);
3741 for (i = 0; i < klass->idepth; i++) {
3742 ifaces = ifaces_array [i];
3744 g_ptr_array_free (ifaces, TRUE);
3746 g_free (ifaces_array);
3748 //printf ("JUST DONE: ");
3749 //print_implemented_interfaces (klass);
3755 * Setup interface offsets for interfaces.
3757 * - klass->max_interface_id
3758 * - klass->interface_offsets_count
3759 * - klass->interfaces_packed
3760 * - klass->interface_offsets_packed
3761 * - klass->interface_bitmap
3763 * This function can fail @class.
3766 mono_class_setup_interface_offsets (MonoClass *klass)
3768 setup_interface_offsets (klass, 0, FALSE);
3771 /*Checks if @klass has @parent as one of it's parents type gtd
3775 * Bar<T> : Foo<Bar<Bar<T>>>
3779 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3781 klass = mono_class_get_generic_type_definition (klass);
3782 parent = mono_class_get_generic_type_definition (parent);
3783 mono_class_setup_supertypes (klass);
3784 mono_class_setup_supertypes (parent);
3786 return klass->idepth >= parent->idepth &&
3787 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3791 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3793 MonoGenericInst *ginst;
3796 if (!mono_class_is_ginst (klass)) {
3797 mono_class_setup_vtable_full (klass, in_setup);
3798 return !mono_class_has_failure (klass);
3801 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3802 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3805 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3806 for (i = 0; i < ginst->type_argc; ++i) {
3808 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3810 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3811 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3812 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3814 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3815 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3823 * mono_class_setup_vtable:
3825 * Creates the generic vtable of CLASS.
3826 * Initializes the following fields in MonoClass:
3829 * Plus all the fields initialized by setup_interface_offsets ().
3830 * If there is an error during vtable construction, klass->has_failure
3831 * is set and details are stored in a MonoErrorBoxed.
3833 * LOCKING: Acquires the loader lock.
3836 mono_class_setup_vtable (MonoClass *klass)
3838 mono_class_setup_vtable_full (klass, NULL);
3842 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3845 MonoMethod **overrides;
3846 MonoGenericContext *context;
3854 if (MONO_CLASS_IS_INTERFACE (klass)) {
3855 /* This sets method->slot for all methods if this is an interface */
3856 mono_class_setup_methods (klass);
3860 if (mono_class_has_failure (klass))
3863 if (g_list_find (in_setup, klass))
3866 mono_loader_lock ();
3868 if (klass->vtable) {
3869 mono_loader_unlock ();
3873 mono_stats.generic_vtable_count ++;
3874 in_setup = g_list_prepend (in_setup, klass);
3876 if (mono_class_is_ginst (klass)) {
3877 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3878 mono_loader_unlock ();
3879 g_list_remove (in_setup, klass);
3883 context = mono_class_get_context (klass);
3884 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3886 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3887 type_token = klass->type_token;
3890 if (image_is_dynamic (klass->image)) {
3891 /* Generic instances can have zero method overrides without causing any harm.
3892 * This is true since we don't do layout all over again for them, we simply inflate
3893 * the layout of the parent.
3895 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3896 if (!is_ok (&error)) {
3897 mono_loader_unlock ();
3898 g_list_remove (in_setup, klass);
3899 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3900 mono_error_cleanup (&error);
3904 /* The following call fails if there are missing methods in the type */
3905 /* FIXME it's probably a good idea to avoid this for generic instances. */
3906 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3910 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3912 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3916 mono_loader_unlock ();
3917 g_list_remove (in_setup, klass);
3922 #define DEBUG_INTERFACE_VTABLE_CODE 0
3923 #define TRACE_INTERFACE_VTABLE_CODE 0
3924 #define VERIFY_INTERFACE_VTABLE_CODE 0
3925 #define VTABLE_SELECTOR (1)
3927 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3928 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3929 if (!(VTABLE_SELECTOR)) break; \
3933 #define DEBUG_INTERFACE_VTABLE(stmt)
3936 #if TRACE_INTERFACE_VTABLE_CODE
3937 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3938 if (!(VTABLE_SELECTOR)) break; \
3942 #define TRACE_INTERFACE_VTABLE(stmt)
3945 #if VERIFY_INTERFACE_VTABLE_CODE
3946 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3947 if (!(VTABLE_SELECTOR)) break; \
3951 #define VERIFY_INTERFACE_VTABLE(stmt)
3955 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3957 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3961 GString *res = g_string_new ("");
3963 g_string_append_c (res, '(');
3964 for (i = 0; i < sig->param_count; ++i) {
3966 g_string_append_c (res, ',');
3967 mono_type_get_desc (res, sig->params [i], include_namespace);
3969 g_string_append (res, ")=>");
3970 if (sig->ret != NULL) {
3971 mono_type_get_desc (res, sig->ret, include_namespace);
3973 g_string_append (res, "NULL");
3976 g_string_free (res, FALSE);
3980 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3981 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3982 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3983 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3991 is_wcf_hack_disabled (void)
3993 static gboolean disabled;
3994 static gboolean inited = FALSE;
3996 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4003 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4005 MonoMethodSignature *cmsig, *imsig;
4006 if (strcmp (im->name, cm->name) == 0) {
4007 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4008 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4011 if (! slot_is_empty) {
4012 if (require_newslot) {
4013 if (! interface_is_explicitly_implemented_by_class) {
4014 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4017 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4018 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4022 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4025 cmsig = mono_method_signature (cm);
4026 imsig = mono_method_signature (im);
4027 if (!cmsig || !imsig) {
4028 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4032 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4033 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4034 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4035 TRACE_INTERFACE_VTABLE (printf ("]"));
4038 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4039 if (mono_security_core_clr_enabled ())
4040 mono_security_core_clr_check_override (klass, cm, im);
4042 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4043 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4044 char *body_name = mono_method_full_name (cm, TRUE);
4045 char *decl_name = mono_method_full_name (im, TRUE);
4046 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4054 MonoClass *ic = im->klass;
4055 const char *ic_name_space = ic->name_space;
4056 const char *ic_name = ic->name;
4059 if (! require_newslot) {
4060 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4063 if (cm->klass->rank == 0) {
4064 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4067 cmsig = mono_method_signature (cm);
4068 imsig = mono_method_signature (im);
4069 if (!cmsig || !imsig) {
4070 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4074 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4075 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4076 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4077 TRACE_INTERFACE_VTABLE (printf ("]"));
4080 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4081 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4084 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4085 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4088 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))) {
4089 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4093 subname = strstr (cm->name, ic_name_space);
4094 if (subname != cm->name) {
4095 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4098 subname += strlen (ic_name_space);
4099 if (subname [0] != '.') {
4100 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4104 if (strstr (subname, ic_name) != subname) {
4105 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4108 subname += strlen (ic_name);
4109 if (subname [0] != '.') {
4110 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4114 if (strcmp (subname, im->name) != 0) {
4115 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4119 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4120 if (mono_security_core_clr_enabled ())
4121 mono_security_core_clr_check_override (klass, cm, im);
4123 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4124 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4125 char *body_name = mono_method_full_name (cm, TRUE);
4126 char *decl_name = mono_method_full_name (im, TRUE);
4127 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4137 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4139 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4140 MonoMethod *method = key;
4141 MonoMethod *override = value;
4142 MonoClass *method_class = mono_method_get_class (method);
4143 MonoClass *override_class = mono_method_get_class (override);
4145 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4146 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4147 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4150 print_overrides (GHashTable *override_map, const char *message) {
4152 printf ("Override map \"%s\" START:\n", message);
4153 g_hash_table_foreach (override_map, foreach_override, NULL);
4154 printf ("Override map \"%s\" END.\n", message);
4156 printf ("Override map \"%s\" EMPTY.\n", message);
4160 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4161 char *full_name = mono_type_full_name (&klass->byval_arg);
4165 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4167 if (print_interfaces) {
4168 print_implemented_interfaces (klass);
4169 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4172 if (klass->parent) {
4173 parent_size = klass->parent->vtable_size;
4177 for (i = 0; i < size; ++i) {
4178 MonoMethod *cm = vtable [i];
4179 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4180 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4182 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4190 #if VERIFY_INTERFACE_VTABLE_CODE
4192 mono_method_try_get_vtable_index (MonoMethod *method)
4194 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4195 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4196 if (imethod->declaring->is_generic)
4197 return imethod->declaring->slot;
4199 return method->slot;
4203 mono_class_verify_vtable (MonoClass *klass)
4206 char *full_name = mono_type_full_name (&klass->byval_arg);
4208 printf ("*** Verifying VTable of class '%s' \n", full_name);
4212 if (!klass->methods)
4215 for (i = 0; i < klass->method.count; ++i) {
4216 MonoMethod *cm = klass->methods [i];
4219 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4223 full_name = mono_method_full_name (cm, TRUE);
4225 slot = mono_method_try_get_vtable_index (cm);
4227 if (slot >= klass->vtable_size) {
4228 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4232 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4233 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4234 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4235 g_free (other_name);
4238 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4245 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4247 char *method_signature;
4250 for (index = 0; index < onum; ++index) {
4251 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4252 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4254 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4255 type_name = mono_type_full_name (&klass->byval_arg);
4256 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4257 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4258 g_free (method_signature);
4260 mono_class_setup_methods (klass);
4261 if (mono_class_has_failure (klass)) {
4262 char *name = mono_type_get_full_name (klass);
4263 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4267 for (index = 0; index < klass->method.count; ++index) {
4268 MonoMethod *cm = klass->methods [index];
4269 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4271 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4272 g_free (method_signature);
4277 mono_method_get_method_definition (MonoMethod *method)
4279 while (method->is_inflated)
4280 method = ((MonoMethodInflated*)method)->declaring;
4285 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4289 for (i = 0; i < onum; ++i) {
4290 MonoMethod *decl = overrides [i * 2];
4291 MonoMethod *body = overrides [i * 2 + 1];
4293 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4294 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4298 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4299 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4300 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4302 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4306 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4307 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4308 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4310 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4314 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4315 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4319 body = mono_method_get_method_definition (body);
4320 decl = mono_method_get_method_definition (decl);
4322 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4323 char *body_name = mono_method_full_name (body, TRUE);
4324 char *decl_name = mono_method_full_name (decl, TRUE);
4325 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4335 mono_class_need_stelemref_method (MonoClass *klass)
4337 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4341 * LOCKING: this is supposed to be called with the loader lock held.
4344 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4348 MonoMethod **vtable;
4349 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4350 GPtrArray *ifaces = NULL;
4351 GHashTable *override_map = NULL;
4353 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4354 int first_non_interface_slot;
4356 GSList *virt_methods = NULL, *l;
4357 int stelemref_slot = 0;
4362 if (overrides && !verify_class_overrides (klass, overrides, onum))
4365 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4366 if (!mono_error_ok (&error)) {
4367 char *name = mono_type_get_full_name (klass);
4368 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4370 mono_error_cleanup (&error);
4372 } else if (ifaces) {
4373 for (i = 0; i < ifaces->len; i++) {
4374 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4375 max_vtsize += ic->method.count;
4377 g_ptr_array_free (ifaces, TRUE);
4381 if (klass->parent) {
4382 mono_class_init (klass->parent);
4383 mono_class_setup_vtable_full (klass->parent, in_setup);
4385 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4388 max_vtsize += klass->parent->vtable_size;
4389 cur_slot = klass->parent->vtable_size;
4392 max_vtsize += klass->method.count;
4394 /*Array have a slot for stelemref*/
4395 if (mono_class_need_stelemref_method (klass)) {
4396 stelemref_slot = cur_slot;
4401 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4402 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4404 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4406 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4407 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4410 max_iid = klass->max_interface_id;
4411 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4413 /* Optimized version for generic instances */
4414 if (mono_class_is_ginst (klass)) {
4416 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4419 mono_class_setup_vtable_full (gklass, in_setup);
4420 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4423 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4424 klass->vtable_size = gklass->vtable_size;
4425 for (i = 0; i < gklass->vtable_size; ++i)
4426 if (gklass->vtable [i]) {
4427 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4428 if (!mono_error_ok (&error)) {
4429 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4430 mono_error_cleanup (&error);
4434 tmp [i]->slot = gklass->vtable [i]->slot;
4436 mono_memory_barrier ();
4437 klass->vtable = tmp;
4439 /* Have to set method->slot for abstract virtual methods */
4440 if (klass->methods && gklass->methods) {
4441 for (i = 0; i < klass->method.count; ++i)
4442 if (klass->methods [i]->slot == -1)
4443 klass->methods [i]->slot = gklass->methods [i]->slot;
4449 if (klass->parent && klass->parent->vtable_size) {
4450 MonoClass *parent = klass->parent;
4453 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4455 // Also inherit parent interface vtables, just as a starting point.
4456 // This is needed otherwise bug-77127.exe fails when the property methods
4457 // have different names in the iterface and the class, because for child
4458 // classes the ".override" information is not used anymore.
4459 for (i = 0; i < parent->interface_offsets_count; i++) {
4460 MonoClass *parent_interface = parent->interfaces_packed [i];
4461 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4462 /*FIXME this is now dead code as this condition will never hold true.
4463 Since interface offsets are inherited then the offset of an interface implemented
4464 by a parent will never be the out of it's vtable boundary.
4466 if (interface_offset >= parent->vtable_size) {
4467 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4470 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4471 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4472 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4473 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4474 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4475 parent_interface_offset + j, parent_interface_offset, j,
4476 interface_offset + j, interface_offset, j));
4483 /*Array have a slot for stelemref*/
4484 if (mono_class_need_stelemref_method (klass)) {
4485 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4487 method->slot = stelemref_slot;
4489 g_assert (method->slot == stelemref_slot);
4491 vtable [stelemref_slot] = method;
4494 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4495 /* override interface methods */
4496 for (i = 0; i < onum; i++) {
4497 MonoMethod *decl = overrides [i*2];
4498 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4500 dslot = mono_method_get_vtable_slot (decl);
4502 mono_class_set_type_load_failure (klass, "");
4506 dslot += mono_class_interface_offset (klass, decl->klass);
4507 vtable [dslot] = overrides [i*2 + 1];
4508 vtable [dslot]->slot = dslot;
4510 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4512 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4514 if (mono_security_core_clr_enabled ())
4515 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4518 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4519 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4522 * Create a list of virtual methods to avoid calling
4523 * mono_class_get_virtual_methods () which is slow because of the metadata
4527 gpointer iter = NULL;
4530 virt_methods = NULL;
4531 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4532 virt_methods = g_slist_prepend (virt_methods, cm);
4534 if (mono_class_has_failure (klass))
4538 // Loop on all implemented interfaces...
4539 for (i = 0; i < klass->interface_offsets_count; i++) {
4540 MonoClass *parent = klass->parent;
4542 gboolean interface_is_explicitly_implemented_by_class;
4545 ic = klass->interfaces_packed [i];
4546 ic_offset = mono_class_interface_offset (klass, ic);
4548 mono_class_setup_methods (ic);
4549 if (mono_class_has_failure (ic))
4552 // Check if this interface is explicitly implemented (instead of just inherited)
4553 if (parent != NULL) {
4554 int implemented_interfaces_index;
4555 interface_is_explicitly_implemented_by_class = FALSE;
4556 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4557 if (ic == klass->interfaces [implemented_interfaces_index]) {
4558 interface_is_explicitly_implemented_by_class = TRUE;
4563 interface_is_explicitly_implemented_by_class = TRUE;
4566 // Loop on all interface methods...
4567 for (im_index = 0; im_index < ic->method.count; im_index++) {
4568 MonoMethod *im = ic->methods [im_index];
4569 int im_slot = ic_offset + im->slot;
4570 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4572 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4575 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4577 // If there is an explicit implementation, just use it right away,
4578 // otherwise look for a matching method
4579 if (override_im == NULL) {
4583 // First look for a suitable method among the class methods
4584 for (l = virt_methods; l; l = l->next) {
4585 cm = (MonoMethod *)l->data;
4586 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)));
4587 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4588 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4589 vtable [im_slot] = cm;
4590 /* Why do we need this? */
4595 TRACE_INTERFACE_VTABLE (printf ("\n"));
4596 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4600 // If the slot is still empty, look in all the inherited virtual methods...
4601 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4602 MonoClass *parent = klass->parent;
4603 // Reverse order, so that last added methods are preferred
4604 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4605 MonoMethod *cm = parent->vtable [cm_index];
4607 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));
4608 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4609 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4610 vtable [im_slot] = cm;
4611 /* Why do we need this? */
4617 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4619 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4623 g_assert (vtable [im_slot] == override_im);
4628 // If the class is not abstract, check that all its interface slots are full.
4629 // The check is done here and not directly at the end of the loop above because
4630 // it can happen (for injected generic array interfaces) that the same slot is
4631 // processed multiple times (those interfaces have overlapping slots), and it
4632 // will not always be the first pass the one that fills the slot.
4633 if (! (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_ABSTRACT)) {
4634 for (i = 0; i < klass->interface_offsets_count; i++) {
4638 ic = klass->interfaces_packed [i];
4639 ic_offset = mono_class_interface_offset (klass, ic);
4641 for (im_index = 0; im_index < ic->method.count; im_index++) {
4642 MonoMethod *im = ic->methods [im_index];
4643 int im_slot = ic_offset + im->slot;
4645 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4648 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4649 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4650 if (vtable [im_slot] == NULL) {
4651 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4658 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4659 for (l = virt_methods; l; l = l->next) {
4660 cm = (MonoMethod *)l->data;
4662 * If the method is REUSE_SLOT, we must check in the
4663 * base class for a method to override.
4665 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4667 for (k = klass->parent; k ; k = k->parent) {
4672 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4673 MonoMethodSignature *cmsig, *m1sig;
4675 cmsig = mono_method_signature (cm);
4676 m1sig = mono_method_signature (m1);
4678 if (!cmsig || !m1sig) {
4679 /* FIXME proper error message */
4680 mono_class_set_type_load_failure (klass, "");
4684 if (!strcmp(cm->name, m1->name) &&
4685 mono_metadata_signature_equal (cmsig, m1sig)) {
4687 if (mono_security_core_clr_enabled ())
4688 mono_security_core_clr_check_override (klass, cm, m1);
4690 slot = mono_method_get_vtable_slot (m1);
4694 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4695 char *body_name = mono_method_full_name (cm, TRUE);
4696 char *decl_name = mono_method_full_name (m1, TRUE);
4697 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4703 g_assert (cm->slot < max_vtsize);
4705 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4706 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4707 mono_method_full_name (m1, 1), m1,
4708 mono_method_full_name (cm, 1), cm));
4709 g_hash_table_insert (override_map, m1, cm);
4713 if (mono_class_has_failure (k))
4723 /*Non final newslot methods must be given a non-interface vtable slot*/
4724 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4728 cm->slot = cur_slot++;
4730 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4731 vtable [cm->slot] = cm;
4734 /* override non interface methods */
4735 for (i = 0; i < onum; i++) {
4736 MonoMethod *decl = overrides [i*2];
4737 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4738 g_assert (decl->slot != -1);
4739 vtable [decl->slot] = overrides [i*2 + 1];
4740 overrides [i * 2 + 1]->slot = decl->slot;
4742 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4743 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4744 mono_method_full_name (decl, 1), decl,
4745 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4746 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4748 if (mono_security_core_clr_enabled ())
4749 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4754 * If a method occupies more than one place in the vtable, and it is
4755 * overriden, then change the other occurances too.
4760 for (i = 0; i < max_vtsize; ++i)
4762 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4764 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4769 g_hash_table_destroy (override_map);
4770 override_map = NULL;
4773 g_slist_free (virt_methods);
4774 virt_methods = NULL;
4776 /* Ensure that all vtable slots are filled with concrete instance methods */
4777 if (!(mono_class_get_flags (klass) & TYPE_ATTRIBUTE_ABSTRACT)) {
4778 for (i = 0; i < cur_slot; ++i) {
4779 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4780 char *type_name = mono_type_get_full_name (klass);
4781 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4782 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4784 g_free (method_name);
4790 if (mono_class_is_ginst (klass)) {
4791 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4793 mono_class_init (gklass);
4795 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4797 /* Check that the vtable_size value computed in mono_class_init () is correct */
4798 if (klass->vtable_size)
4799 g_assert (cur_slot == klass->vtable_size);
4800 klass->vtable_size = cur_slot;
4803 /* Try to share the vtable with our parent. */
4804 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4805 mono_memory_barrier ();
4806 klass->vtable = klass->parent->vtable;
4808 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4809 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4810 mono_memory_barrier ();
4811 klass->vtable = tmp;
4814 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4815 if (mono_print_vtable) {
4818 print_implemented_interfaces (klass);
4820 for (i = 0; i <= max_iid; i++)
4821 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4824 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4825 klass->vtable_size, icount);
4827 for (i = 0; i < cur_slot; ++i) {
4832 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4833 mono_method_full_name (cm, TRUE));
4839 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4840 klass->name, max_iid);
4842 for (i = 0; i < klass->interface_count; i++) {
4843 ic = klass->interfaces [i];
4844 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4845 mono_class_interface_offset (klass, ic),
4846 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4849 for (k = klass->parent; k ; k = k->parent) {
4850 for (i = 0; i < k->interface_count; i++) {
4851 ic = k->interfaces [i];
4852 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4853 mono_class_interface_offset (klass, ic),
4854 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4860 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4865 char *name = mono_type_get_full_name (klass);
4866 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4869 g_hash_table_destroy (override_map);
4871 g_slist_free (virt_methods);
4876 * mono_method_get_vtable_slot:
4878 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4879 * LOCKING: Acquires the loader lock.
4881 * FIXME Use proper MonoError machinery here.
4884 mono_method_get_vtable_slot (MonoMethod *method)
4886 if (method->slot == -1) {
4887 mono_class_setup_vtable (method->klass);
4888 if (mono_class_has_failure (method->klass))
4890 if (method->slot == -1) {
4894 if (!mono_class_is_ginst (method->klass)) {
4895 g_assert (method->is_inflated);
4896 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4899 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4900 g_assert (mono_class_is_ginst (method->klass));
4901 gklass = mono_class_get_generic_class (method->klass)->container_class;
4902 mono_class_setup_methods (method->klass);
4903 g_assert (method->klass->methods);
4904 for (i = 0; i < method->klass->method.count; ++i) {
4905 if (method->klass->methods [i] == method)
4908 g_assert (i < method->klass->method.count);
4909 g_assert (gklass->methods);
4910 method->slot = gklass->methods [i]->slot;
4912 g_assert (method->slot != -1);
4914 return method->slot;
4918 * mono_method_get_vtable_index:
4921 * Returns the index into the runtime vtable to access the method or,
4922 * in the case of a virtual generic method, the virtual generic method
4923 * thunk. Returns -1 on failure.
4925 * FIXME Use proper MonoError machinery here.
4928 mono_method_get_vtable_index (MonoMethod *method)
4930 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4931 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4932 if (imethod->declaring->is_generic)
4933 return mono_method_get_vtable_slot (imethod->declaring);
4935 return mono_method_get_vtable_slot (method);
4938 static MonoMethod *default_ghc = NULL;
4939 static MonoMethod *default_finalize = NULL;
4940 static int finalize_slot = -1;
4941 static int ghc_slot = -1;
4944 initialize_object_slots (MonoClass *klass)
4949 if (klass == mono_defaults.object_class) {
4950 mono_class_setup_vtable (klass);
4951 for (i = 0; i < klass->vtable_size; ++i) {
4952 MonoMethod *cm = klass->vtable [i];
4954 if (!strcmp (cm->name, "GetHashCode"))
4956 else if (!strcmp (cm->name, "Finalize"))
4960 g_assert (ghc_slot > 0);
4961 default_ghc = klass->vtable [ghc_slot];
4963 g_assert (finalize_slot > 0);
4964 default_finalize = klass->vtable [finalize_slot];
4969 MonoMethod *array_method;
4971 } GenericArrayMethodInfo;
4973 static int generic_array_method_num = 0;
4974 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4977 generic_array_methods (MonoClass *klass)
4979 int i, count_generic = 0;
4980 GList *list = NULL, *tmp;
4981 if (generic_array_method_num)
4982 return generic_array_method_num;
4983 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4984 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4985 for (i = 0; i < klass->parent->method.count; i++) {
4986 MonoMethod *m = klass->parent->methods [i];
4987 if (!strncmp (m->name, "InternalArray__", 15)) {
4989 list = g_list_prepend (list, m);
4992 list = g_list_reverse (list);
4993 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4995 for (tmp = list; tmp; tmp = tmp->next) {
4996 const char *mname, *iname;
4998 MonoMethod *m = (MonoMethod *)tmp->data;
4999 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5000 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5002 generic_array_method_info [i].array_method = m;
5003 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5004 iname = "System.Collections.Generic.ICollection`1.";
5005 mname = m->name + 27;
5006 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5007 iname = "System.Collections.Generic.IEnumerable`1.";
5008 mname = m->name + 27;
5009 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5010 iname = "System.Collections.Generic.IReadOnlyList`1.";
5011 mname = m->name + strlen (ireadonlylist_prefix);
5012 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5013 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5014 mname = m->name + strlen (ireadonlycollection_prefix);
5015 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5016 iname = "System.Collections.Generic.IList`1.";
5017 mname = m->name + 15;
5019 g_assert_not_reached ();
5022 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5023 strcpy (name, iname);
5024 strcpy (name + strlen (iname), mname);
5025 generic_array_method_info [i].name = name;
5028 /*g_print ("array generic methods: %d\n", count_generic);*/
5030 generic_array_method_num = count_generic;
5032 return generic_array_method_num;
5036 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5038 MonoGenericContext tmp_context;
5041 tmp_context.class_inst = NULL;
5042 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
5043 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5045 for (i = 0; i < generic_array_method_num; i++) {
5047 MonoMethod *m = generic_array_method_info [i].array_method;
5048 MonoMethod *inflated;
5050 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5051 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5052 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5057 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5059 int null_length = strlen ("(null)");
5060 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5061 char *s = (char *)mono_image_alloc (image, len);
5064 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5065 g_assert (result == len - 1);
5072 * @klass: the class to initialize
5074 * Compute the instance_size, class_size and other infos that cannot be
5075 * computed at mono_class_get() time. Also compute vtable_size if possible.
5076 * Returns TRUE on success or FALSE if there was a problem in loading
5077 * the type (incorrect assemblies, missing assemblies, methods, etc).
5078 * Initializes the following fields in @klass:
5079 * - all the fields initialized by mono_class_init_sizes ()
5084 * LOCKING: Acquires the loader lock.
5087 mono_class_init (MonoClass *klass)
5089 int i, vtable_size = 0, array_method_count = 0;
5090 MonoCachedClassInfo cached_info;
5091 gboolean has_cached_info;
5092 gboolean locked = FALSE;
5093 gboolean ghcimpl = FALSE;
5094 gboolean has_cctor = FALSE;
5095 int first_iface_slot = 0;
5099 /* Double-checking locking pattern */
5100 if (klass->inited || mono_class_has_failure (klass))
5101 return !mono_class_has_failure (klass);
5103 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5106 * This function can recursively call itself.
5108 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
5109 if (g_slist_find (init_list, klass)) {
5110 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5113 init_list = g_slist_prepend (init_list, klass);
5114 mono_native_tls_set_value (init_pending_tls_id, init_list);
5117 * We want to avoid doing complicated work inside locks, so we compute all the required
5118 * information and write it to @klass inside a lock.
5121 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5122 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5126 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5127 MonoClass *element_class = klass->element_class;
5128 if (!element_class->inited)
5129 mono_class_init (element_class);
5130 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5134 mono_stats.initialized_class_count++;
5136 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5137 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5139 mono_class_init (gklass);
5140 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5143 mono_class_setup_interface_id (klass);
5146 if (klass->parent && !klass->parent->inited)
5147 mono_class_init (klass->parent);
5149 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5151 /* Compute instance size etc. */
5152 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
5153 if (mono_class_has_failure (klass))
5156 mono_class_setup_supertypes (klass);
5159 initialize_object_slots (klass);
5162 * Initialize the rest of the data without creating a generic vtable if possible.
5163 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5164 * also avoid computing a generic vtable.
5166 if (has_cached_info) {
5168 vtable_size = cached_info.vtable_size;
5169 ghcimpl = cached_info.ghcimpl;
5170 has_cctor = cached_info.has_cctor;
5171 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5172 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5173 * The first slot if for array with.
5175 static int szarray_vtable_size[2] = { 0 };
5177 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5180 if (!szarray_vtable_size [slot]) {
5181 mono_class_setup_vtable (klass);
5182 szarray_vtable_size [slot] = klass->vtable_size;
5183 vtable_size = klass->vtable_size;
5185 vtable_size = szarray_vtable_size[slot];
5187 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
5188 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5190 /* Generic instance case */
5191 ghcimpl = gklass->ghcimpl;
5192 has_cctor = gklass->has_cctor;
5194 mono_class_setup_vtable (gklass);
5195 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5198 vtable_size = gklass->vtable_size;
5202 /* ghcimpl is not currently used
5204 if (klass->parent) {
5205 MonoMethod *cmethod = klass->vtable [ghc_slot];
5206 if (cmethod->is_inflated)
5207 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5208 if (cmethod == default_ghc) {
5214 /* C# doesn't allow interfaces to have cctors */
5215 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5216 MonoMethod *cmethod = NULL;
5218 if (klass->type_token && !image_is_dynamic(klass->image)) {
5219 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5220 /* The find_method function ignores the 'flags' argument */
5221 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5224 mono_class_setup_methods (klass);
5225 if (mono_class_has_failure (klass))
5228 for (i = 0; i < klass->method.count; ++i) {
5229 MonoMethod *method = klass->methods [i];
5230 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5231 (strcmp (".cctor", method->name) == 0)) {
5241 array_method_count = 3 + (klass->rank > 1? 2: 1);
5243 if (klass->interface_count) {
5244 int count_generic = generic_array_methods (klass);
5245 array_method_count += klass->interface_count * count_generic;
5249 if (klass->parent) {
5250 if (!klass->parent->vtable_size)
5251 mono_class_setup_vtable (klass->parent);
5252 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5254 g_assert (klass->parent->vtable_size);
5255 first_iface_slot = klass->parent->vtable_size;
5256 if (mono_class_need_stelemref_method (klass))
5261 * Do the actual changes to @klass inside the loader lock
5263 mono_loader_lock ();
5266 if (klass->inited || mono_class_has_failure (klass)) {
5267 mono_loader_unlock ();
5268 /* Somebody might have gotten in before us */
5269 return !mono_class_has_failure (klass);
5272 mono_stats.initialized_class_count++;
5274 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5275 MonoClass *gklass = klass->generic_class->container_class;
5277 mono_stats.generic_class_count++;
5279 klass->method = gklass->method;
5280 klass->field = gklass->field;
5283 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5284 klass->nested_classes_inited = TRUE;
5285 klass->ghcimpl = ghcimpl;
5286 klass->has_cctor = has_cctor;
5288 klass->vtable_size = vtable_size;
5289 if (has_cached_info) {
5290 klass->has_finalize = cached_info.has_finalize;
5291 klass->has_finalize_inited = TRUE;
5294 klass->method.count = array_method_count;
5296 mono_loader_unlock ();
5299 setup_interface_offsets (klass, first_iface_slot, TRUE);
5301 if (mono_security_core_clr_enabled ())
5302 mono_security_core_clr_check_inheritance (klass);
5304 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5305 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5310 init_list = g_slist_remove (init_list, klass);
5311 mono_native_tls_set_value (init_pending_tls_id, init_list);
5313 /* Because of the double-checking locking pattern */
5314 mono_memory_barrier ();
5318 mono_loader_unlock ();
5320 return !mono_class_has_failure (klass);
5324 * mono_class_has_finalizer:
5326 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5330 mono_class_has_finalizer (MonoClass *klass)
5332 gboolean has_finalize = FALSE;
5334 if (klass->has_finalize_inited)
5335 return klass->has_finalize;
5337 /* Interfaces and valuetypes are not supposed to have finalizers */
5338 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5339 MonoMethod *cmethod = NULL;
5341 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5342 } else if (mono_class_is_ginst (klass)) {
5343 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5345 has_finalize = mono_class_has_finalizer (gklass);
5346 } else if (klass->parent && klass->parent->has_finalize) {
5347 has_finalize = TRUE;
5349 if (klass->parent) {
5351 * Can't search in metadata for a method named Finalize, because that
5352 * ignores overrides.
5354 mono_class_setup_vtable (klass);
5355 if (mono_class_has_failure (klass))
5358 cmethod = klass->vtable [finalize_slot];
5362 g_assert (klass->vtable_size > finalize_slot);
5364 if (klass->parent) {
5365 if (cmethod->is_inflated)
5366 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5367 if (cmethod != default_finalize)
5368 has_finalize = TRUE;
5374 mono_image_lock (klass->image);
5376 if (!klass->has_finalize_inited) {
5377 klass->has_finalize = has_finalize ? 1 : 0;
5379 mono_memory_barrier ();
5380 klass->has_finalize_inited = TRUE;
5383 mono_image_unlock (klass->image);
5385 return klass->has_finalize;
5389 mono_is_corlib_image (MonoImage *image)
5391 return image == mono_defaults.corlib;
5395 * LOCKING: this assumes the loader lock is held
5398 mono_class_setup_mono_type (MonoClass *klass)
5400 const char *name = klass->name;
5401 const char *nspace = klass->name_space;
5402 gboolean is_corlib = mono_is_corlib_image (klass->image);
5404 klass->this_arg.byref = 1;
5405 klass->this_arg.data.klass = klass;
5406 klass->this_arg.type = MONO_TYPE_CLASS;
5407 klass->byval_arg.data.klass = klass;
5408 klass->byval_arg.type = MONO_TYPE_CLASS;
5410 if (is_corlib && !strcmp (nspace, "System")) {
5411 if (!strcmp (name, "ValueType")) {
5413 * do not set the valuetype bit for System.ValueType.
5414 * klass->valuetype = 1;
5416 klass->blittable = TRUE;
5417 } else if (!strcmp (name, "Enum")) {
5419 * do not set the valuetype bit for System.Enum.
5420 * klass->valuetype = 1;
5422 klass->valuetype = 0;
5423 klass->enumtype = 0;
5424 } else if (!strcmp (name, "Object")) {
5425 klass->byval_arg.type = MONO_TYPE_OBJECT;
5426 klass->this_arg.type = MONO_TYPE_OBJECT;
5427 } else if (!strcmp (name, "String")) {
5428 klass->byval_arg.type = MONO_TYPE_STRING;
5429 klass->this_arg.type = MONO_TYPE_STRING;
5430 } else if (!strcmp (name, "TypedReference")) {
5431 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5432 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5436 if (klass->valuetype) {
5437 int t = MONO_TYPE_VALUETYPE;
5439 if (is_corlib && !strcmp (nspace, "System")) {
5442 if (!strcmp (name, "Boolean")) {
5443 t = MONO_TYPE_BOOLEAN;
5444 } else if (!strcmp(name, "Byte")) {
5446 klass->blittable = TRUE;
5450 if (!strcmp (name, "Char")) {
5455 if (!strcmp (name, "Double")) {
5457 klass->blittable = TRUE;
5461 if (!strcmp (name, "Int32")) {
5463 klass->blittable = TRUE;
5464 } else if (!strcmp(name, "Int16")) {
5466 klass->blittable = TRUE;
5467 } else if (!strcmp(name, "Int64")) {
5469 klass->blittable = TRUE;
5470 } else if (!strcmp(name, "IntPtr")) {
5472 klass->blittable = TRUE;
5476 if (!strcmp (name, "Single")) {
5478 klass->blittable = TRUE;
5479 } else if (!strcmp(name, "SByte")) {
5481 klass->blittable = TRUE;
5485 if (!strcmp (name, "UInt32")) {
5487 klass->blittable = TRUE;
5488 } else if (!strcmp(name, "UInt16")) {
5490 klass->blittable = TRUE;
5491 } else if (!strcmp(name, "UInt64")) {
5493 klass->blittable = TRUE;
5494 } else if (!strcmp(name, "UIntPtr")) {
5496 klass->blittable = TRUE;
5500 if (!strcmp (name, "TypedReference")) {
5501 t = MONO_TYPE_TYPEDBYREF;
5502 klass->blittable = TRUE;
5506 if (!strcmp (name, "Void")) {
5514 klass->byval_arg.type = (MonoTypeEnum)t;
5515 klass->this_arg.type = (MonoTypeEnum)t;
5518 if (MONO_CLASS_IS_INTERFACE (klass))
5519 klass->interface_id = mono_get_unique_iid (klass);
5524 * COM initialization is delayed until needed.
5525 * However when a [ComImport] attribute is present on a type it will trigger
5526 * the initialization. This is not a problem unless the BCL being executed
5527 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5530 init_com_from_comimport (MonoClass *klass)
5532 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5533 if (mono_security_core_clr_enabled ()) {
5534 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5535 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5536 /* but it can not be made available for application (i.e. user code) since all COM calls
5537 * are considered native calls. In this case we fail with a TypeLoadException (just like
5538 * Silverlight 2 does */
5539 mono_class_set_type_load_failure (klass, "");
5544 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5546 #endif /*DISABLE_COM*/
5549 * LOCKING: this assumes the loader lock is held
5552 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5554 gboolean system_namespace;
5555 gboolean is_corlib = mono_is_corlib_image (klass->image);
5557 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5559 /* if root of the hierarchy */
5560 if (system_namespace && !strcmp (klass->name, "Object")) {
5561 klass->parent = NULL;
5562 klass->instance_size = sizeof (MonoObject);
5565 if (!strcmp (klass->name, "<Module>")) {
5566 klass->parent = NULL;
5567 klass->instance_size = 0;
5571 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5572 /* Imported COM Objects always derive from __ComObject. */
5574 if (MONO_CLASS_IS_IMPORT (klass)) {
5575 init_com_from_comimport (klass);
5576 if (parent == mono_defaults.object_class)
5577 parent = mono_class_get_com_object_class ();
5581 /* set the parent to something useful and safe, but mark the type as broken */
5582 parent = mono_defaults.object_class;
5583 mono_class_set_type_load_failure (klass, "");
5587 klass->parent = parent;
5589 if (mono_class_is_ginst (parent) && !parent->name) {
5591 * If the parent is a generic instance, we may get
5592 * called before it is fully initialized, especially
5593 * before it has its name.
5598 #ifndef DISABLE_REMOTING
5599 klass->marshalbyref = parent->marshalbyref;
5600 klass->contextbound = parent->contextbound;
5603 klass->delegate = parent->delegate;
5605 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5606 mono_class_set_is_com_object (klass);
5608 if (system_namespace) {
5609 #ifndef DISABLE_REMOTING
5610 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5611 klass->marshalbyref = 1;
5613 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5614 klass->contextbound = 1;
5616 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5617 klass->delegate = 1;
5620 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5621 (strcmp (klass->parent->name_space, "System") == 0)))
5622 klass->valuetype = 1;
5623 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5624 klass->valuetype = klass->enumtype = 1;
5626 /*klass->enumtype = klass->parent->enumtype; */
5628 /* initialize com types if COM interfaces are present */
5630 if (MONO_CLASS_IS_IMPORT (klass))
5631 init_com_from_comimport (klass);
5633 klass->parent = NULL;
5639 * mono_class_setup_supertypes:
5642 * Build the data structure needed to make fast type checks work.
5643 * This currently sets two fields in @class:
5644 * - idepth: distance between @class and System.Object in the type
5646 * - supertypes: array of classes: each element has a class in the hierarchy
5647 * starting from @class up to System.Object
5649 * LOCKING: This function is atomic, in case of contention we waste memory.
5652 mono_class_setup_supertypes (MonoClass *klass)
5655 MonoClass **supertypes;
5657 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5661 if (klass->parent && !klass->parent->supertypes)
5662 mono_class_setup_supertypes (klass->parent);
5664 klass->idepth = klass->parent->idepth + 1;
5668 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5669 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5671 if (klass->parent) {
5672 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5675 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5676 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5678 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5681 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5685 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5687 MonoClass *gtd = (MonoClass*)user_data;
5688 /* Only try to fix generic instances of @gtd */
5689 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5692 /* Check if the generic instance has no parent. */
5693 if (gtd->parent && !gclass->parent)
5694 mono_generic_class_setup_parent (gclass, gtd);
5700 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5702 mono_class_set_type_load_failure (klass, "%s", msg);
5703 mono_error_set_type_load_class (error, klass, "%s", msg);
5707 * mono_class_create_from_typedef:
5708 * @image: image where the token is valid
5709 * @type_token: typedef token
5710 * @error: used to return any error found while creating the type
5712 * Create the MonoClass* representing the specified type token.
5713 * @type_token must be a TypeDef token.
5715 * FIXME: don't return NULL on failure, just the the caller figure it out.
5718 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5720 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5721 MonoClass *klass, *parent = NULL;
5722 guint32 cols [MONO_TYPEDEF_SIZE];
5723 guint32 cols_next [MONO_TYPEDEF_SIZE];
5724 guint tidx = mono_metadata_token_index (type_token);
5725 MonoGenericContext *context = NULL;
5726 const char *name, *nspace;
5728 MonoClass **interfaces;
5729 guint32 field_last, method_last;
5730 guint32 nesting_tokeen;
5732 mono_error_init (error);
5734 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5735 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5739 mono_loader_lock ();
5741 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5742 mono_loader_unlock ();
5746 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5748 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5749 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5751 if (mono_metadata_has_generic_params (image, type_token)) {
5752 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5753 klass->class_kind = MONO_CLASS_GTD;
5754 classes_size += sizeof (MonoClassGtd);
5757 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5758 klass->class_kind = MONO_CLASS_DEF;
5759 classes_size += sizeof (MonoClassDef);
5764 klass->name_space = nspace;
5766 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5768 klass->image = image;
5769 klass->type_token = type_token;
5770 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5772 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5775 * Check whether we're a generic type definition.
5777 if (mono_class_is_gtd (klass)) {
5778 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5779 generic_container->owner.klass = klass;
5780 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5781 context = &generic_container->context;
5782 mono_class_set_generic_container (klass, generic_container);
5783 enable_gclass_recording ();
5786 if (cols [MONO_TYPEDEF_EXTENDS]) {
5788 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5790 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5791 /*WARNING: this must satisfy mono_metadata_type_hash*/
5792 klass->this_arg.byref = 1;
5793 klass->this_arg.data.klass = klass;
5794 klass->this_arg.type = MONO_TYPE_CLASS;
5795 klass->byval_arg.data.klass = klass;
5796 klass->byval_arg.type = MONO_TYPE_CLASS;
5798 parent = mono_class_get_checked (image, parent_token, error);
5799 if (parent && context) /* Always inflate */
5800 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5802 if (parent == NULL) {
5803 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5804 goto parent_failure;
5807 for (tmp = parent; tmp; tmp = tmp->parent) {
5809 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5810 goto parent_failure;
5812 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5813 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5814 goto parent_failure;
5819 mono_class_setup_parent (klass, parent);
5821 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5822 mono_class_setup_mono_type (klass);
5824 if (mono_class_is_gtd (klass))
5825 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5828 * This might access klass->byval_arg for recursion generated by generic constraints,
5829 * so it has to come after setup_mono_type ().
5831 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5832 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5833 if (!mono_error_ok (error)) {
5834 /*FIXME implement a mono_class_set_failure_from_mono_error */
5835 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5836 mono_loader_unlock ();
5837 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5842 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5846 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5850 klass->cast_class = klass->element_class = klass;
5852 if (!klass->enumtype) {
5853 if (!mono_metadata_interfaces_from_typedef_full (
5854 image, type_token, &interfaces, &icount, FALSE, context, error)){
5856 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5857 mono_loader_unlock ();
5858 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5862 klass->interfaces = interfaces;
5863 klass->interface_count = icount;
5864 klass->interfaces_inited = 1;
5867 /*g_print ("Load class %s\n", name);*/
5870 * Compute the field and method lists
5872 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5873 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5875 if (tt->rows > tidx){
5876 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5877 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5878 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5880 field_last = image->tables [MONO_TABLE_FIELD].rows;
5881 method_last = image->tables [MONO_TABLE_METHOD].rows;
5884 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5885 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5886 klass->field.count = field_last - klass->field.first;
5888 klass->field.count = 0;
5890 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5891 klass->method.count = method_last - klass->method.first;
5893 klass->method.count = 0;
5895 /* reserve space to store vector pointer in arrays */
5896 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5897 klass->instance_size += 2 * sizeof (gpointer);
5898 g_assert (klass->field.count == 0);
5901 if (klass->enumtype) {
5902 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5903 if (!enum_basetype) {
5904 /*set it to a default value as the whole runtime can't handle this to be null*/
5905 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5906 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5907 mono_loader_unlock ();
5908 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5911 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5915 * If we're a generic type definition, load the constraints.
5916 * We must do this after the class has been constructed to make certain recursive scenarios
5919 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5920 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5921 mono_loader_unlock ();
5922 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5926 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5927 if (!strncmp (name, "Vector", 6))
5928 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");
5931 mono_loader_unlock ();
5933 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5938 mono_class_setup_mono_type (klass);
5939 mono_loader_unlock ();
5940 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5944 /** Is klass a Nullable<T> ginst? */
5946 mono_class_is_nullable (MonoClass *klass)
5948 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5949 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5953 /** if klass is T? return T */
5955 mono_class_get_nullable_param (MonoClass *klass)
5957 g_assert (mono_class_is_nullable (klass));
5958 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5962 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5966 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5968 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5969 if (!mono_error_ok (&error)) {
5970 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5971 klass->parent = mono_defaults.object_class;
5972 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5973 mono_error_cleanup (&error);
5977 mono_class_setup_parent (klass, klass->parent);
5979 if (klass->enumtype) {
5980 klass->cast_class = gtd->cast_class;
5981 klass->element_class = gtd->element_class;
5987 * Create the `MonoClass' for an instantiation of a generic type.
5988 * We only do this if we actually need it.
5991 mono_generic_class_get_class (MonoGenericClass *gclass)
5993 MonoClass *klass, *gklass;
5995 if (gclass->cached_class)
5996 return gclass->cached_class;
5998 mono_loader_lock ();
5999 if (gclass->cached_class) {
6000 mono_loader_unlock ();
6001 return gclass->cached_class;
6004 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6006 gklass = gclass->container_class;
6008 if (record_gclass_instantiation > 0)
6009 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6011 if (gklass->nested_in) {
6012 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6013 klass->nested_in = gklass->nested_in;
6016 klass->name = gklass->name;
6017 klass->name_space = gklass->name_space;
6019 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6021 klass->image = gklass->image;
6022 klass->type_token = gklass->type_token;
6023 klass->field.count = gklass->field.count;
6025 klass->class_kind = MONO_CLASS_GINST;
6027 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6029 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6030 klass->this_arg.type = klass->byval_arg.type;
6031 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6032 klass->this_arg.byref = TRUE;
6033 klass->enumtype = gklass->enumtype;
6034 klass->valuetype = gklass->valuetype;
6036 klass->cast_class = klass->element_class = klass;
6038 if (mono_class_is_nullable (klass))
6039 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6042 * We're not interested in the nested classes of a generic instance.
6043 * We use the generic type definition to look for nested classes.
6046 mono_generic_class_setup_parent (klass, gklass);
6048 if (gclass->is_dynamic) {
6050 * 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.
6051 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6052 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6054 if (!gklass->wastypebuilder)
6057 mono_class_setup_supertypes (klass);
6059 if (klass->enumtype) {
6061 * For enums, gklass->fields might not been set, but instance_size etc. is
6062 * already set in mono_reflection_create_internal_class (). For non-enums,
6063 * these will be computed normally in mono_class_layout_fields ().
6065 klass->instance_size = gklass->instance_size;
6066 klass->sizes.class_size = gklass->sizes.class_size;
6067 mono_memory_barrier ();
6068 klass->size_inited = 1;
6072 mono_memory_barrier ();
6073 gclass->cached_class = klass;
6075 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6077 ++class_ginst_count;
6078 inflated_classes_size += sizeof (MonoClassGenericInst);
6080 mono_loader_unlock ();
6086 get_image_for_container (MonoGenericContainer *container)
6089 if (container->is_anonymous) {
6090 result = container->owner.image;
6093 if (container->is_method) {
6094 MonoMethod *method = container->owner.method;
6095 g_assert_checked (method);
6096 klass = method->klass;
6098 klass = container->owner.klass;
6100 g_assert_checked (klass);
6101 result = klass->image;
6108 get_image_for_generic_param (MonoGenericParam *param)
6110 MonoGenericContainer *container = mono_generic_param_owner (param);
6111 g_assert_checked (container);
6112 return get_image_for_container (container);
6115 // Make a string in the designated image consisting of a single integer.
6116 #define INT_STRING_SIZE 16
6118 make_generic_name_string (MonoImage *image, int num)
6120 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6121 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6125 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6126 // pinfo is derived from param by the caller for us.
6128 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6130 MonoClass *klass, **ptr;
6132 MonoGenericContainer *container = mono_generic_param_owner (param);
6133 g_assert_checked (container);
6135 MonoImage *image = get_image_for_container (container);
6136 gboolean is_mvar = container->is_method;
6137 gboolean is_anonymous = container->is_anonymous;
6139 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6140 klass->class_kind = MONO_CLASS_GPARAM;
6141 classes_size += sizeof (MonoClassGenericParam);
6142 ++class_gparam_count;
6145 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6147 int n = mono_generic_param_num (param);
6148 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6152 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6153 } else if (is_mvar) {
6154 MonoMethod *omethod = container->owner.method;
6155 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6157 MonoClass *oklass = container->owner.klass;
6158 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6161 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6163 // Count non-NULL items in pinfo->constraints
6166 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6170 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6171 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6173 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6174 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6176 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6179 if (count - pos > 0) {
6180 klass->interface_count = count - pos;
6181 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6182 klass->interfaces_inited = TRUE;
6183 for (i = pos; i < count; i++)
6184 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6187 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6189 klass->inited = TRUE;
6190 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6191 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6193 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6194 klass->this_arg.type = klass->byval_arg.type;
6195 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6196 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6197 klass->this_arg.byref = TRUE;
6199 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6200 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6202 /*Init these fields to sane values*/
6203 klass->min_align = 1;
6205 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6206 * constrained to, the JIT depends on this.
6208 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6209 mono_memory_barrier ();
6210 klass->size_inited = 1;
6212 mono_class_setup_supertypes (klass);
6214 if (count - pos > 0) {
6215 mono_class_setup_vtable (klass->parent);
6216 if (mono_class_has_failure (klass->parent))
6217 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6219 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6225 #define FAST_CACHE_SIZE 16
6228 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6229 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6230 * we cache the MonoClasses.
6231 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6232 * LOCKING: Takes the image lock depending on @take_lock.
6235 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6237 int n = mono_generic_param_num (param);
6238 MonoImage *image = get_image_for_generic_param (param);
6239 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6240 MonoClass *klass = NULL;
6245 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6246 // For high numbers or constraints we have to use pointer hashes.
6247 if (param->gshared_constraint) {
6248 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6251 mono_image_lock (image);
6252 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6254 mono_image_unlock (image);
6259 if (n < FAST_CACHE_SIZE) {
6261 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6263 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6265 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6268 mono_image_lock (image);
6269 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6271 mono_image_unlock (image);
6278 * LOCKING: Image lock (param->image) must be held
6281 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6283 int n = mono_generic_param_num (param);
6284 MonoImage *image = get_image_for_generic_param (param);
6285 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6289 if (param->gshared_constraint) {
6290 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6292 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6293 mono_memory_barrier ();
6295 image->mvar_cache_constrained = ht;
6297 image->var_cache_constrained = ht;
6299 g_hash_table_insert (ht, param, klass);
6300 } else if (n < FAST_CACHE_SIZE) {
6302 /* Requires locking to avoid droping an already published class */
6303 if (!image->mvar_cache_fast)
6304 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6305 image->mvar_cache_fast [n] = klass;
6307 if (!image->var_cache_fast)
6308 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6309 image->var_cache_fast [n] = klass;
6312 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6314 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6316 ht = g_hash_table_new (NULL, NULL);
6317 mono_memory_barrier ();
6319 image->mvar_cache_slow = ht;
6321 image->var_cache_slow = ht;
6324 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6329 * LOCKING: Acquires the image lock (@image).
6332 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6334 MonoImage *image = get_image_for_generic_param (param);
6335 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6336 MonoClass *klass, *klass2;
6338 // If a klass already exists for this object and is cached, return it.
6339 if (pinfo) // Non-anonymous
6340 klass = pinfo->pklass;
6342 klass = get_anon_gparam_class (param, TRUE);
6347 // Create a new klass
6348 klass = make_generic_param_class (param, pinfo);
6350 // Now we need to cache the klass we created.
6351 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6352 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6353 // and allow our newly-created klass object to just leak.
6354 mono_memory_barrier ();
6356 mono_image_lock (image);
6358 // Here "klass2" refers to the klass potentially created by the other thread.
6359 if (pinfo) // Repeat check from above
6360 klass2 = pinfo->pklass;
6362 klass2 = get_anon_gparam_class (param, FALSE);
6369 pinfo->pklass = klass;
6371 set_anon_gparam_class (param, klass);
6373 mono_image_unlock (image);
6375 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6377 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6379 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6385 * mono_class_from_generic_parameter:
6386 * @param: Parameter to find/construct a class for.
6387 * @arg2: Is ignored.
6388 * @arg3: Is ignored.
6391 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6393 return mono_class_from_generic_parameter_internal (param);
6398 mono_ptr_class_get (MonoType *type)
6401 MonoClass *el_class;
6405 el_class = mono_class_from_mono_type (type);
6406 image = el_class->image;
6408 mono_image_lock (image);
6409 if (image->ptr_cache) {
6410 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6411 mono_image_unlock (image);
6415 mono_image_unlock (image);
6417 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6419 classes_size += sizeof (MonoClassPointer);
6420 ++class_pointer_count;
6422 result->parent = NULL; /* no parent for PTR types */
6423 result->name_space = el_class->name_space;
6424 name = g_strdup_printf ("%s*", el_class->name);
6425 result->name = mono_image_strdup (image, name);
6426 result->class_kind = MONO_CLASS_POINTER;
6429 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6431 result->image = el_class->image;
6432 result->inited = TRUE;
6433 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6434 result->cast_class = result->element_class = el_class;
6435 result->blittable = TRUE;
6437 result->byval_arg.type = MONO_TYPE_PTR;
6438 result->this_arg.type = result->byval_arg.type;
6439 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6440 result->this_arg.byref = TRUE;
6442 mono_class_setup_supertypes (result);
6444 mono_image_lock (image);
6445 if (image->ptr_cache) {
6447 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6448 mono_image_unlock (image);
6449 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6453 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6455 g_hash_table_insert (image->ptr_cache, el_class, result);
6456 mono_image_unlock (image);
6458 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6464 mono_fnptr_class_get (MonoMethodSignature *sig)
6467 static GHashTable *ptr_hash = NULL;
6469 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6471 mono_loader_lock ();
6474 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6476 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6477 mono_loader_unlock ();
6480 result = g_new0 (MonoClass, 1);
6482 classes_size += sizeof (MonoClassPointer);
6483 ++class_pointer_count;
6485 result->parent = NULL; /* no parent for PTR types */
6486 result->name_space = "System";
6487 result->name = "MonoFNPtrFakeClass";
6488 result->class_kind = MONO_CLASS_POINTER;
6490 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6492 result->image = mono_defaults.corlib; /* need to fix... */
6493 result->inited = TRUE;
6494 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6495 result->cast_class = result->element_class = result;
6496 result->blittable = TRUE;
6498 result->byval_arg.type = MONO_TYPE_FNPTR;
6499 result->this_arg.type = result->byval_arg.type;
6500 result->this_arg.data.method = result->byval_arg.data.method = sig;
6501 result->this_arg.byref = TRUE;
6502 result->blittable = TRUE;
6504 mono_class_setup_supertypes (result);
6506 g_hash_table_insert (ptr_hash, sig, result);
6508 mono_loader_unlock ();
6510 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6516 * mono_class_from_mono_type:
6517 * @type: describes the type to return
6519 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6522 mono_class_from_mono_type (MonoType *type)
6524 switch (type->type) {
6525 case MONO_TYPE_OBJECT:
6526 return type->data.klass? type->data.klass: mono_defaults.object_class;
6527 case MONO_TYPE_VOID:
6528 return type->data.klass? type->data.klass: mono_defaults.void_class;
6529 case MONO_TYPE_BOOLEAN:
6530 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6531 case MONO_TYPE_CHAR:
6532 return type->data.klass? type->data.klass: mono_defaults.char_class;
6534 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6536 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6538 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6540 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6542 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6544 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6546 return type->data.klass? type->data.klass: mono_defaults.int_class;
6548 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6550 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6552 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6554 return type->data.klass? type->data.klass: mono_defaults.single_class;
6556 return type->data.klass? type->data.klass: mono_defaults.double_class;
6557 case MONO_TYPE_STRING:
6558 return type->data.klass? type->data.klass: mono_defaults.string_class;
6559 case MONO_TYPE_TYPEDBYREF:
6560 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6561 case MONO_TYPE_ARRAY:
6562 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6564 return mono_ptr_class_get (type->data.type);
6565 case MONO_TYPE_FNPTR:
6566 return mono_fnptr_class_get (type->data.method);
6567 case MONO_TYPE_SZARRAY:
6568 return mono_array_class_get (type->data.klass, 1);
6569 case MONO_TYPE_CLASS:
6570 case MONO_TYPE_VALUETYPE:
6571 return type->data.klass;
6572 case MONO_TYPE_GENERICINST:
6573 return mono_generic_class_get_class (type->data.generic_class);
6574 case MONO_TYPE_MVAR:
6576 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6578 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6579 g_assert_not_reached ();
6582 // Yes, this returns NULL, even if it is documented as not doing so, but there
6583 // is no way for the code to make it this far, due to the assert above.
6588 * mono_type_retrieve_from_typespec
6589 * @image: context where the image is created
6590 * @type_spec: typespec token
6591 * @context: the generic context used to evaluate generic instantiations in
6594 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6596 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6598 *did_inflate = FALSE;
6603 if (context && (context->class_inst || context->method_inst)) {
6604 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6606 if (!mono_error_ok (error)) {
6612 *did_inflate = TRUE;
6619 * mono_class_create_from_typespec
6620 * @image: context where the image is created
6621 * @type_spec: typespec token
6622 * @context: the generic context used to evaluate generic instantiations in
6625 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6628 gboolean inflated = FALSE;
6629 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6630 return_val_if_nok (error, NULL);
6631 ret = mono_class_from_mono_type (t);
6633 mono_metadata_free_type (t);
6638 * mono_bounded_array_class_get:
6639 * @element_class: element class
6640 * @rank: the dimension of the array class
6641 * @bounded: whenever the array has non-zero bounds
6643 * Returns: A class object describing the array with element type @element_type and
6647 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6651 MonoClass *parent = NULL;
6652 GSList *list, *rootlist = NULL;
6656 g_assert (rank <= 255);
6659 /* bounded only matters for one-dimensional arrays */
6662 image = eclass->image;
6664 if (rank == 1 && !bounded) {
6666 * This case is very frequent not just during compilation because of calls
6667 * from mono_class_from_mono_type (), mono_array_new (),
6668 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6670 mono_os_mutex_lock (&image->szarray_cache_lock);
6671 if (!image->szarray_cache)
6672 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6673 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6674 mono_os_mutex_unlock (&image->szarray_cache_lock);
6678 mono_loader_lock ();
6680 mono_loader_lock ();
6682 if (!image->array_cache)
6683 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6685 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6686 for (; list; list = list->next) {
6687 klass = (MonoClass *)list->data;
6688 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6689 mono_loader_unlock ();
6696 parent = mono_defaults.array_class;
6697 if (!parent->inited)
6698 mono_class_init (parent);
6700 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6702 klass->image = image;
6703 klass->name_space = eclass->name_space;
6704 klass->class_kind = MONO_CLASS_ARRAY;
6706 nsize = strlen (eclass->name);
6707 name = (char *)g_malloc (nsize + 2 + rank + 1);
6708 memcpy (name, eclass->name, nsize);
6711 memset (name + nsize + 1, ',', rank - 1);
6713 name [nsize + rank] = '*';
6714 name [nsize + rank + bounded] = ']';
6715 name [nsize + rank + bounded + 1] = 0;
6716 klass->name = mono_image_strdup (image, name);
6719 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6721 classes_size += sizeof (MonoClassArray);
6722 ++class_array_count;\
6724 klass->type_token = 0;
6725 klass->parent = parent;
6726 klass->instance_size = mono_class_instance_size (klass->parent);
6728 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6729 /*Arrays of those two types are invalid.*/
6730 MonoError prepared_error;
6731 mono_error_init (&prepared_error);
6732 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6733 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6734 mono_error_cleanup (&prepared_error);
6735 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6736 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6737 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6738 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6740 /* element_size -1 is ok as this is not an instantitable type*/
6741 klass->sizes.element_size = -1;
6743 klass->sizes.element_size = mono_class_array_element_size (eclass);
6745 mono_class_setup_supertypes (klass);
6747 if (mono_class_is_ginst (eclass))
6748 mono_class_init (eclass);
6749 mono_class_init_sizes (eclass);
6750 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6751 /*FIXME we fail the array type, but we have to let other fields be set.*/
6753 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6757 if (eclass->enumtype)
6758 klass->cast_class = eclass->element_class;
6760 klass->cast_class = eclass;
6762 switch (klass->cast_class->byval_arg.type) {
6764 klass->cast_class = mono_defaults.byte_class;
6767 klass->cast_class = mono_defaults.int16_class;
6770 #if SIZEOF_VOID_P == 4
6774 klass->cast_class = mono_defaults.int32_class;
6777 #if SIZEOF_VOID_P == 8
6781 klass->cast_class = mono_defaults.int64_class;
6787 klass->element_class = eclass;
6789 if ((rank > 1) || bounded) {
6790 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6791 klass->byval_arg.type = MONO_TYPE_ARRAY;
6792 klass->byval_arg.data.array = at;
6793 at->eklass = eclass;
6795 /* FIXME: complete.... */
6797 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6798 klass->byval_arg.data.klass = eclass;
6800 klass->this_arg = klass->byval_arg;
6801 klass->this_arg.byref = 1;
6803 //WTF was this? it's wrong
6804 // klass->generic_container = eclass->generic_container;
6806 if (rank == 1 && !bounded) {
6807 MonoClass *prev_class;
6809 mono_os_mutex_lock (&image->szarray_cache_lock);
6810 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6812 /* Someone got in before us */
6815 g_hash_table_insert (image->szarray_cache, eclass, klass);
6816 mono_os_mutex_unlock (&image->szarray_cache_lock);
6818 list = g_slist_append (rootlist, klass);
6819 g_hash_table_insert (image->array_cache, eclass, list);
6822 mono_loader_unlock ();
6824 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6830 * mono_array_class_get:
6831 * @element_class: element class
6832 * @rank: the dimension of the array class
6834 * Returns: A class object describing the array with element type @element_type and
6838 mono_array_class_get (MonoClass *eclass, guint32 rank)
6840 return mono_bounded_array_class_get (eclass, rank, FALSE);
6844 * mono_class_instance_size:
6847 * Use to get the size of a class in bytes.
6849 * Returns: The size of an object instance
6852 mono_class_instance_size (MonoClass *klass)
6854 if (!klass->size_inited)
6855 mono_class_init_sizes (klass);
6857 return klass->instance_size;
6861 * mono_class_min_align:
6864 * Use to get the computed minimum alignment requirements for the specified class.
6866 * Returns: minimum alignment requirements
6869 mono_class_min_align (MonoClass *klass)
6871 if (!klass->size_inited)
6872 mono_class_init_sizes (klass);
6874 return klass->min_align;
6878 * mono_class_value_size:
6881 * This function is used for value types, and return the
6882 * space and the alignment to store that kind of value object.
6884 * Returns: the size of a value of kind @klass
6887 mono_class_value_size (MonoClass *klass, guint32 *align)
6891 /* fixme: check disable, because we still have external revereces to
6892 * mscorlib and Dummy Objects
6894 /*g_assert (klass->valuetype);*/
6896 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6899 *align = klass->min_align;
6905 * mono_class_data_size:
6908 * Returns: The size of the static class data
6911 mono_class_data_size (MonoClass *klass)
6914 mono_class_init (klass);
6915 /* This can happen with dynamically created types */
6916 if (!klass->size_inited)
6917 mono_class_init_sizes (klass);
6919 /* in arrays, sizes.class_size is unioned with element_size
6920 * and arrays have no static fields
6924 return klass->sizes.class_size;
6928 * Auxiliary routine to mono_class_get_field
6930 * Takes a field index instead of a field token.
6932 static MonoClassField *
6933 mono_class_get_field_idx (MonoClass *klass, int idx)
6935 mono_class_setup_fields (klass);
6936 if (mono_class_has_failure (klass))
6940 if (klass->image->uncompressed_metadata) {
6942 * klass->field.first points to the FieldPtr table, while idx points into the
6943 * Field table, so we have to do a search.
6945 /*FIXME this is broken for types with multiple fields with the same name.*/
6946 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6949 for (i = 0; i < klass->field.count; ++i)
6950 if (mono_field_get_name (&klass->fields [i]) == name)
6951 return &klass->fields [i];
6952 g_assert_not_reached ();
6954 if (klass->field.count) {
6955 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6956 return &klass->fields [idx - klass->field.first];
6960 klass = klass->parent;
6966 * mono_class_get_field:
6967 * @class: the class to lookup the field.
6968 * @field_token: the field token
6970 * Returns: A MonoClassField representing the type and offset of
6971 * the field, or a NULL value if the field does not belong to this
6975 mono_class_get_field (MonoClass *klass, guint32 field_token)
6977 int idx = mono_metadata_token_index (field_token);
6979 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6981 return mono_class_get_field_idx (klass, idx - 1);
6985 * mono_class_get_field_from_name:
6986 * @klass: the class to lookup the field.
6987 * @name: the field name
6989 * Search the class @klass and it's parents for a field with the name @name.
6991 * Returns: The MonoClassField pointer of the named field or NULL
6994 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6996 return mono_class_get_field_from_name_full (klass, name, NULL);
7000 * mono_class_get_field_from_name_full:
7001 * @klass: the class to lookup the field.
7002 * @name: the field name
7003 * @type: the type of the fields. This optional.
7005 * Search the class @klass and it's parents for a field with the name @name and type @type.
7007 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7008 * of its generic type definition.
7010 * Returns: The MonoClassField pointer of the named field or NULL
7013 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7017 mono_class_setup_fields (klass);
7018 if (mono_class_has_failure (klass))
7022 for (i = 0; i < klass->field.count; ++i) {
7023 MonoClassField *field = &klass->fields [i];
7025 if (strcmp (name, mono_field_get_name (field)) != 0)
7029 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7030 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7035 klass = klass->parent;
7041 * mono_class_get_field_token:
7042 * @field: the field we need the token of
7044 * Get the token of a field. Note that the tokesn is only valid for the image
7045 * the field was loaded from. Don't use this function for fields in dynamic types.
7047 * Returns: The token representing the field in the image it was loaded from.
7050 mono_class_get_field_token (MonoClassField *field)
7052 MonoClass *klass = field->parent;
7055 mono_class_setup_fields (klass);
7060 for (i = 0; i < klass->field.count; ++i) {
7061 if (&klass->fields [i] == field) {
7062 int idx = klass->field.first + i + 1;
7064 if (klass->image->uncompressed_metadata)
7065 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7066 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7069 klass = klass->parent;
7072 g_assert_not_reached ();
7077 mono_field_get_index (MonoClassField *field)
7079 int index = field - field->parent->fields;
7081 g_assert (index >= 0 && index < field->parent->field.count);
7087 * mono_class_get_field_default_value:
7089 * Return the default value of the field as a pointer into the metadata blob.
7092 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7095 guint32 constant_cols [MONO_CONSTANT_SIZE];
7097 MonoClass *klass = field->parent;
7099 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7101 if (!klass->ext || !klass->ext->field_def_values) {
7102 MonoFieldDefaultValue *def_values;
7104 mono_class_alloc_ext (klass);
7106 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7108 mono_image_lock (klass->image);
7109 mono_memory_barrier ();
7110 if (!klass->ext->field_def_values)
7111 klass->ext->field_def_values = def_values;
7112 mono_image_unlock (klass->image);
7115 field_index = mono_field_get_index (field);
7117 if (!klass->ext->field_def_values [field_index].data) {
7118 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7122 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7124 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7125 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7126 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7129 *def_type = klass->ext->field_def_values [field_index].def_type;
7130 return klass->ext->field_def_values [field_index].data;
7134 mono_property_get_index (MonoProperty *prop)
7136 int index = prop - prop->parent->ext->properties;
7138 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7144 * mono_class_get_property_default_value:
7146 * Return the default value of the field as a pointer into the metadata blob.
7149 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7152 guint32 constant_cols [MONO_CONSTANT_SIZE];
7153 MonoClass *klass = property->parent;
7155 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7157 * We don't cache here because it is not used by C# so it's quite rare, but
7158 * we still do the lookup in klass->ext because that is where the data
7159 * is stored for dynamic assemblies.
7162 if (image_is_dynamic (klass->image)) {
7163 int prop_index = mono_property_get_index (property);
7164 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7165 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7166 return klass->ext->prop_def_values [prop_index].data;
7170 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7174 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7175 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7176 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7180 mono_class_get_event_token (MonoEvent *event)
7182 MonoClass *klass = event->parent;
7187 for (i = 0; i < klass->ext->event.count; ++i) {
7188 if (&klass->ext->events [i] == event)
7189 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7192 klass = klass->parent;
7195 g_assert_not_reached ();
7200 * mono_class_get_property_from_name:
7202 * @name: name of the property to lookup in the specified class
7204 * Use this method to lookup a property in a class
7205 * Returns: the MonoProperty with the given name, or NULL if the property
7206 * does not exist on the @klass.
7209 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7213 gpointer iter = NULL;
7214 while ((p = mono_class_get_properties (klass, &iter))) {
7215 if (! strcmp (name, p->name))
7218 klass = klass->parent;
7224 * mono_class_get_property_token:
7225 * @prop: MonoProperty to query
7227 * Returns: The ECMA token for the specified property.
7230 mono_class_get_property_token (MonoProperty *prop)
7232 MonoClass *klass = prop->parent;
7236 gpointer iter = NULL;
7237 while ((p = mono_class_get_properties (klass, &iter))) {
7238 if (&klass->ext->properties [i] == prop)
7239 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7243 klass = klass->parent;
7246 g_assert_not_reached ();
7251 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7253 const char *name, *nspace;
7254 if (image_is_dynamic (image))
7255 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7257 switch (type_token & 0xff000000){
7258 case MONO_TOKEN_TYPE_DEF: {
7259 guint32 cols [MONO_TYPEDEF_SIZE];
7260 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7261 guint tidx = mono_metadata_token_index (type_token);
7263 if (tidx > tt->rows)
7264 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7266 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7267 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7268 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7269 if (strlen (nspace) == 0)
7270 return g_strdup_printf ("%s", name);
7272 return g_strdup_printf ("%s.%s", nspace, name);
7275 case MONO_TOKEN_TYPE_REF: {
7277 guint32 cols [MONO_TYPEREF_SIZE];
7278 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7279 guint tidx = mono_metadata_token_index (type_token);
7282 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7284 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7285 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7286 mono_error_cleanup (&error);
7290 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7291 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7292 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7293 if (strlen (nspace) == 0)
7294 return g_strdup_printf ("%s", name);
7296 return g_strdup_printf ("%s.%s", nspace, name);
7299 case MONO_TOKEN_TYPE_SPEC:
7300 return g_strdup_printf ("Typespec 0x%08x", type_token);
7302 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7307 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7309 if (image_is_dynamic (image))
7310 return g_strdup_printf ("DynamicAssembly %s", image->name);
7312 switch (type_token & 0xff000000){
7313 case MONO_TOKEN_TYPE_DEF:
7314 if (image->assembly)
7315 return mono_stringify_assembly_name (&image->assembly->aname);
7316 else if (image->assembly_name)
7317 return g_strdup (image->assembly_name);
7318 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7319 case MONO_TOKEN_TYPE_REF: {
7321 MonoAssemblyName aname;
7322 guint32 cols [MONO_TYPEREF_SIZE];
7323 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7324 guint32 idx = mono_metadata_token_index (type_token);
7327 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7329 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7330 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7331 mono_error_cleanup (&error);
7334 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7336 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7337 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7338 case MONO_RESOLUTION_SCOPE_MODULE:
7340 return g_strdup ("");
7341 case MONO_RESOLUTION_SCOPE_MODULEREF:
7343 return g_strdup ("");
7344 case MONO_RESOLUTION_SCOPE_TYPEREF:
7346 return g_strdup ("");
7347 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7348 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7349 return mono_stringify_assembly_name (&aname);
7351 g_assert_not_reached ();
7355 case MONO_TOKEN_TYPE_SPEC:
7357 return g_strdup ("");
7359 g_assert_not_reached ();
7366 * mono_class_get_full:
7367 * @image: the image where the class resides
7368 * @type_token: the token for the class
7369 * @context: the generic context used to evaluate generic instantiations in
7370 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7372 * Returns: The MonoClass that represents @type_token in @image
7375 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7379 klass = mono_class_get_checked (image, type_token, &error);
7381 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7382 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7384 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7390 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7394 mono_error_init (error);
7395 klass = mono_class_get_checked (image, type_token, error);
7397 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7398 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7403 * mono_class_get_checked:
7404 * @image: the image where the class resides
7405 * @type_token: the token for the class
7406 * @error: error object to return any error
7408 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7411 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7413 MonoClass *klass = NULL;
7415 mono_error_init (error);
7417 if (image_is_dynamic (image)) {
7418 int table = mono_metadata_token_table (type_token);
7420 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7421 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7424 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7428 switch (type_token & 0xff000000){
7429 case MONO_TOKEN_TYPE_DEF:
7430 klass = mono_class_create_from_typedef (image, type_token, error);
7432 case MONO_TOKEN_TYPE_REF:
7433 klass = mono_class_from_typeref_checked (image, type_token, error);
7435 case MONO_TOKEN_TYPE_SPEC:
7436 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7439 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7443 /* Generic case, should be avoided for when a better error is possible. */
7444 if (!klass && mono_error_ok (error)) {
7445 char *name = mono_class_name_from_token (image, type_token);
7446 char *assembly = mono_assembly_name_from_token (image, type_token);
7447 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7455 * mono_type_get_checked:
7456 * @image: the image where the type resides
7457 * @type_token: the token for the type
7458 * @context: the generic context used to evaluate generic instantiations in
7459 * @error: Error handling context
7461 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7463 * Returns: The MonoType that represents @type_token in @image
7466 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7468 MonoType *type = NULL;
7469 gboolean inflated = FALSE;
7471 mono_error_init (error);
7473 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7474 if (image_is_dynamic (image)) {
7475 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7476 return_val_if_nok (error, NULL);
7477 return mono_class_get_type (klass);
7480 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7481 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7488 return mono_class_get_type (klass);
7491 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7498 MonoType *tmp = type;
7499 type = mono_class_get_type (mono_class_from_mono_type (type));
7500 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7501 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7502 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7504 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7506 if (type->type != tmp->type)
7509 mono_metadata_free_type (tmp);
7516 * @image: image where the class token will be looked up.
7517 * @type_token: a type token from the image
7519 * Returns the MonoClass with the given @type_token on the @image
7522 mono_class_get (MonoImage *image, guint32 type_token)
7524 return mono_class_get_full (image, type_token, NULL);
7528 * mono_image_init_name_cache:
7530 * Initializes the class name cache stored in image->name_cache.
7532 * LOCKING: Acquires the corresponding image lock.
7535 mono_image_init_name_cache (MonoImage *image)
7537 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7538 guint32 cols [MONO_TYPEDEF_SIZE];
7541 guint32 i, visib, nspace_index;
7542 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7544 if (image->name_cache)
7547 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7549 if (image_is_dynamic (image)) {
7550 mono_image_lock (image);
7551 if (image->name_cache) {
7552 /* Somebody initialized it before us */
7553 g_hash_table_destroy (the_name_cache);
7555 mono_atomic_store_release (&image->name_cache, the_name_cache);
7557 mono_image_unlock (image);
7561 /* Temporary hash table to avoid lookups in the nspace_table */
7562 name_cache2 = g_hash_table_new (NULL, NULL);
7564 for (i = 1; i <= t->rows; ++i) {
7565 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7566 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7568 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7569 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7571 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7573 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7574 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7576 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7577 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7578 if (!nspace_table) {
7579 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7580 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7581 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7584 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7587 /* Load type names from EXPORTEDTYPES table */
7589 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7590 guint32 cols [MONO_EXP_TYPE_SIZE];
7593 for (i = 0; i < t->rows; ++i) {
7594 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7596 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7597 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7601 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7602 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7604 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7605 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7606 if (!nspace_table) {
7607 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7608 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7609 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7612 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7616 g_hash_table_destroy (name_cache2);
7618 mono_image_lock (image);
7619 if (image->name_cache) {
7620 /* Somebody initialized it before us */
7621 g_hash_table_destroy (the_name_cache);
7623 mono_atomic_store_release (&image->name_cache, the_name_cache);
7625 mono_image_unlock (image);
7628 /*FIXME Only dynamic assemblies should allow this operation.*/
7630 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7631 const char *name, guint32 index)
7633 GHashTable *nspace_table;
7634 GHashTable *name_cache;
7637 mono_image_init_name_cache (image);
7638 mono_image_lock (image);
7640 name_cache = image->name_cache;
7641 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7642 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7643 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7646 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7647 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7649 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7651 mono_image_unlock (image);
7660 find_nocase (gpointer key, gpointer value, gpointer user_data)
7662 char *name = (char*)key;
7663 FindUserData *data = (FindUserData*)user_data;
7665 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7666 data->value = value;
7670 * mono_class_from_name_case:
7671 * @image: The MonoImage where the type is looked up in
7672 * @name_space: the type namespace
7673 * @name: the type short name.
7674 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7676 * Obtains a MonoClass with a given namespace and a given name which
7677 * is located in the given MonoImage. The namespace and name
7678 * lookups are case insensitive.
7681 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7684 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7685 mono_error_cleanup (&error);
7691 * mono_class_from_name_case:
7692 * @image: The MonoImage where the type is looked up in
7693 * @name_space: the type namespace
7694 * @name: the type short name.
7697 * Obtains a MonoClass with a given namespace and a given name which
7698 * is located in the given MonoImage. The namespace and name
7699 * lookups are case insensitive.
7701 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7702 * was not found. The @error object will contain information about the problem
7706 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7708 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7709 guint32 cols [MONO_TYPEDEF_SIZE];
7714 mono_error_init (error);
7716 if (image_is_dynamic (image)) {
7718 FindUserData user_data;
7720 mono_image_init_name_cache (image);
7721 mono_image_lock (image);
7723 user_data.key = name_space;
7724 user_data.value = NULL;
7725 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7727 if (user_data.value) {
7728 GHashTable *nspace_table = (GHashTable*)user_data.value;
7730 user_data.key = name;
7731 user_data.value = NULL;
7733 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7735 if (user_data.value)
7736 token = GPOINTER_TO_UINT (user_data.value);
7739 mono_image_unlock (image);
7742 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7748 /* add a cache if needed */
7749 for (i = 1; i <= t->rows; ++i) {
7750 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7751 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7753 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7754 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7756 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7758 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7759 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7760 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7761 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7767 return_nested_in (MonoClass *klass, char *nested)
7770 char *s = strchr (nested, '/');
7771 gpointer iter = NULL;
7778 while ((found = mono_class_get_nested_types (klass, &iter))) {
7779 if (strcmp (found->name, nested) == 0) {
7781 return return_nested_in (found, s);
7789 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7791 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7792 MonoImage *file_image;
7796 mono_error_init (error);
7799 * The EXPORTEDTYPES table only contains public types, so have to search the
7801 * Note: image->modules contains the contents of the MODULEREF table, while
7802 * the real module list is in the FILE table.
7804 for (i = 0; i < file_table->rows; i++) {
7805 guint32 cols [MONO_FILE_SIZE];
7806 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7807 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7810 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7812 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7813 if (klass || !is_ok (error))
7822 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7824 GHashTable *nspace_table;
7825 MonoImage *loaded_image;
7832 mono_error_init (error);
7834 // Checking visited images avoids stack overflows when cyclic references exist.
7835 if (g_hash_table_lookup (visited_images, image))
7838 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7840 if ((nested = strchr (name, '/'))) {
7841 int pos = nested - name;
7842 int len = strlen (name);
7845 memcpy (buf, name, len + 1);
7847 nested = buf + pos + 1;
7851 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7852 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7853 gboolean res = get_class_from_name (image, name_space, name, &klass);
7856 klass = search_modules (image, name_space, name, error);
7861 return klass ? return_nested_in (klass, nested) : NULL;
7867 mono_image_init_name_cache (image);
7868 mono_image_lock (image);
7870 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7873 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7875 mono_image_unlock (image);
7877 if (!token && image_is_dynamic (image) && image->modules) {
7878 /* Search modules as well */
7879 for (i = 0; i < image->module_count; ++i) {
7880 MonoImage *module = image->modules [i];
7882 klass = mono_class_from_name_checked (module, name_space, name, error);
7883 if (klass || !is_ok (error))
7889 klass = search_modules (image, name_space, name, error);
7890 if (klass || !is_ok (error))
7895 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7896 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7897 guint32 cols [MONO_EXP_TYPE_SIZE];
7900 idx = mono_metadata_token_index (token);
7902 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7904 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7905 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7906 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7909 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7911 return klass ? return_nested_in (klass, nested) : NULL;
7913 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7914 guint32 assembly_idx;
7916 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7918 mono_assembly_load_reference (image, assembly_idx - 1);
7919 g_assert (image->references [assembly_idx - 1]);
7920 if (image->references [assembly_idx - 1] == (gpointer)-1)
7922 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7924 return klass ? return_nested_in (klass, nested) : NULL;
7927 g_assert_not_reached ();
7931 token = MONO_TOKEN_TYPE_DEF | token;
7933 klass = mono_class_get_checked (image, token, error);
7935 return return_nested_in (klass, nested);
7940 * mono_class_from_name_checked:
7941 * @image: The MonoImage where the type is looked up in
7942 * @name_space: the type namespace
7943 * @name: the type short name.
7945 * Obtains a MonoClass with a given namespace and a given name which
7946 * is located in the given MonoImage.
7948 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7949 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7952 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7955 GHashTable *visited_images;
7957 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7959 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7961 g_hash_table_destroy (visited_images);
7967 * mono_class_from_name:
7968 * @image: The MonoImage where the type is looked up in
7969 * @name_space: the type namespace
7970 * @name: the type short name.
7972 * Obtains a MonoClass with a given namespace and a given name which
7973 * is located in the given MonoImage.
7975 * To reference nested classes, use the "/" character as a separator.
7976 * For example use "Foo/Bar" to reference the class Bar that is nested
7977 * inside Foo, like this: "class Foo { class Bar {} }".
7980 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7985 klass = mono_class_from_name_checked (image, name_space, name, &error);
7986 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7992 * mono_class_load_from_name:
7993 * @image: The MonoImage where the type is looked up in
7994 * @name_space: the type namespace
7995 * @name: the type short name.
7997 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7998 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7999 * If they are missing. Thing of System.Object or System.String.
8002 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8007 klass = mono_class_from_name_checked (image, name_space, name, &error);
8009 g_error ("Runtime critical type %s.%s not found", name_space, name);
8010 if (!mono_error_ok (&error))
8011 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8016 * mono_class_try_load_from_name:
8017 * @image: The MonoImage where the type is looked up in
8018 * @name_space: the type namespace
8019 * @name: the type short name.
8021 * This function tries to load a type, returning the class was found or NULL otherwise.
8022 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8024 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8025 * a type that we would otherwise assume to be available but was not due some error.
8029 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8034 klass = mono_class_from_name_checked (image, name_space, name, &error);
8035 if (!mono_error_ok (&error))
8036 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8042 * mono_class_is_subclass_of:
8043 * @klass: class to probe if it is a subclass of another one
8044 * @klassc: the class we suspect is the base class
8045 * @check_interfaces: whether we should perform interface checks
8047 * This method determines whether @klass is a subclass of @klassc.
8049 * If the @check_interfaces flag is set, then if @klassc is an interface
8050 * this method return TRUE if the @klass implements the interface or
8051 * if @klass is an interface, if one of its base classes is @klass.
8053 * If @check_interfaces is false then, then if @klass is not an interface
8054 * then it returns TRUE if the @klass is a subclass of @klassc.
8056 * if @klass is an interface and @klassc is System.Object, then this function
8061 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8062 gboolean check_interfaces)
8064 /* FIXME test for interfaces with variant generic arguments */
8065 mono_class_init (klass);
8066 mono_class_init (klassc);
8068 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8069 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8071 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8074 for (i = 0; i < klass->interface_count; i ++) {
8075 MonoClass *ic = klass->interfaces [i];
8080 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8085 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8088 if (klassc == mono_defaults.object_class)
8095 mono_type_is_generic_argument (MonoType *type)
8097 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8101 mono_class_has_variant_generic_params (MonoClass *klass)
8104 MonoGenericContainer *container;
8106 if (!mono_class_is_ginst (klass))
8109 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8111 for (i = 0; i < container->type_argc; ++i)
8112 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8119 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8121 if (target == candidate)
8124 if (check_for_reference_conv &&
8125 mono_type_is_generic_argument (&target->byval_arg) &&
8126 mono_type_is_generic_argument (&candidate->byval_arg)) {
8127 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8128 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8130 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8133 if (!mono_class_is_assignable_from (target, candidate))
8139 * @container the generic container from the GTD
8140 * @klass: the class to be assigned to
8141 * @oklass: the source class
8143 * Both @klass and @oklass must be instances of the same generic interface.
8145 * Returns: TRUE if @klass can be assigned to a @klass variable
8148 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8151 MonoType **klass_argv, **oklass_argv;
8152 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8153 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8155 if (klass == oklass)
8158 /*Viable candidates are instances of the same generic interface*/
8159 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8162 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8163 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8165 for (j = 0; j < container->type_argc; ++j) {
8166 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8167 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8169 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8173 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8174 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8176 if (param1_class != param2_class) {
8177 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8178 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8180 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8181 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8191 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8193 MonoGenericParam *gparam, *ogparam;
8194 MonoGenericParamInfo *tinfo, *cinfo;
8195 MonoClass **candidate_class;
8196 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8199 if (target == candidate)
8201 if (target->byval_arg.type != candidate->byval_arg.type)
8204 gparam = target->byval_arg.data.generic_param;
8205 ogparam = candidate->byval_arg.data.generic_param;
8206 tinfo = mono_generic_param_info (gparam);
8207 cinfo = mono_generic_param_info (ogparam);
8209 class_constraint_satisfied = FALSE;
8210 valuetype_constraint_satisfied = FALSE;
8212 /*candidate must have a super set of target's special constraints*/
8213 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8214 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8216 if (cinfo->constraints) {
8217 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8218 MonoClass *cc = *candidate_class;
8220 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8221 class_constraint_satisfied = TRUE;
8222 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8223 valuetype_constraint_satisfied = TRUE;
8226 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8227 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8229 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8231 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8233 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8234 valuetype_constraint_satisfied)) {
8239 /*candidate type constraints must be a superset of target's*/
8240 if (tinfo->constraints) {
8241 MonoClass **target_class;
8242 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8243 MonoClass *tc = *target_class;
8246 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8247 * check it's constraints since it satisfy the constraint by itself.
8249 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8252 if (!cinfo->constraints)
8255 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8256 MonoClass *cc = *candidate_class;
8258 if (mono_class_is_assignable_from (tc, cc))
8262 * This happens when we have the following:
8264 * Bar<K> where K : IFace
8265 * Foo<T, U> where T : U where U : IFace
8267 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8270 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8271 if (mono_gparam_is_assignable_from (target, cc))
8275 if (!*candidate_class)
8280 /*candidate itself must have a constraint that satisfy target*/
8281 if (cinfo->constraints) {
8282 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8283 MonoClass *cc = *candidate_class;
8284 if (mono_class_is_assignable_from (target, cc))
8292 * mono_class_is_assignable_from:
8293 * @klass: the class to be assigned to
8294 * @oklass: the source class
8296 * Returns: TRUE if an instance of object oklass can be assigned to an
8297 * instance of object @klass
8300 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8303 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8305 mono_class_init (klass);
8307 if (!oklass->inited)
8308 mono_class_init (oklass);
8310 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8313 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8314 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8316 return mono_gparam_is_assignable_from (klass, oklass);
8319 if (MONO_CLASS_IS_INTERFACE (klass)) {
8320 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8321 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8322 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8326 for (i = 0; constraints [i]; ++i) {
8327 if (mono_class_is_assignable_from (klass, constraints [i]))
8335 /* interface_offsets might not be set for dynamic classes */
8336 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8338 * oklass might be a generic type parameter but they have
8339 * interface_offsets set.
8341 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8342 if (!is_ok (&error)) {
8343 mono_error_cleanup (&error);
8348 if (!oklass->interface_bitmap)
8349 /* Happens with generic instances of not-yet created dynamic types */
8351 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8354 if (mono_class_has_variant_generic_params (klass)) {
8356 mono_class_setup_interfaces (oklass, &error);
8357 if (!mono_error_ok (&error)) {
8358 mono_error_cleanup (&error);
8362 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8363 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8364 MonoClass *iface = oklass->interfaces_packed [i];
8366 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8371 } else if (klass->delegate) {
8372 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8374 }else if (klass->rank) {
8375 MonoClass *eclass, *eoclass;
8377 if (oklass->rank != klass->rank)
8380 /* vectors vs. one dimensional arrays */
8381 if (oklass->byval_arg.type != klass->byval_arg.type)
8384 eclass = klass->cast_class;
8385 eoclass = oklass->cast_class;
8388 * a is b does not imply a[] is b[] when a is a valuetype, and
8389 * b is a reference type.
8392 if (eoclass->valuetype) {
8393 if ((eclass == mono_defaults.enum_class) ||
8394 (eclass == mono_defaults.enum_class->parent) ||
8395 (eclass == mono_defaults.object_class))
8399 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8400 } else if (mono_class_is_nullable (klass)) {
8401 if (mono_class_is_nullable (oklass))
8402 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8404 return mono_class_is_assignable_from (klass->cast_class, oklass);
8405 } else if (klass == mono_defaults.object_class)
8408 return mono_class_has_parent (oklass, klass);
8411 /*Check if @oklass is variant compatible with @klass.*/
8413 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8416 MonoType **klass_argv, **oklass_argv;
8417 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8418 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8420 /*Viable candidates are instances of the same generic interface*/
8421 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8424 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8425 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8427 for (j = 0; j < container->type_argc; ++j) {
8428 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8429 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8431 if (param1_class->valuetype != param2_class->valuetype)
8435 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8436 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8438 if (param1_class != param2_class) {
8439 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8440 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8442 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8443 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8451 /*Check if @candidate implements the interface @target*/
8453 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8457 gboolean is_variant = mono_class_has_variant_generic_params (target);
8459 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8460 if (mono_class_is_variant_compatible_slow (target, candidate))
8465 if (candidate == target)
8468 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8469 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8470 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8472 if (tb && tb->interfaces) {
8473 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8474 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8475 MonoClass *iface_class;
8477 /* we can't realize the type here since it can do pretty much anything. */
8480 iface_class = mono_class_from_mono_type (iface->type);
8481 if (iface_class == target)
8483 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8485 if (mono_class_implement_interface_slow (target, iface_class))
8490 /*setup_interfaces don't mono_class_init anything*/
8491 /*FIXME this doesn't handle primitive type arrays.
8492 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8493 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8495 mono_class_setup_interfaces (candidate, &error);
8496 if (!mono_error_ok (&error)) {
8497 mono_error_cleanup (&error);
8501 for (i = 0; i < candidate->interface_count; ++i) {
8502 if (candidate->interfaces [i] == target)
8505 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8508 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8512 candidate = candidate->parent;
8513 } while (candidate);
8519 * Check if @oklass can be assigned to @klass.
8520 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8523 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8525 if (candidate == target)
8527 if (target == mono_defaults.object_class)
8530 if (mono_class_has_parent (candidate, target))
8533 /*If target is not an interface there is no need to check them.*/
8534 if (MONO_CLASS_IS_INTERFACE (target))
8535 return mono_class_implement_interface_slow (target, candidate);
8537 if (target->delegate && mono_class_has_variant_generic_params (target))
8538 return mono_class_is_variant_compatible (target, candidate, FALSE);
8541 MonoClass *eclass, *eoclass;
8543 if (target->rank != candidate->rank)
8546 /* vectors vs. one dimensional arrays */
8547 if (target->byval_arg.type != candidate->byval_arg.type)
8550 eclass = target->cast_class;
8551 eoclass = candidate->cast_class;
8554 * a is b does not imply a[] is b[] when a is a valuetype, and
8555 * b is a reference type.
8558 if (eoclass->valuetype) {
8559 if ((eclass == mono_defaults.enum_class) ||
8560 (eclass == mono_defaults.enum_class->parent) ||
8561 (eclass == mono_defaults.object_class))
8565 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8567 /*FIXME properly handle nullables */
8568 /*FIXME properly handle (M)VAR */
8573 * mono_class_get_cctor:
8574 * @klass: A MonoClass pointer
8576 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8579 mono_class_get_cctor (MonoClass *klass)
8581 MonoCachedClassInfo cached_info;
8583 if (image_is_dynamic (klass->image)) {
8585 * has_cctor is not set for these classes because mono_class_init () is
8588 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8591 if (!klass->has_cctor)
8594 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8596 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8597 if (!mono_error_ok (&error))
8598 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8602 if (mono_class_is_ginst (klass) && !klass->methods)
8603 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8605 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8609 * mono_class_get_finalizer:
8610 * @klass: The MonoClass pointer
8612 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8615 mono_class_get_finalizer (MonoClass *klass)
8617 MonoCachedClassInfo cached_info;
8620 mono_class_init (klass);
8621 if (!mono_class_has_finalizer (klass))
8624 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8626 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8627 if (!mono_error_ok (&error))
8628 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8631 mono_class_setup_vtable (klass);
8632 return klass->vtable [finalize_slot];
8637 * mono_class_needs_cctor_run:
8638 * @klass: the MonoClass pointer
8639 * @caller: a MonoMethod describing the caller
8641 * Determines whenever the class has a static constructor and whenever it
8642 * needs to be called when executing CALLER.
8645 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8649 method = mono_class_get_cctor (klass);
8651 return (method == caller) ? FALSE : TRUE;
8657 * mono_class_array_element_size:
8660 * Returns: The number of bytes an element of type @klass
8661 * uses when stored into an array.
8664 mono_class_array_element_size (MonoClass *klass)
8666 MonoType *type = &klass->byval_arg;
8669 switch (type->type) {
8672 case MONO_TYPE_BOOLEAN:
8676 case MONO_TYPE_CHAR:
8685 case MONO_TYPE_CLASS:
8686 case MONO_TYPE_STRING:
8687 case MONO_TYPE_OBJECT:
8688 case MONO_TYPE_SZARRAY:
8689 case MONO_TYPE_ARRAY:
8690 return sizeof (gpointer);
8695 case MONO_TYPE_VALUETYPE:
8696 if (type->data.klass->enumtype) {
8697 type = mono_class_enum_basetype (type->data.klass);
8698 klass = klass->element_class;
8701 return mono_class_instance_size (klass) - sizeof (MonoObject);
8702 case MONO_TYPE_GENERICINST:
8703 type = &type->data.generic_class->container_class->byval_arg;
8706 case MONO_TYPE_MVAR: {
8709 return mono_type_size (type, &align);
8711 case MONO_TYPE_VOID:
8715 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8721 * mono_array_element_size:
8722 * @ac: pointer to a #MonoArrayClass
8724 * Returns: The size of single array element.
8727 mono_array_element_size (MonoClass *ac)
8729 g_assert (ac->rank);
8730 return ac->sizes.element_size;
8734 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8735 MonoGenericContext *context)
8738 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8739 g_assert (mono_error_ok (&error));
8744 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8745 MonoGenericContext *context, MonoError *error)
8747 mono_error_init (error);
8749 if (image_is_dynamic (image)) {
8750 MonoClass *tmp_handle_class;
8751 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8753 mono_error_assert_ok (error);
8754 g_assert (tmp_handle_class);
8756 *handle_class = tmp_handle_class;
8758 if (tmp_handle_class == mono_defaults.typehandle_class)
8759 return &((MonoClass*)obj)->byval_arg;
8764 switch (token & 0xff000000) {
8765 case MONO_TOKEN_TYPE_DEF:
8766 case MONO_TOKEN_TYPE_REF:
8767 case MONO_TOKEN_TYPE_SPEC: {
8770 *handle_class = mono_defaults.typehandle_class;
8771 type = mono_type_get_checked (image, token, context, error);
8775 mono_class_init (mono_class_from_mono_type (type));
8776 /* We return a MonoType* as handle */
8779 case MONO_TOKEN_FIELD_DEF: {
8781 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8783 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8787 *handle_class = mono_defaults.fieldhandle_class;
8788 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8792 mono_class_init (klass);
8793 return mono_class_get_field (klass, token);
8795 case MONO_TOKEN_METHOD_DEF:
8796 case MONO_TOKEN_METHOD_SPEC: {
8798 meth = mono_get_method_checked (image, token, NULL, context, error);
8800 *handle_class = mono_defaults.methodhandle_class;
8806 case MONO_TOKEN_MEMBER_REF: {
8807 guint32 cols [MONO_MEMBERREF_SIZE];
8809 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8810 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8811 mono_metadata_decode_blob_size (sig, &sig);
8812 if (*sig == 0x6) { /* it's a field */
8814 MonoClassField *field;
8815 field = mono_field_from_token_checked (image, token, &klass, context, error);
8817 *handle_class = mono_defaults.fieldhandle_class;
8821 meth = mono_get_method_checked (image, token, NULL, context, error);
8823 *handle_class = mono_defaults.methodhandle_class;
8828 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8834 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8836 MonoClass *handle_class;
8837 mono_error_init (error);
8838 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8842 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8844 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8847 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8850 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8852 get_cached_class_info = func;
8856 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8858 if (!get_cached_class_info)
8861 return get_cached_class_info (klass, res);
8865 mono_install_get_class_from_name (MonoGetClassFromName func)
8867 get_class_from_name = func;
8871 * mono_class_get_image:
8873 * Use this method to get the `MonoImage*` where this class came from.
8875 * Returns: The image where this class is defined.
8878 mono_class_get_image (MonoClass *klass)
8880 return klass->image;
8884 * mono_class_get_element_class:
8885 * @klass: the MonoClass to act on
8887 * Use this function to get the element class of an array.
8889 * Returns: The element class of an array.
8892 mono_class_get_element_class (MonoClass *klass)
8894 return klass->element_class;
8898 * mono_class_is_valuetype:
8899 * @klass: the MonoClass to act on
8901 * Use this method to determine if the provided `MonoClass*` represents a value type,
8902 * or a reference type.
8904 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8907 mono_class_is_valuetype (MonoClass *klass)
8909 return klass->valuetype;
8913 * mono_class_is_enum:
8914 * @klass: the MonoClass to act on
8916 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8918 * Returns: TRUE if the MonoClass represents an enumeration.
8921 mono_class_is_enum (MonoClass *klass)
8923 return klass->enumtype;
8927 * mono_class_enum_basetype:
8928 * @klass: the MonoClass to act on
8930 * Use this function to get the underlying type for an enumeration value.
8932 * Returns: The underlying type representation for an enumeration.
8935 mono_class_enum_basetype (MonoClass *klass)
8937 if (klass->element_class == klass)
8938 /* SRE or broken types */
8941 return &klass->element_class->byval_arg;
8945 * mono_class_get_parent
8946 * @klass: the MonoClass to act on
8948 * Returns: The parent class for this class.
8951 mono_class_get_parent (MonoClass *klass)
8953 return klass->parent;
8957 * mono_class_get_nesting_type:
8958 * @klass: the MonoClass to act on
8960 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8962 * If the return is NULL, this indicates that this class is not nested.
8964 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8967 mono_class_get_nesting_type (MonoClass *klass)
8969 return klass->nested_in;
8973 * mono_class_get_rank:
8974 * @klass: the MonoClass to act on
8976 * Returns: The rank for the array (the number of dimensions).
8979 mono_class_get_rank (MonoClass *klass)
8985 * mono_class_get_name
8986 * @klass: the MonoClass to act on
8988 * Returns: The name of the class.
8991 mono_class_get_name (MonoClass *klass)
8997 * mono_class_get_namespace:
8998 * @klass: the MonoClass to act on
9000 * Returns: The namespace of the class.
9003 mono_class_get_namespace (MonoClass *klass)
9005 return klass->name_space;
9009 * mono_class_get_type:
9010 * @klass: the MonoClass to act on
9012 * This method returns the internal Type representation for the class.
9014 * Returns: The MonoType from the class.
9017 mono_class_get_type (MonoClass *klass)
9019 return &klass->byval_arg;
9023 * mono_class_get_type_token:
9024 * @klass: the MonoClass to act on
9026 * This method returns type token for the class.
9028 * Returns: The type token for the class.
9031 mono_class_get_type_token (MonoClass *klass)
9033 return klass->type_token;
9037 * mono_class_get_byref_type:
9038 * @klass: the MonoClass to act on
9043 mono_class_get_byref_type (MonoClass *klass)
9045 return &klass->this_arg;
9049 * mono_class_num_fields:
9050 * @klass: the MonoClass to act on
9052 * Returns: The number of static and instance fields in the class.
9055 mono_class_num_fields (MonoClass *klass)
9057 return klass->field.count;
9061 * mono_class_num_methods:
9062 * @klass: the MonoClass to act on
9064 * Returns: The number of methods in the class.
9067 mono_class_num_methods (MonoClass *klass)
9069 return klass->method.count;
9073 * mono_class_num_properties
9074 * @klass: the MonoClass to act on
9076 * Returns: The number of properties in the class.
9079 mono_class_num_properties (MonoClass *klass)
9081 mono_class_setup_properties (klass);
9083 return klass->ext->property.count;
9087 * mono_class_num_events:
9088 * @klass: the MonoClass to act on
9090 * Returns: The number of events in the class.
9093 mono_class_num_events (MonoClass *klass)
9095 mono_class_setup_events (klass);
9097 return klass->ext->event.count;
9101 * mono_class_get_fields:
9102 * @klass: the MonoClass to act on
9104 * This routine is an iterator routine for retrieving the fields in a class.
9106 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9107 * iterate over all of the elements. When no more values are
9108 * available, the return value is NULL.
9110 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9113 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9115 MonoClassField* field;
9119 mono_class_setup_fields (klass);
9120 if (mono_class_has_failure (klass))
9122 /* start from the first */
9123 if (klass->field.count) {
9124 *iter = &klass->fields [0];
9125 return &klass->fields [0];
9131 field = (MonoClassField *)*iter;
9133 if (field < &klass->fields [klass->field.count]) {
9141 * mono_class_get_methods
9142 * @klass: the MonoClass to act on
9144 * This routine is an iterator routine for retrieving the fields in a class.
9146 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9147 * iterate over all of the elements. When no more values are
9148 * available, the return value is NULL.
9150 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9153 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9155 MonoMethod** method;
9159 mono_class_setup_methods (klass);
9162 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9163 * FIXME we should better report this error to the caller
9165 if (!klass->methods)
9167 /* start from the first */
9168 if (klass->method.count) {
9169 *iter = &klass->methods [0];
9170 return klass->methods [0];
9176 method = (MonoMethod **)*iter;
9178 if (method < &klass->methods [klass->method.count]) {
9186 * mono_class_get_virtual_methods:
9188 * Iterate over the virtual methods of KLASS.
9190 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9193 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9195 MonoMethod** method;
9198 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9200 mono_class_setup_methods (klass);
9202 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9203 * FIXME we should better report this error to the caller
9205 if (!klass->methods)
9207 /* start from the first */
9208 method = &klass->methods [0];
9210 method = (MonoMethod **)*iter;
9213 while (method < &klass->methods [klass->method.count]) {
9214 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9218 if (method < &klass->methods [klass->method.count]) {
9225 /* Search directly in metadata to avoid calling setup_methods () */
9226 MonoMethod *res = NULL;
9232 start_index = GPOINTER_TO_UINT (*iter);
9235 for (i = start_index; i < klass->method.count; ++i) {
9238 /* klass->method.first points into the methodptr table */
9239 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9241 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9245 if (i < klass->method.count) {
9247 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9248 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9250 /* Add 1 here so the if (*iter) check fails */
9251 *iter = GUINT_TO_POINTER (i + 1);
9260 * mono_class_get_properties:
9261 * @klass: the MonoClass to act on
9263 * This routine is an iterator routine for retrieving the properties in a class.
9265 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9266 * iterate over all of the elements. When no more values are
9267 * available, the return value is NULL.
9269 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9272 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9274 MonoProperty* property;
9278 mono_class_setup_properties (klass);
9279 /* start from the first */
9280 if (klass->ext->property.count) {
9281 *iter = &klass->ext->properties [0];
9282 return (MonoProperty *)*iter;
9288 property = (MonoProperty *)*iter;
9290 if (property < &klass->ext->properties [klass->ext->property.count]) {
9292 return (MonoProperty *)*iter;
9298 * mono_class_get_events:
9299 * @klass: the MonoClass to act on
9301 * This routine is an iterator routine for retrieving the properties in a class.
9303 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9304 * iterate over all of the elements. When no more values are
9305 * available, the return value is NULL.
9307 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9310 mono_class_get_events (MonoClass* klass, gpointer *iter)
9316 mono_class_setup_events (klass);
9317 /* start from the first */
9318 if (klass->ext->event.count) {
9319 *iter = &klass->ext->events [0];
9320 return (MonoEvent *)*iter;
9326 event = (MonoEvent *)*iter;
9328 if (event < &klass->ext->events [klass->ext->event.count]) {
9330 return (MonoEvent *)*iter;
9336 * mono_class_get_interfaces
9337 * @klass: the MonoClass to act on
9339 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9341 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9342 * iterate over all of the elements. When no more values are
9343 * available, the return value is NULL.
9345 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9348 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9356 mono_class_init (klass);
9357 if (!klass->interfaces_inited) {
9358 mono_class_setup_interfaces (klass, &error);
9359 if (!mono_error_ok (&error)) {
9360 mono_error_cleanup (&error);
9364 /* start from the first */
9365 if (klass->interface_count) {
9366 *iter = &klass->interfaces [0];
9367 return klass->interfaces [0];
9373 iface = (MonoClass **)*iter;
9375 if (iface < &klass->interfaces [klass->interface_count]) {
9383 setup_nested_types (MonoClass *klass)
9386 GList *classes, *nested_classes, *l;
9389 if (klass->nested_classes_inited)
9392 if (!klass->type_token)
9393 klass->nested_classes_inited = TRUE;
9395 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9399 guint32 cols [MONO_NESTED_CLASS_SIZE];
9400 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9401 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9402 if (!mono_error_ok (&error)) {
9403 /*FIXME don't swallow the error message*/
9404 mono_error_cleanup (&error);
9406 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9410 classes = g_list_prepend (classes, nclass);
9412 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9415 mono_class_alloc_ext (klass);
9417 nested_classes = NULL;
9418 for (l = classes; l; l = l->next)
9419 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9420 g_list_free (classes);
9422 mono_image_lock (klass->image);
9424 mono_memory_barrier ();
9425 if (!klass->nested_classes_inited) {
9426 klass->ext->nested_classes = nested_classes;
9427 mono_memory_barrier ();
9428 klass->nested_classes_inited = TRUE;
9431 mono_image_unlock (klass->image);
9435 * mono_class_get_nested_types
9436 * @klass: the MonoClass to act on
9438 * This routine is an iterator routine for retrieving the nested types of a class.
9439 * This works only if @klass is non-generic, or a generic type definition.
9441 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9442 * iterate over all of the elements. When no more values are
9443 * available, the return value is NULL.
9445 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9448 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9454 if (!klass->nested_classes_inited)
9455 setup_nested_types (klass);
9458 /* start from the first */
9459 if (klass->ext && klass->ext->nested_classes) {
9460 *iter = klass->ext->nested_classes;
9461 return (MonoClass *)klass->ext->nested_classes->data;
9463 /* no nested types */
9467 item = (GList *)*iter;
9471 return (MonoClass *)item->data;
9478 * mono_class_is_delegate
9479 * @klass: the MonoClass to act on
9481 * Returns: TRUE if the MonoClass represents a System.Delegate.
9484 mono_class_is_delegate (MonoClass *klass)
9486 return klass->delegate;
9490 * mono_class_implements_interface
9491 * @klass: The MonoClass to act on
9492 * @interface: The interface to check if @klass implements.
9494 * Returns: TRUE if @klass implements @interface.
9497 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9499 return mono_class_is_assignable_from (iface, klass);
9503 * mono_field_get_name:
9504 * @field: the MonoClassField to act on
9506 * Returns: The name of the field.
9509 mono_field_get_name (MonoClassField *field)
9515 * mono_field_get_type:
9516 * @field: the MonoClassField to act on
9518 * Returns: MonoType of the field.
9521 mono_field_get_type (MonoClassField *field)
9524 MonoType *type = mono_field_get_type_checked (field, &error);
9525 if (!mono_error_ok (&error)) {
9526 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9527 mono_error_cleanup (&error);
9534 * mono_field_get_type_checked:
9535 * @field: the MonoClassField to act on
9536 * @error: used to return any erro found while retrieving @field type
9538 * Returns: MonoType of the field.
9541 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9543 mono_error_init (error);
9545 mono_field_resolve_type (field, error);
9550 * mono_field_get_parent:
9551 * @field: the MonoClassField to act on
9553 * Returns: MonoClass where the field was defined.
9556 mono_field_get_parent (MonoClassField *field)
9558 return field->parent;
9562 * mono_field_get_flags;
9563 * @field: the MonoClassField to act on
9565 * The metadata flags for a field are encoded using the
9566 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9568 * Returns: The flags for the field.
9571 mono_field_get_flags (MonoClassField *field)
9574 return mono_field_resolve_flags (field);
9575 return field->type->attrs;
9579 * mono_field_get_offset:
9580 * @field: the MonoClassField to act on
9582 * Returns: The field offset.
9585 mono_field_get_offset (MonoClassField *field)
9587 return field->offset;
9591 mono_field_get_rva (MonoClassField *field)
9595 MonoClass *klass = field->parent;
9596 MonoFieldDefaultValue *field_def_values;
9598 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9600 if (!klass->ext || !klass->ext->field_def_values) {
9601 mono_class_alloc_ext (klass);
9603 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9605 mono_image_lock (klass->image);
9606 if (!klass->ext->field_def_values)
9607 klass->ext->field_def_values = field_def_values;
9608 mono_image_unlock (klass->image);
9611 field_index = mono_field_get_index (field);
9613 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9614 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9616 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9617 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9620 return klass->ext->field_def_values [field_index].data;
9624 * mono_field_get_data:
9625 * @field: the MonoClassField to act on
9627 * Returns: A pointer to the metadata constant value or to the field
9628 * data if it has an RVA flag.
9631 mono_field_get_data (MonoClassField *field)
9633 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9634 MonoTypeEnum def_type;
9636 return mono_class_get_field_default_value (field, &def_type);
9637 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9638 return mono_field_get_rva (field);
9645 * mono_property_get_name:
9646 * @prop: the MonoProperty to act on
9648 * Returns: The name of the property
9651 mono_property_get_name (MonoProperty *prop)
9657 * mono_property_get_set_method
9658 * @prop: the MonoProperty to act on.
9660 * Returns: The setter method of the property (A MonoMethod)
9663 mono_property_get_set_method (MonoProperty *prop)
9669 * mono_property_get_get_method
9670 * @prop: the MonoProperty to act on.
9672 * Returns: The setter method of the property (A MonoMethod)
9675 mono_property_get_get_method (MonoProperty *prop)
9681 * mono_property_get_parent:
9682 * @prop: the MonoProperty to act on.
9684 * Returns: The MonoClass where the property was defined.
9687 mono_property_get_parent (MonoProperty *prop)
9689 return prop->parent;
9693 * mono_property_get_flags:
9694 * @prop: the MonoProperty to act on.
9696 * The metadata flags for a property are encoded using the
9697 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9699 * Returns: The flags for the property.
9702 mono_property_get_flags (MonoProperty *prop)
9708 * mono_event_get_name:
9709 * @event: the MonoEvent to act on
9711 * Returns: The name of the event.
9714 mono_event_get_name (MonoEvent *event)
9720 * mono_event_get_add_method:
9721 * @event: The MonoEvent to act on.
9723 * Returns: The @add' method for the event (a MonoMethod).
9726 mono_event_get_add_method (MonoEvent *event)
9732 * mono_event_get_remove_method:
9733 * @event: The MonoEvent to act on.
9735 * Returns: The @remove method for the event (a MonoMethod).
9738 mono_event_get_remove_method (MonoEvent *event)
9740 return event->remove;
9744 * mono_event_get_raise_method:
9745 * @event: The MonoEvent to act on.
9747 * Returns: The @raise method for the event (a MonoMethod).
9750 mono_event_get_raise_method (MonoEvent *event)
9752 return event->raise;
9756 * mono_event_get_parent:
9757 * @event: the MonoEvent to act on.
9759 * Returns: The MonoClass where the event is defined.
9762 mono_event_get_parent (MonoEvent *event)
9764 return event->parent;
9768 * mono_event_get_flags
9769 * @event: the MonoEvent to act on.
9771 * The metadata flags for an event are encoded using the
9772 * EVENT_* constants. See the tabledefs.h file for details.
9774 * Returns: The flags for the event.
9777 mono_event_get_flags (MonoEvent *event)
9779 return event->attrs;
9783 * mono_class_get_method_from_name:
9784 * @klass: where to look for the method
9785 * @name: name of the method
9786 * @param_count: number of parameters. -1 for any number.
9788 * Obtains a MonoMethod with a given name and number of parameters.
9789 * It only works if there are no multiple signatures for any given method name.
9792 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9794 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9798 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9800 MonoMethod *res = NULL;
9803 /* Search directly in the metadata to avoid calling setup_methods () */
9804 for (i = 0; i < klass->method.count; ++i) {
9806 guint32 cols [MONO_METHOD_SIZE];
9808 MonoMethodSignature *sig;
9810 /* klass->method.first points into the methodptr table */
9811 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9813 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9814 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9816 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9819 if (param_count == -1) {
9823 sig = mono_method_signature_checked (method, &error);
9825 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9828 if (sig->param_count == param_count) {
9839 * mono_class_get_method_from_name_flags:
9840 * @klass: where to look for the method
9841 * @name_space: name of the method
9842 * @param_count: number of parameters. -1 for any number.
9843 * @flags: flags which must be set in the method
9845 * Obtains a MonoMethod with a given name and number of parameters.
9846 * It only works if there are no multiple signatures for any given method name.
9849 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9851 MonoMethod *res = NULL;
9854 mono_class_init (klass);
9856 if (mono_class_is_ginst (klass) && !klass->methods) {
9857 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9860 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9861 if (!mono_error_ok (&error))
9862 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9867 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9868 mono_class_setup_methods (klass);
9870 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9871 See mono/tests/array_load_exception.il
9872 FIXME we should better report this error to the caller
9874 if (!klass->methods)
9876 for (i = 0; i < klass->method.count; ++i) {
9877 MonoMethod *method = klass->methods [i];
9879 if (method->name[0] == name [0] &&
9880 !strcmp (name, method->name) &&
9881 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9882 ((method->flags & flags) == flags)) {
9889 res = find_method_in_metadata (klass, name, param_count, flags);
9896 * mono_class_set_failure:
9897 * @klass: class in which the failure was detected
9898 * @ex_type: the kind of exception/error to be thrown (later)
9899 * @ex_data: exception data (specific to each type of exception/error)
9901 * Keep a detected failure informations in the class for later processing.
9902 * Note that only the first failure is kept.
9904 * LOCKING: Acquires the loader lock.
9907 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9909 g_assert (boxed_error != NULL);
9911 if (mono_class_has_failure (klass))
9914 mono_loader_lock ();
9915 klass->has_failure = 1;
9916 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9917 mono_loader_unlock ();
9923 mono_class_has_failure (const MonoClass *klass)
9925 g_assert (klass != NULL);
9926 return klass->has_failure != 0;
9931 * mono_class_set_type_load_failure:
9932 * @klass: class in which the failure was detected
9933 * @fmt: Printf-style error message string.
9935 * Collect detected failure informaion in the class for later processing.
9936 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9937 * Note that only the first failure is kept.
9939 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9941 * LOCKING: Acquires the loader lock.
9944 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9946 MonoError prepare_error;
9949 if (mono_class_has_failure (klass))
9952 mono_error_init (&prepare_error);
9954 va_start (args, fmt);
9955 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9958 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9959 mono_error_cleanup (&prepare_error);
9960 return mono_class_set_failure (klass, box);
9964 * mono_class_get_exception_data:
9966 * Return the exception_data property of KLASS.
9968 * LOCKING: Acquires the loader lock.
9971 mono_class_get_exception_data (const MonoClass *klass)
9973 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9977 * mono_classes_init:
9979 * Initialize the resources used by this module.
9982 mono_classes_init (void)
9984 mono_os_mutex_init (&classes_mutex);
9986 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9987 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9989 mono_counters_register ("MonoClassDef count",
9990 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9991 mono_counters_register ("MonoClassGtd count",
9992 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9993 mono_counters_register ("MonoClassGenericInst count",
9994 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9995 mono_counters_register ("MonoClassGenericParam count",
9996 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9997 mono_counters_register ("MonoClassArray count",
9998 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9999 mono_counters_register ("MonoClassPointer count",
10000 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
10001 mono_counters_register ("Inflated methods size",
10002 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10003 mono_counters_register ("Inflated classes size",
10004 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10005 mono_counters_register ("MonoClass size",
10006 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10007 mono_counters_register ("MonoClassExt size",
10008 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10010 mono_counters_register ("MonoClassExt count",
10011 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
10015 * mono_classes_cleanup:
10017 * Free the resources used by this module.
10020 mono_classes_cleanup (void)
10022 mono_native_tls_free (setup_fields_tls_id);
10023 mono_native_tls_free (init_pending_tls_id);
10025 if (global_interface_bitset)
10026 mono_bitset_free (global_interface_bitset);
10027 global_interface_bitset = NULL;
10028 mono_os_mutex_destroy (&classes_mutex);
10032 * mono_class_get_exception_for_failure:
10033 * @klass: class in which the failure was detected
10035 * Return a constructed MonoException than the caller can then throw
10036 * using mono_raise_exception - or NULL if no failure is present (or
10037 * doesn't result in an exception).
10040 mono_class_get_exception_for_failure (MonoClass *klass)
10042 if (!mono_class_has_failure (klass))
10044 MonoError unboxed_error;
10045 mono_error_init (&unboxed_error);
10046 mono_error_set_for_class_failure (&unboxed_error, klass);
10047 return mono_error_convert_to_exception (&unboxed_error);
10051 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10053 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10054 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10056 if (outer_klass == inner_klass)
10058 inner_klass = inner_klass->nested_in;
10059 } while (inner_klass);
10064 mono_class_get_generic_type_definition (MonoClass *klass)
10066 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10067 return gklass ? gklass->container_class : klass;
10071 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10073 * Generic instantiations are ignored for all super types of @klass.
10075 * Visibility checks ignoring generic instantiations.
10078 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10081 klass = mono_class_get_generic_type_definition (klass);
10082 parent = mono_class_get_generic_type_definition (parent);
10083 mono_class_setup_supertypes (klass);
10085 for (i = 0; i < klass->idepth; ++i) {
10086 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10092 * Subtype can only access parent members with family protection if the site object
10093 * is subclass of Subtype. For example:
10094 * class A { protected int x; }
10096 * void valid_access () {
10100 * void invalid_access () {
10107 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10109 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10112 if (context_klass == NULL)
10114 /*if access_klass is not member_klass context_klass must be type compat*/
10115 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10121 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10124 if (accessing == accessed)
10126 if (!accessed || !accessing)
10129 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10130 * anywhere so untrusted friends are not safe to access platform's code internals */
10131 if (mono_security_core_clr_enabled ()) {
10132 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10136 mono_assembly_load_friends (accessed);
10137 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10138 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10139 /* Be conservative with checks */
10140 if (!friend_->name)
10142 if (strcmp (accessing->aname.name, friend_->name))
10144 if (friend_->public_key_token [0]) {
10145 if (!accessing->aname.public_key_token [0])
10147 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10156 * If klass is a generic type or if it is derived from a generic type, return the
10157 * MonoClass of the generic definition
10158 * Returns NULL if not found
10161 get_generic_definition_class (MonoClass *klass)
10164 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10165 if (gklass && gklass->container_class)
10166 return gklass->container_class;
10167 klass = klass->parent;
10173 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10176 for (i = 0; i < ginst->type_argc; ++i) {
10177 MonoType *type = ginst->type_argv[i];
10178 switch (type->type) {
10179 case MONO_TYPE_SZARRAY:
10180 if (!can_access_type (access_klass, type->data.klass))
10183 case MONO_TYPE_ARRAY:
10184 if (!can_access_type (access_klass, type->data.array->eklass))
10187 case MONO_TYPE_PTR:
10188 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10191 case MONO_TYPE_CLASS:
10192 case MONO_TYPE_VALUETYPE:
10193 case MONO_TYPE_GENERICINST:
10194 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10204 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10208 if (access_klass == member_klass)
10211 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10214 if (access_klass->element_class && !access_klass->enumtype)
10215 access_klass = access_klass->element_class;
10217 if (member_klass->element_class && !member_klass->enumtype)
10218 member_klass = member_klass->element_class;
10220 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10222 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10225 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10228 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10231 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10234 /*Non nested type with nested visibility. We just fail it.*/
10235 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10238 switch (access_level) {
10239 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10240 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10242 case TYPE_ATTRIBUTE_PUBLIC:
10245 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10248 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10249 return is_nesting_type (member_klass, access_klass);
10251 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10252 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10254 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10255 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10257 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10258 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10259 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10261 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10262 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10263 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10268 /* FIXME: check visibility of type, too */
10270 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10272 MonoClass *member_generic_def;
10273 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10276 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10277 if (((access_gklass && access_gklass->container_class) ||
10278 mono_class_is_gtd (access_klass)) &&
10279 (member_generic_def = get_generic_definition_class (member_klass))) {
10280 MonoClass *access_container;
10282 if (mono_class_is_gtd (access_klass))
10283 access_container = access_klass;
10285 access_container = access_gklass->container_class;
10287 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10291 /* Partition I 8.5.3.2 */
10292 /* the access level values are the same for fields and methods */
10293 switch (access_level) {
10294 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10295 /* same compilation unit */
10296 return access_klass->image == member_klass->image;
10297 case FIELD_ATTRIBUTE_PRIVATE:
10298 return access_klass == member_klass;
10299 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10300 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10301 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10304 case FIELD_ATTRIBUTE_ASSEMBLY:
10305 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10306 case FIELD_ATTRIBUTE_FAMILY:
10307 if (is_valid_family_access (access_klass, member_klass, context_klass))
10310 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10311 if (is_valid_family_access (access_klass, member_klass, context_klass))
10313 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10314 case FIELD_ATTRIBUTE_PUBLIC:
10321 * mono_method_can_access_field:
10322 * @method: Method that will attempt to access the field
10323 * @field: the field to access
10325 * Used to determine if a method is allowed to access the specified field.
10327 * Returns: TRUE if the given @method is allowed to access the @field while following
10328 * the accessibility rules of the CLI.
10331 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10333 /* FIXME: check all overlapping fields */
10334 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10336 MonoClass *nested = method->klass->nested_in;
10338 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10341 nested = nested->nested_in;
10348 * mono_method_can_access_method:
10349 * @method: Method that will attempt to access the other method
10350 * @called: the method that we want to probe for accessibility.
10352 * Used to determine if the @method is allowed to access the specified @called method.
10354 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10355 * the accessibility rules of the CLI.
10358 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10360 method = mono_method_get_method_definition (method);
10361 called = mono_method_get_method_definition (called);
10362 return mono_method_can_access_method_full (method, called, NULL);
10366 * mono_method_can_access_method_full:
10367 * @method: The caller method
10368 * @called: The called method
10369 * @context_klass: The static type on stack of the owner @called object used
10371 * This function must be used with instance calls, as they have more strict family accessibility.
10372 * It can be used with static methods, but context_klass should be NULL.
10374 * Returns: TRUE if caller have proper visibility and acessibility to @called
10377 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10379 /* Wrappers are except from access checks */
10380 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10383 MonoClass *access_class = method->klass;
10384 MonoClass *member_class = called->klass;
10385 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10387 MonoClass *nested = access_class->nested_in;
10389 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10392 nested = nested->nested_in;
10399 can = can_access_type (access_class, member_class);
10401 MonoClass *nested = access_class->nested_in;
10403 can = can_access_type (nested, member_class);
10406 nested = nested->nested_in;
10413 if (called->is_inflated) {
10414 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10415 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10424 * mono_method_can_access_field_full:
10425 * @method: The caller method
10426 * @field: The accessed field
10427 * @context_klass: The static type on stack of the owner @field object used
10429 * This function must be used with instance fields, as they have more strict family accessibility.
10430 * It can be used with static fields, but context_klass should be NULL.
10432 * Returns: TRUE if caller have proper visibility and acessibility to @field
10435 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10437 MonoClass *access_class = method->klass;
10438 MonoClass *member_class = field->parent;
10439 /* FIXME: check all overlapping fields */
10440 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10442 MonoClass *nested = access_class->nested_in;
10444 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10447 nested = nested->nested_in;
10454 can = can_access_type (access_class, member_class);
10456 MonoClass *nested = access_class->nested_in;
10458 can = can_access_type (nested, member_class);
10461 nested = nested->nested_in;
10471 * mono_class_can_access_class:
10472 * @source_class: The source class
10473 * @target_class: The accessed class
10475 * This function returns is @target_class is visible to @source_class
10477 * Returns: TRUE if source have proper visibility and acessibility to target
10480 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10482 return can_access_type (source_class, target_class);
10486 * mono_type_is_valid_enum_basetype:
10487 * @type: The MonoType to check
10489 * Returns: TRUE if the type can be used as the basetype of an enum
10491 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10492 switch (type->type) {
10495 case MONO_TYPE_BOOLEAN:
10498 case MONO_TYPE_CHAR:
10512 * mono_class_is_valid_enum:
10513 * @klass: An enum class to be validated
10515 * This method verify the required properties an enum should have.
10517 * Returns: TRUE if the informed enum class is valid
10519 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10520 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10521 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10523 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10524 MonoClassField * field;
10525 gpointer iter = NULL;
10526 gboolean found_base_field = FALSE;
10528 g_assert (klass->enumtype);
10529 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10530 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10534 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10537 while ((field = mono_class_get_fields (klass, &iter))) {
10538 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10539 if (found_base_field)
10541 found_base_field = TRUE;
10542 if (!mono_type_is_valid_enum_basetype (field->type))
10547 if (!found_base_field)
10550 if (klass->method.count > 0)
10557 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10559 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10563 * mono_class_setup_interface_id:
10565 * Initializes MonoClass::interface_id if required.
10567 * LOCKING: Acquires the loader lock.
10570 mono_class_setup_interface_id (MonoClass *klass)
10572 mono_loader_lock ();
10573 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10574 klass->interface_id = mono_get_unique_iid (klass);
10575 mono_loader_unlock ();
10579 * mono_class_alloc_ext:
10581 * Allocate klass->ext if not already done.
10584 mono_class_alloc_ext (MonoClass *klass)
10591 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10592 mono_image_lock (klass->image);
10593 mono_memory_barrier ();
10596 class_ext_size += sizeof (MonoClassExt);
10598 mono_image_unlock (klass->image);
10602 * mono_class_setup_interfaces:
10604 * Initialize klass->interfaces/interfaces_count.
10605 * LOCKING: Acquires the loader lock.
10606 * This function can fail the type.
10609 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10611 int i, interface_count;
10612 MonoClass **interfaces;
10614 mono_error_init (error);
10616 if (klass->interfaces_inited)
10619 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10620 MonoType *args [1];
10622 /* generic IList, ICollection, IEnumerable */
10623 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10624 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10626 args [0] = &klass->element_class->byval_arg;
10627 interfaces [0] = mono_class_bind_generic_parameters (
10628 mono_defaults.generic_ilist_class, 1, args, FALSE);
10629 if (interface_count > 1)
10630 interfaces [1] = mono_class_bind_generic_parameters (
10631 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10632 } else if (mono_class_is_ginst (klass)) {
10633 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10635 mono_class_setup_interfaces (gklass, error);
10636 if (!mono_error_ok (error)) {
10637 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10641 interface_count = gklass->interface_count;
10642 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10643 for (i = 0; i < interface_count; i++) {
10644 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10645 if (!mono_error_ok (error)) {
10646 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10651 interface_count = 0;
10655 mono_image_lock (klass->image);
10657 if (!klass->interfaces_inited) {
10658 klass->interface_count = interface_count;
10659 klass->interfaces = interfaces;
10661 mono_memory_barrier ();
10663 klass->interfaces_inited = TRUE;
10666 mono_image_unlock (klass->image);
10670 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10672 MonoClass *klass = field->parent;
10673 MonoImage *image = klass->image;
10674 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10675 int field_idx = field - klass->fields;
10677 mono_error_init (error);
10680 MonoClassField *gfield = >d->fields [field_idx];
10681 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10682 if (!mono_error_ok (error)) {
10683 char *full_name = mono_type_get_full_name (gtd);
10684 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));
10685 g_free (full_name);
10688 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10689 if (!mono_error_ok (error)) {
10690 char *full_name = mono_type_get_full_name (klass);
10691 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));
10692 g_free (full_name);
10696 guint32 cols [MONO_FIELD_SIZE];
10697 MonoGenericContainer *container = NULL;
10698 int idx = klass->field.first + field_idx;
10700 /*FIXME, in theory we do not lazy load SRE fields*/
10701 g_assert (!image_is_dynamic (image));
10703 if (mono_class_is_gtd (klass)) {
10704 container = mono_class_get_generic_container (klass);
10706 container = mono_class_get_generic_container (gtd);
10707 g_assert (container);
10710 /* klass->field.first and idx points into the fieldptr table */
10711 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10713 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10714 char *full_name = mono_type_get_full_name (klass);
10715 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10716 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10717 g_free (full_name);
10721 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10723 mono_metadata_decode_value (sig, &sig);
10724 /* FIELD signature == 0x06 */
10725 g_assert (*sig == 0x06);
10727 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10728 if (!field->type) {
10729 char *full_name = mono_type_get_full_name (klass);
10730 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));
10731 g_free (full_name);
10737 mono_field_resolve_flags (MonoClassField *field)
10739 MonoClass *klass = field->parent;
10740 MonoImage *image = klass->image;
10741 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10742 int field_idx = field - klass->fields;
10746 MonoClassField *gfield = >d->fields [field_idx];
10747 return mono_field_get_flags (gfield);
10749 int idx = klass->field.first + field_idx;
10751 /*FIXME, in theory we do not lazy load SRE fields*/
10752 g_assert (!image_is_dynamic (image));
10754 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10759 * mono_class_get_fields_lazy:
10760 * @klass: the MonoClass to act on
10762 * This routine is an iterator routine for retrieving the fields in a class.
10763 * Only minimal information about fields are loaded. Accessors must be used
10764 * for all MonoClassField returned.
10766 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10767 * iterate over all of the elements. When no more values are
10768 * available, the return value is NULL.
10770 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10773 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10775 MonoClassField* field;
10779 mono_class_setup_basic_field_info (klass);
10780 if (!klass->fields)
10782 /* start from the first */
10783 if (klass->field.count) {
10784 *iter = &klass->fields [0];
10785 return (MonoClassField *)*iter;
10791 field = (MonoClassField *)*iter;
10793 if (field < &klass->fields [klass->field.count]) {
10795 return (MonoClassField *)*iter;
10801 mono_class_full_name (MonoClass *klass)
10803 return mono_type_full_name (&klass->byval_arg);
10806 /* Declare all shared lazy type lookup functions */
10807 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)