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/assembly.h>
22 #include <mono/metadata/metadata.h>
23 #include <mono/metadata/metadata-internals.h>
24 #include <mono/metadata/profiler-private.h>
25 #include <mono/metadata/tabledefs.h>
26 #include <mono/metadata/tokentype.h>
27 #include <mono/metadata/class-internals.h>
28 #include <mono/metadata/object.h>
29 #include <mono/metadata/appdomain.h>
30 #include <mono/metadata/mono-endian.h>
31 #include <mono/metadata/debug-helpers.h>
32 #include <mono/metadata/reflection.h>
33 #include <mono/metadata/exception.h>
34 #include <mono/metadata/security-manager.h>
35 #include <mono/metadata/security-core-clr.h>
36 #include <mono/metadata/attrdefs.h>
37 #include <mono/metadata/gc-internals.h>
38 #include <mono/metadata/verify-internals.h>
39 #include <mono/metadata/mono-debug.h>
40 #include <mono/utils/mono-counters.h>
41 #include <mono/utils/mono-string.h>
42 #include <mono/utils/mono-error-internals.h>
43 #include <mono/utils/mono-logger-internals.h>
44 #include <mono/utils/mono-memory-model.h>
45 #include <mono/utils/atomic.h>
46 #include <mono/utils/bsearch.h>
47 #include <mono/utils/checked-build.h>
51 gboolean mono_print_vtable = FALSE;
52 gboolean mono_align_small_structs = FALSE;
55 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
56 guint32 classes_size, class_ext_size;
58 /* Low level lock which protects data structures in this module */
59 static mono_mutex_t classes_mutex;
61 /* Function supplied by the runtime to find classes by name using information from the AOT file */
62 static MonoGetClassFromName get_class_from_name = NULL;
64 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
65 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
66 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
67 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
68 static int generic_array_methods (MonoClass *klass);
69 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
71 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
72 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
73 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
74 static guint32 mono_field_resolve_flags (MonoClassField *field);
75 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
76 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
79 We use gclass recording to allow recursive system f types to be referenced by a parent.
81 Given the following type hierarchy:
83 class TextBox : TextBoxBase<TextBox> {}
84 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
85 class TextInput<T> : Input<T> where T: TextInput<T> {}
88 The runtime tries to load TextBoxBase<>.
89 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
90 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
91 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
93 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
94 at this point, iow, both are registered in the type map and both and a NULL parent. This means
95 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
97 To fix that what we do is to record all generic instantes created while resolving the parent of
98 any generic type definition and, after resolved, correct the parent field if needed.
101 static int record_gclass_instantiation;
102 static GSList *gclass_recorded_list;
103 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
108 mono_locks_os_acquire (&classes_mutex, ClassesLock);
112 classes_unlock (void)
114 mono_locks_os_release (&classes_mutex, ClassesLock);
118 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
121 enable_gclass_recording (void)
123 ++record_gclass_instantiation;
127 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
130 disable_gclass_recording (gclass_record_func func, void *user_data)
132 GSList **head = &gclass_recorded_list;
134 g_assert (record_gclass_instantiation > 0);
135 --record_gclass_instantiation;
138 GSList *node = *head;
139 if (func ((MonoClass*)node->data, user_data)) {
141 g_slist_free_1 (node);
147 /* We automatically discard all recorded gclasses when disabled. */
148 if (!record_gclass_instantiation && gclass_recorded_list) {
149 g_slist_free (gclass_recorded_list);
150 gclass_recorded_list = NULL;
155 * mono_class_from_typeref:
156 * @image: a MonoImage
157 * @type_token: a TypeRef token
159 * Creates the MonoClass* structure representing the type defined by
160 * the typeref token valid inside @image.
161 * Returns: The MonoClass* representing the typeref token, NULL ifcould
165 mono_class_from_typeref (MonoImage *image, guint32 type_token)
168 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
169 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
174 * mono_class_from_typeref_checked:
175 * @image: a MonoImage
176 * @type_token: a TypeRef token
177 * @error: error return code, if any.
179 * Creates the MonoClass* structure representing the type defined by
180 * the typeref token valid inside @image.
182 * Returns: The MonoClass* representing the typeref token, NULL if it could
183 * not be loaded with the @error value filled with the information about the
187 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
189 guint32 cols [MONO_TYPEREF_SIZE];
190 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
192 const char *name, *nspace;
193 MonoClass *res = NULL;
196 mono_error_init (error);
198 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
201 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
203 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
204 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
206 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
207 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
208 case MONO_RESOLUTION_SCOPE_MODULE:
210 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
211 This is not the observed behavior of existing implementations.
212 The defacto behavior is that it's just a typedef in disguise.
214 /* a typedef in disguise */
215 res = mono_class_from_name_checked (image, nspace, name, error);
218 case MONO_RESOLUTION_SCOPE_MODULEREF:
219 module = mono_image_load_module (image, idx);
221 res = mono_class_from_name_checked (module, nspace, name, error);
224 case MONO_RESOLUTION_SCOPE_TYPEREF: {
225 MonoClass *enclosing;
228 if (idx == mono_metadata_token_index (type_token)) {
229 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
233 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
234 return_val_if_nok (error, NULL);
236 if (enclosing->nested_classes_inited && enclosing->ext) {
237 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
238 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
239 res = (MonoClass *)tmp->data;
240 if (strcmp (res->name, name) == 0)
244 /* Don't call mono_class_init as we might've been called by it recursively */
245 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
247 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
248 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
249 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
251 if (strcmp (nname, name) == 0)
252 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
254 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
257 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
260 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
264 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
265 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
269 if (!image->references || !image->references [idx - 1])
270 mono_assembly_load_reference (image, idx - 1);
271 g_assert (image->references [idx - 1]);
273 /* If the assembly did not load, register this as a type load exception */
274 if (image->references [idx - 1] == REFERENCE_MISSING){
275 MonoAssemblyName aname;
278 mono_assembly_get_assemblyref (image, idx - 1, &aname);
279 human_name = mono_stringify_assembly_name (&aname);
280 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
284 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
287 /* Generic case, should be avoided for when a better error is possible. */
288 if (!res && mono_error_ok (error)) {
289 char *name = mono_class_name_from_token (image, type_token);
290 char *assembly = mono_assembly_name_from_token (image, type_token);
291 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
293 mono_loader_assert_no_error ();
299 mono_image_memdup (MonoImage *image, void *data, guint size)
301 void *res = mono_image_alloc (image, size);
302 memcpy (res, data, size);
306 /* Copy everything mono_metadata_free_array free. */
308 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
311 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
313 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
315 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
317 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
319 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
321 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
326 /* Copy everything mono_metadata_free_method_signature free. */
328 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
332 sig = mono_metadata_signature_dup_full (image, sig);
334 sig->ret = mono_metadata_type_dup (image, sig->ret);
335 for (i = 0; i < sig->param_count; ++i)
336 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
342 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
344 MonoAssembly *ta = klass->image->assembly;
347 name = mono_stringify_assembly_name (&ta->aname);
348 g_string_append_printf (str, ", %s", name);
353 mono_type_name_check_byref (MonoType *type, GString *str)
356 g_string_append_c (str, '&');
360 * mono_identifier_escape_type_name_chars:
361 * @str: a destination string
362 * @identifier: an IDENTIFIER in internal form
366 * The displayed form of the identifier is appended to str.
368 * The displayed form of an identifier has the characters ,+&*[]\
369 * that have special meaning in type names escaped with a preceeding
370 * backslash (\) character.
373 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
379 // reserve space for common case: there will be no escaped characters.
380 g_string_set_size(str, n + strlen(identifier));
381 g_string_set_size(str, n);
383 for (const char* s = identifier; *s != 0 ; s++) {
392 g_string_append_c (str, '\\');
393 g_string_append_c (str, *s);
396 g_string_append_c (str, *s);
404 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
405 MonoTypeNameFormat format)
409 switch (type->type) {
410 case MONO_TYPE_ARRAY: {
411 int i, rank = type->data.array->rank;
412 MonoTypeNameFormat nested_format;
414 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
415 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
417 mono_type_get_name_recurse (
418 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
419 g_string_append_c (str, '[');
421 g_string_append_c (str, '*');
422 for (i = 1; i < rank; i++)
423 g_string_append_c (str, ',');
424 g_string_append_c (str, ']');
426 mono_type_name_check_byref (type, str);
428 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
429 _mono_type_get_assembly_name (type->data.array->eklass, str);
432 case MONO_TYPE_SZARRAY: {
433 MonoTypeNameFormat nested_format;
435 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
436 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
438 mono_type_get_name_recurse (
439 &type->data.klass->byval_arg, str, FALSE, nested_format);
440 g_string_append (str, "[]");
442 mono_type_name_check_byref (type, str);
444 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
445 _mono_type_get_assembly_name (type->data.klass, str);
448 case MONO_TYPE_PTR: {
449 MonoTypeNameFormat nested_format;
451 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
452 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
454 mono_type_get_name_recurse (
455 type->data.type, str, FALSE, nested_format);
456 g_string_append_c (str, '*');
458 mono_type_name_check_byref (type, str);
460 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
461 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
466 if (!mono_generic_param_info (type->data.generic_param))
467 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
469 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
471 mono_type_name_check_byref (type, str);
475 klass = mono_class_from_mono_type (type);
476 if (klass->nested_in) {
477 mono_type_get_name_recurse (
478 &klass->nested_in->byval_arg, str, TRUE, format);
479 if (format == MONO_TYPE_NAME_FORMAT_IL)
480 g_string_append_c (str, '.');
482 g_string_append_c (str, '+');
483 } else if (*klass->name_space) {
484 if (format == MONO_TYPE_NAME_FORMAT_IL)
485 g_string_append (str, klass->name_space);
487 mono_identifier_escape_type_name_chars (str, klass->name_space);
488 g_string_append_c (str, '.');
490 if (format == MONO_TYPE_NAME_FORMAT_IL) {
491 char *s = strchr (klass->name, '`');
492 int len = s ? s - klass->name : strlen (klass->name);
493 g_string_append_len (str, klass->name, len);
495 mono_identifier_escape_type_name_chars (str, klass->name);
499 if (klass->generic_class) {
500 MonoGenericClass *gclass = klass->generic_class;
501 MonoGenericInst *inst = gclass->context.class_inst;
502 MonoTypeNameFormat nested_format;
505 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
506 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
508 if (format == MONO_TYPE_NAME_FORMAT_IL)
509 g_string_append_c (str, '<');
511 g_string_append_c (str, '[');
512 for (i = 0; i < inst->type_argc; i++) {
513 MonoType *t = inst->type_argv [i];
516 g_string_append_c (str, ',');
517 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
518 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
519 g_string_append_c (str, '[');
520 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
521 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
522 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
523 g_string_append_c (str, ']');
525 if (format == MONO_TYPE_NAME_FORMAT_IL)
526 g_string_append_c (str, '>');
528 g_string_append_c (str, ']');
529 } else if (klass->generic_container &&
530 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
531 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
534 if (format == MONO_TYPE_NAME_FORMAT_IL)
535 g_string_append_c (str, '<');
537 g_string_append_c (str, '[');
538 for (i = 0; i < klass->generic_container->type_argc; i++) {
540 g_string_append_c (str, ',');
541 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
543 if (format == MONO_TYPE_NAME_FORMAT_IL)
544 g_string_append_c (str, '>');
546 g_string_append_c (str, ']');
549 mono_type_name_check_byref (type, str);
551 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
552 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
553 _mono_type_get_assembly_name (klass, str);
559 * mono_type_get_name_full:
561 * @format: the format for the return string.
564 * Returns: The string representation in a number of formats:
566 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
567 * returned in the formatrequired by System.Reflection, this is the
568 * inverse of mono_reflection_parse_type ().
570 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
571 * be used by the IL assembler.
573 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
575 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
578 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
582 result = g_string_new ("");
584 mono_type_get_name_recurse (type, result, FALSE, format);
586 return g_string_free (result, FALSE);
590 * mono_type_get_full_name:
593 * Returns: The string representation for type as required by System.Reflection.
594 * The inverse of mono_reflection_parse_type ().
597 mono_type_get_full_name (MonoClass *klass)
599 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
603 * mono_type_get_name:
606 * Returns: The string representation for type as it would be represented in IL code.
609 mono_type_get_name (MonoType *type)
611 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
615 * mono_type_get_underlying_type:
618 * Returns: The MonoType for the underlying integer type if @type
619 * is an enum and byref is false, otherwise the type itself.
622 mono_type_get_underlying_type (MonoType *type)
624 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
625 return mono_class_enum_basetype (type->data.klass);
626 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
627 return mono_class_enum_basetype (type->data.generic_class->container_class);
632 * mono_class_is_open_constructed_type:
635 * Returns: TRUE if type represents a generics open constructed type.
636 * IOW, not all type parameters required for the instantiation have
637 * been provided or it's a generic type definition.
639 * An open constructed type means it's a non realizable type. Not to
640 * be mixed up with an abstract type - we can't cast or dispatch to
641 * an open type, for example.
644 mono_class_is_open_constructed_type (MonoType *t)
650 case MONO_TYPE_SZARRAY:
651 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
652 case MONO_TYPE_ARRAY:
653 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
655 return mono_class_is_open_constructed_type (t->data.type);
656 case MONO_TYPE_GENERICINST:
657 return t->data.generic_class->context.class_inst->is_open;
658 case MONO_TYPE_CLASS:
659 case MONO_TYPE_VALUETYPE:
660 return t->data.klass->generic_container != NULL;
667 This is a simple function to catch the most common bad instances of generic types.
668 Specially those that might lead to further failures in the runtime.
671 is_valid_generic_argument (MonoType *type)
673 switch (type->type) {
675 //case MONO_TYPE_TYPEDBYREF:
683 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
685 mono_error_init (error);
687 switch (type->type) {
688 case MONO_TYPE_MVAR: {
690 int num = mono_type_get_generic_param_num (type);
691 MonoGenericInst *inst = context->method_inst;
694 if (num >= inst->type_argc) {
695 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
696 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
697 num, info ? info->name : "", inst->type_argc);
701 if (!is_valid_generic_argument (inst->type_argv [num])) {
702 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
703 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
704 num, info ? info->name : "", inst->type_argv [num]->type);
708 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
709 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
710 * ->byref and ->attrs from @type are propagated to the returned type.
712 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
713 nt->byref = type->byref;
714 nt->attrs = type->attrs;
717 case MONO_TYPE_VAR: {
719 int num = mono_type_get_generic_param_num (type);
720 MonoGenericInst *inst = context->class_inst;
723 if (num >= inst->type_argc) {
724 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
725 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
726 num, info ? info->name : "", inst->type_argc);
729 if (!is_valid_generic_argument (inst->type_argv [num])) {
730 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
731 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
732 num, info ? info->name : "", inst->type_argv [num]->type);
735 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
736 nt->byref = type->byref;
737 nt->attrs = type->attrs;
740 case MONO_TYPE_SZARRAY: {
741 MonoClass *eclass = type->data.klass;
742 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
743 if (!inflated || !mono_error_ok (error))
745 nt = mono_metadata_type_dup (image, type);
746 nt->data.klass = mono_class_from_mono_type (inflated);
747 mono_metadata_free_type (inflated);
750 case MONO_TYPE_ARRAY: {
751 MonoClass *eclass = type->data.array->eklass;
752 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
753 if (!inflated || !mono_error_ok (error))
755 nt = mono_metadata_type_dup (image, type);
756 nt->data.array->eklass = mono_class_from_mono_type (inflated);
757 mono_metadata_free_type (inflated);
760 case MONO_TYPE_GENERICINST: {
761 MonoGenericClass *gclass = type->data.generic_class;
762 MonoGenericInst *inst;
764 if (!gclass->context.class_inst->is_open)
767 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
768 return_val_if_nok (error, NULL);
770 if (inst != gclass->context.class_inst)
771 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
773 if (gclass == type->data.generic_class)
776 nt = mono_metadata_type_dup (image, type);
777 nt->data.generic_class = gclass;
780 case MONO_TYPE_CLASS:
781 case MONO_TYPE_VALUETYPE: {
782 MonoClass *klass = type->data.klass;
783 MonoGenericContainer *container = klass->generic_container;
784 MonoGenericInst *inst;
785 MonoGenericClass *gclass = NULL;
791 /* We can't use context->class_inst directly, since it can have more elements */
792 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
793 return_val_if_nok (error, NULL);
795 if (inst == container->context.class_inst)
798 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
800 nt = mono_metadata_type_dup (image, type);
801 nt->type = MONO_TYPE_GENERICINST;
802 nt->data.generic_class = gclass;
812 mono_generic_class_get_context (MonoGenericClass *gclass)
814 return &gclass->context;
818 mono_class_get_context (MonoClass *klass)
820 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
824 * mono_class_get_generic_container:
826 * Return the generic container of KLASS which should be a generic type definition.
828 MonoGenericContainer*
829 mono_class_get_generic_container (MonoClass *klass)
831 g_assert (klass->is_generic);
833 return klass->generic_container;
837 * mono_class_get_generic_class:
839 * Return the MonoGenericClass of KLASS, which should be a generic instance.
842 mono_class_get_generic_class (MonoClass *klass)
844 g_assert (klass->is_inflated);
846 return klass->generic_class;
850 * mono_class_inflate_generic_type_with_mempool:
851 * @mempool: a mempool
853 * @context: a generics context
854 * @error: error context
856 * The same as mono_class_inflate_generic_type, but allocates the MonoType
857 * from mempool if it is non-NULL. If it is NULL, the MonoType is
858 * allocated on the heap and is owned by the caller.
859 * The returned type can potentially be the same as TYPE, so it should not be
860 * modified by the caller, and it should be freed using mono_metadata_free_type ().
863 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
865 MonoType *inflated = NULL;
866 mono_error_init (error);
869 inflated = inflate_generic_type (image, type, context, error);
870 return_val_if_nok (error, NULL);
873 MonoType *shared = mono_metadata_get_shared_type (type);
878 return mono_metadata_type_dup (image, type);
882 mono_stats.inflated_type_count++;
887 * mono_class_inflate_generic_type:
889 * @context: a generics context
891 * If @type is a generic type and @context is not NULL, instantiate it using the
892 * generics context @context.
894 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
895 * on the heap and is owned by the caller. Returns NULL on error.
897 * @deprecated Please use mono_class_inflate_generic_type_checked instead
900 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
904 result = mono_class_inflate_generic_type_checked (type, context, &error);
905 mono_error_cleanup (&error);
910 * mono_class_inflate_generic_type:
912 * @context: a generics context
913 * @error: error context to use
915 * If @type is a generic type and @context is not NULL, instantiate it using the
916 * generics context @context.
918 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
919 * on the heap and is owned by the caller.
922 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
924 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
928 * mono_class_inflate_generic_type_no_copy:
930 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
934 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
936 MonoType *inflated = NULL;
938 mono_error_init (error);
940 inflated = inflate_generic_type (image, type, context, error);
941 return_val_if_nok (error, NULL);
947 mono_stats.inflated_type_count++;
952 * mono_class_inflate_generic_class:
954 * Inflate the class @gklass with @context. Set @error on failure.
957 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
962 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
963 return_val_if_nok (error, NULL);
965 res = mono_class_from_mono_type (inflated);
966 mono_metadata_free_type (inflated);
971 static MonoGenericContext
972 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
974 MonoGenericInst *class_inst = NULL;
975 MonoGenericInst *method_inst = NULL;
976 MonoGenericContext res = { NULL, NULL };
978 mono_error_init (error);
980 if (context->class_inst) {
981 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
982 if (!mono_error_ok (error))
986 if (context->method_inst) {
987 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
988 if (!mono_error_ok (error))
992 res.class_inst = class_inst;
993 res.method_inst = method_inst;
999 * mono_class_inflate_generic_method:
1000 * @method: a generic method
1001 * @context: a generics context
1003 * Instantiate the generic method @method using the generics context @context.
1005 * Returns: The new instantiated method
1008 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1010 return mono_class_inflate_generic_method_full (method, NULL, context);
1014 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1016 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1020 * mono_class_inflate_generic_method_full:
1022 * Instantiate method @method with the generic context @context.
1023 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1024 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1027 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1030 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1031 if (!mono_error_ok (&error))
1032 /*FIXME do proper error handling - on this case, kill this function. */
1033 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1039 * mono_class_inflate_generic_method_full_checked:
1040 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1043 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1046 MonoMethodInflated *iresult, *cached;
1047 MonoMethodSignature *sig;
1048 MonoGenericContext tmp_context;
1050 mono_error_init (error);
1052 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1053 while (method->is_inflated) {
1054 MonoGenericContext *method_context = mono_method_get_context (method);
1055 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1057 tmp_context = inflate_generic_context (method_context, context, error);
1058 return_val_if_nok (error, NULL);
1060 context = &tmp_context;
1062 if (mono_metadata_generic_context_equal (method_context, context))
1065 method = imethod->declaring;
1069 * A method only needs to be inflated if the context has argument for which it is
1072 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1073 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1076 if (!((method->is_generic && context->method_inst) ||
1077 (method->klass->generic_container && context->class_inst)))
1080 iresult = g_new0 (MonoMethodInflated, 1);
1081 iresult->context = *context;
1082 iresult->declaring = method;
1084 if (!context->method_inst && method->is_generic)
1085 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1087 if (!context->class_inst) {
1088 g_assert (!iresult->declaring->klass->generic_class);
1089 if (iresult->declaring->klass->generic_container)
1090 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1091 else if (iresult->declaring->klass->generic_class)
1092 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1094 /* This can happen with some callers like mono_object_get_virtual_method () */
1095 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1096 iresult->context.class_inst = NULL;
1098 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1101 mono_image_set_lock (set);
1102 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1103 mono_image_set_unlock (set);
1107 return (MonoMethod*)cached;
1110 mono_stats.inflated_method_count++;
1112 inflated_methods_size += sizeof (MonoMethodInflated);
1114 sig = mono_method_signature (method);
1116 char *name = mono_type_get_full_name (method->klass);
1117 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1123 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1125 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1128 result = (MonoMethod *) iresult;
1129 result->is_inflated = TRUE;
1130 result->is_generic = FALSE;
1131 result->sre_method = FALSE;
1132 result->signature = NULL;
1134 if (!context->method_inst) {
1135 /* Set the generic_container of the result to the generic_container of method */
1136 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1138 if (generic_container) {
1139 result->is_generic = 1;
1140 mono_method_set_generic_container (result, generic_container);
1144 if (!klass_hint || !klass_hint->generic_class ||
1145 klass_hint->generic_class->container_class != method->klass ||
1146 klass_hint->generic_class->context.class_inst != context->class_inst)
1149 if (method->klass->generic_container)
1150 result->klass = klass_hint;
1152 if (!result->klass) {
1153 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1154 if (!mono_error_ok (error))
1157 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1159 mono_metadata_free_type (inflated);
1163 * FIXME: This should hold, but it doesn't:
1165 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1166 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1167 * g_assert (result->is_generic);
1170 * Fixing this here causes other things to break, hence a very
1171 * ugly hack in mini-trampolines.c - see
1172 * is_generic_method_definition().
1176 mono_image_set_lock (set);
1177 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1179 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1180 iresult->owner = set;
1183 mono_image_set_unlock (set);
1185 return (MonoMethod*)cached;
1193 * mono_get_inflated_method:
1195 * Obsolete. We keep it around since it's mentioned in the public API.
1198 mono_get_inflated_method (MonoMethod *method)
1204 * mono_method_get_context_general:
1206 * @uninflated: handle uninflated methods?
1208 * Returns the generic context of a method or NULL if it doesn't have
1209 * one. For an inflated method that's the context stored in the
1210 * method. Otherwise it's in the method's generic container or in the
1211 * generic container of the method's class.
1214 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1216 if (method->is_inflated) {
1217 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1218 return &imethod->context;
1222 if (method->is_generic)
1223 return &(mono_method_get_generic_container (method)->context);
1224 if (method->klass->generic_container)
1225 return &method->klass->generic_container->context;
1230 * mono_method_get_context:
1233 * Returns the generic context for method if it's inflated, otherwise
1237 mono_method_get_context (MonoMethod *method)
1239 return mono_method_get_context_general (method, FALSE);
1243 * mono_method_get_generic_container:
1245 * Returns the generic container of METHOD, which should be a generic method definition.
1246 * Returns NULL if METHOD is not a generic method definition.
1247 * LOCKING: Acquires the loader lock.
1249 MonoGenericContainer*
1250 mono_method_get_generic_container (MonoMethod *method)
1252 MonoGenericContainer *container;
1254 if (!method->is_generic)
1257 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1258 g_assert (container);
1264 * mono_method_set_generic_container:
1266 * Sets the generic container of METHOD to CONTAINER.
1267 * LOCKING: Acquires the image lock.
1270 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1272 g_assert (method->is_generic);
1274 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1278 * mono_class_find_enum_basetype:
1279 * @class: The enum class
1281 * Determine the basetype of an enum by iterating through its fields. We do this
1282 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1285 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1287 MonoGenericContainer *container = NULL;
1288 MonoImage *m = klass->image;
1289 const int top = klass->field.count;
1292 g_assert (klass->enumtype);
1294 mono_error_init (error);
1296 if (klass->generic_container)
1297 container = klass->generic_container;
1298 else if (klass->generic_class) {
1299 MonoClass *gklass = klass->generic_class->container_class;
1301 container = gklass->generic_container;
1302 g_assert (container);
1306 * Fetch all the field information.
1308 for (i = 0; i < top; i++){
1310 guint32 cols [MONO_FIELD_SIZE];
1311 int idx = klass->field.first + i;
1314 /* klass->field.first and idx points into the fieldptr table */
1315 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1317 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1320 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1321 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1325 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1326 mono_metadata_decode_value (sig, &sig);
1327 /* FIELD signature == 0x06 */
1329 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1333 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1337 if (klass->generic_class) {
1338 //FIXME do we leak here?
1339 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1340 if (!mono_error_ok (error))
1342 ftype->attrs = cols [MONO_FIELD_FLAGS];
1347 mono_error_set_type_load_class (error, klass, "Could not find base type");
1350 mono_loader_assert_no_error ();
1355 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1358 mono_type_has_exceptions (MonoType *type)
1360 switch (type->type) {
1361 case MONO_TYPE_CLASS:
1362 case MONO_TYPE_VALUETYPE:
1363 case MONO_TYPE_SZARRAY:
1364 return mono_class_has_failure (type->data.klass);
1365 case MONO_TYPE_ARRAY:
1366 return mono_class_has_failure (type->data.array->eklass);
1367 case MONO_TYPE_GENERICINST:
1368 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1377 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1381 mono_class_alloc (MonoClass *klass, int size)
1383 if (klass->generic_class)
1384 return mono_image_set_alloc (klass->generic_class->owner, size);
1386 return mono_image_alloc (klass->image, size);
1390 mono_class_alloc0 (MonoClass *klass, int size)
1394 res = mono_class_alloc (klass, size);
1395 memset (res, 0, size);
1399 #define mono_class_new0(klass,struct_type, n_structs) \
1400 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1403 * mono_class_setup_basic_field_info:
1404 * @class: The class to initialize
1406 * Initializes the klass->fields.
1407 * LOCKING: Assumes the loader lock is held.
1410 mono_class_setup_basic_field_info (MonoClass *klass)
1412 MonoClassField *field;
1420 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1421 image = klass->image;
1422 top = klass->field.count;
1424 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1426 * This happens when a generic instance of an unfinished generic typebuilder
1427 * is used as an element type for creating an array type. We can't initialize
1428 * the fields of this class using the fields of gklass, since gklass is not
1429 * finished yet, fields could be added to it later.
1435 mono_class_setup_basic_field_info (gtd);
1437 top = gtd->field.count;
1438 klass->field.first = gtd->field.first;
1439 klass->field.count = gtd->field.count;
1442 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1445 * Fetch all the field information.
1447 for (i = 0; i < top; i++){
1448 field = &klass->fields [i];
1449 field->parent = klass;
1452 field->name = mono_field_get_name (>d->fields [i]);
1454 int idx = klass->field.first + i;
1455 /* klass->field.first and idx points into the fieldptr table */
1456 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1457 /* The name is needed for fieldrefs */
1458 field->name = mono_metadata_string_heap (image, name_idx);
1464 * mono_class_setup_fields:
1465 * @class: The class to initialize
1467 * Initializes the klass->fields.
1468 * LOCKING: Assumes the loader lock is held.
1471 mono_class_setup_fields (MonoClass *klass)
1474 MonoImage *m = klass->image;
1476 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1477 int i, blittable = TRUE;
1478 guint32 real_size = 0;
1479 guint32 packing_size = 0;
1481 gboolean explicit_size;
1482 MonoClassField *field;
1483 MonoGenericContainer *container = NULL;
1484 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1487 * FIXME: We have a race condition here. It's possible that this function returns
1488 * to its caller with `instance_size` set to `0` instead of the actual size. This
1489 * is not a problem when the function is called recursively on the same class,
1490 * because the size will be initialized by the outer invocation. What follows is a
1491 * description of how it can occur in other cases, too. There it is a problem,
1492 * because it can lead to the GC being asked to allocate an object of size `0`,
1493 * which SGen chokes on. The race condition is triggered infrequently by
1494 * `tests/sgen-suspend.cs`.
1496 * This function is called for a class whenever one of its subclasses is inited.
1497 * For example, it's called for every subclass of Object. What it does is this:
1499 * if (klass->setup_fields_called)
1502 * klass->instance_size = 0;
1504 * klass->setup_fields_called = 1;
1505 * ... critical point
1506 * klass->instance_size = actual_instance_size;
1508 * The last two steps are sometimes reversed, but that only changes the way in which
1509 * the race condition works.
1511 * Assume thread A goes through this function and makes it to the critical point.
1512 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1513 * immediately, but `instance_size` is incorrect.
1515 * The other case looks like this:
1517 * if (klass->setup_fields_called)
1519 * ... critical point X
1520 * klass->instance_size = 0;
1521 * ... critical point Y
1522 * klass->instance_size = actual_instance_size;
1524 * klass->setup_fields_called = 1;
1526 * Assume thread A goes through the function and makes it to critical point X. Now
1527 * thread B runs through the whole of the function, returning, assuming
1528 * `instance_size` is set. At that point thread A gets to run and makes it to
1529 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1532 if (klass->setup_fields_called)
1535 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1537 * This happens when a generic instance of an unfinished generic typebuilder
1538 * is used as an element type for creating an array type. We can't initialize
1539 * the fields of this class using the fields of gklass, since gklass is not
1540 * finished yet, fields could be added to it later.
1545 mono_class_setup_basic_field_info (klass);
1546 top = klass->field.count;
1549 mono_class_setup_fields (gtd);
1550 if (mono_class_has_failure (gtd)) {
1551 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1558 klass->sizes.class_size = 0;
1560 if (klass->parent) {
1561 /* For generic instances, klass->parent might not have been initialized */
1562 mono_class_init (klass->parent);
1563 if (!klass->parent->size_inited) {
1564 mono_class_setup_fields (klass->parent);
1565 if (mono_class_has_failure (klass->parent)) {
1566 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1570 instance_size += klass->parent->instance_size;
1571 klass->min_align = klass->parent->min_align;
1572 /* we use |= since it may have been set already */
1573 klass->has_references |= klass->parent->has_references;
1574 blittable = klass->parent->blittable;
1576 instance_size = sizeof (MonoObject);
1577 klass->min_align = 1;
1580 /* We can't really enable 16 bytes alignment until the GC supports it.
1581 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1582 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1583 Bug #506144 is an example of this issue.
1585 if (klass->simd_type)
1586 klass->min_align = 16;
1588 /* Get the real size */
1589 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1591 if (explicit_size) {
1592 if ((packing_size & 0xffffff00) != 0) {
1593 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1594 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1597 klass->packing_size = packing_size;
1598 real_size += instance_size;
1602 if (explicit_size && real_size) {
1603 instance_size = MAX (real_size, instance_size);
1605 klass->blittable = blittable;
1606 if (!klass->instance_size)
1607 klass->instance_size = instance_size;
1608 mono_memory_barrier ();
1609 klass->size_inited = 1;
1610 klass->fields_inited = 1;
1611 klass->setup_fields_called = 1;
1615 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1618 /* Prevent infinite loops if the class references itself */
1619 klass->setup_fields_called = 1;
1621 if (klass->generic_container) {
1622 container = klass->generic_container;
1624 container = gtd->generic_container;
1625 g_assert (container);
1629 * Fetch all the field information.
1631 for (i = 0; i < top; i++){
1632 int idx = klass->field.first + i;
1633 field = &klass->fields [i];
1635 field->parent = klass;
1638 mono_field_resolve_type (field, &error);
1639 if (!mono_error_ok (&error)) {
1640 /*mono_field_resolve_type already failed class*/
1641 mono_error_cleanup (&error);
1645 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1646 g_assert (field->type);
1649 if (mono_field_is_deleted (field))
1652 MonoClassField *gfield = >d->fields [i];
1653 field->offset = gfield->offset;
1655 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1657 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1658 field->offset = offset;
1660 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1661 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1664 if (field->offset < -1) { /*-1 is used to encode special static fields */
1665 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1668 if (klass->generic_container) {
1669 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1675 /* Only do these checks if we still think this type is blittable */
1676 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1677 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1680 MonoClass *field_class = mono_class_from_mono_type (field->type);
1682 mono_class_setup_fields (field_class);
1683 if (mono_class_has_failure (field_class)) {
1684 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1688 if (!field_class || !field_class->blittable)
1693 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1694 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1695 blittable = klass->element_class->blittable;
1698 if (mono_type_has_exceptions (field->type)) {
1699 char *class_name = mono_type_get_full_name (klass);
1700 char *type_name = mono_type_full_name (field->type);
1702 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1703 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1704 g_free (class_name);
1708 /* The def_value of fields is compute lazily during vtable creation */
1711 if (klass == mono_defaults.string_class)
1714 klass->blittable = blittable;
1716 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1717 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1720 if (explicit_size && real_size) {
1721 instance_size = MAX (real_size, instance_size);
1724 if (mono_class_has_failure (klass))
1726 mono_class_layout_fields (klass, instance_size);
1728 /*valuetypes can't be neither bigger than 1Mb or empty. */
1729 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1730 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1732 mono_memory_barrier ();
1733 klass->fields_inited = 1;
1737 * mono_class_setup_fields_locking:
1738 * @class: The class to initialize
1740 * Initializes the klass->fields array of fields.
1741 * Aquires the loader lock.
1744 mono_class_setup_fields_locking (MonoClass *klass)
1746 /* This can be checked without locks */
1747 if (klass->fields_inited)
1749 mono_loader_lock ();
1750 mono_class_setup_fields (klass);
1751 mono_loader_unlock ();
1755 * mono_class_has_references:
1757 * Returns whenever @klass->has_references is set, initializing it if needed.
1758 * Aquires the loader lock.
1761 mono_class_has_references (MonoClass *klass)
1763 if (klass->init_pending) {
1764 /* Be conservative */
1767 mono_class_init (klass);
1769 return klass->has_references;
1774 * mono_type_get_basic_type_from_generic:
1777 * Returns a closed type corresponding to the possibly open type
1781 mono_type_get_basic_type_from_generic (MonoType *type)
1783 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1784 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1785 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1786 return &mono_defaults.object_class->byval_arg;
1791 type_has_references (MonoClass *klass, MonoType *ftype)
1793 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1795 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1796 MonoGenericParam *gparam = ftype->data.generic_param;
1798 if (gparam->gshared_constraint)
1799 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1805 * mono_class_layout_fields:
1807 * @instance_size: base instance size
1809 * Compute the placement of fields inside an object or struct, according to
1810 * the layout rules and set the following fields in @class:
1811 * - has_references (if the class contains instance references firled or structs that contain references)
1812 * - has_static_refs (same, but for static fields)
1813 * - instance_size (size of the object in memory)
1814 * - class_size (size needed for the static fields)
1815 * - size_inited (flag set when the instance_size is set)
1817 * LOCKING: this is supposed to be called with the loader lock held.
1820 mono_class_layout_fields (MonoClass *klass, int instance_size)
1823 const int top = klass->field.count;
1824 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1825 guint32 pass, passes, real_size;
1826 gboolean gc_aware_layout = FALSE;
1827 gboolean has_static_fields = FALSE;
1828 MonoClassField *field;
1831 * When we do generic sharing we need to have layout
1832 * information for open generic classes (either with a generic
1833 * context containing type variables or with a generic
1834 * container), so we don't return in that case anymore.
1838 * Enable GC aware auto layout: in this mode, reference
1839 * fields are grouped together inside objects, increasing collector
1841 * Requires that all classes whose layout is known to native code be annotated
1842 * with [StructLayout (LayoutKind.Sequential)]
1843 * Value types have gc_aware_layout disabled by default, as per
1844 * what the default is for other runtimes.
1846 /* corlib is missing [StructLayout] directives in many places */
1847 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1848 if (!klass->valuetype)
1849 gc_aware_layout = TRUE;
1852 /* Compute klass->has_references */
1854 * Process non-static fields first, since static fields might recursively
1855 * refer to the class itself.
1857 for (i = 0; i < top; i++) {
1860 field = &klass->fields [i];
1862 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1863 ftype = mono_type_get_underlying_type (field->type);
1864 ftype = mono_type_get_basic_type_from_generic (ftype);
1865 if (type_has_references (klass, ftype))
1866 klass->has_references = TRUE;
1870 for (i = 0; i < top; i++) {
1873 field = &klass->fields [i];
1875 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1876 ftype = mono_type_get_underlying_type (field->type);
1877 ftype = mono_type_get_basic_type_from_generic (ftype);
1878 if (type_has_references (klass, ftype))
1879 klass->has_static_refs = TRUE;
1883 for (i = 0; i < top; i++) {
1886 field = &klass->fields [i];
1888 ftype = mono_type_get_underlying_type (field->type);
1889 ftype = mono_type_get_basic_type_from_generic (ftype);
1890 if (type_has_references (klass, ftype)) {
1891 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1892 klass->has_static_refs = TRUE;
1894 klass->has_references = TRUE;
1899 * Compute field layout and total size (not considering static fields)
1902 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1903 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1905 if (gc_aware_layout)
1910 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1913 if (klass->parent) {
1914 mono_class_setup_fields (klass->parent);
1915 if (mono_class_has_failure (klass->parent)) {
1916 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1919 real_size = klass->parent->instance_size;
1921 real_size = sizeof (MonoObject);
1924 for (pass = 0; pass < passes; ++pass) {
1925 for (i = 0; i < top; i++){
1930 field = &klass->fields [i];
1932 if (mono_field_is_deleted (field))
1934 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1937 ftype = mono_type_get_underlying_type (field->type);
1938 ftype = mono_type_get_basic_type_from_generic (ftype);
1939 if (gc_aware_layout) {
1940 if (type_has_references (klass, ftype)) {
1949 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1950 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1951 /* This field is a hack inserted by MCS to empty structures */
1955 size = mono_type_size (field->type, &align);
1957 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1958 align = klass->packing_size ? MIN (klass->packing_size, align): align;
1959 /* if the field has managed references, we need to force-align it
1962 if (type_has_references (klass, ftype))
1963 align = MAX (align, sizeof (gpointer));
1965 klass->min_align = MAX (align, klass->min_align);
1966 field->offset = real_size;
1968 field->offset += align - 1;
1969 field->offset &= ~(align - 1);
1971 /*TypeBuilders produce all sort of weird things*/
1972 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
1973 real_size = field->offset + size;
1976 instance_size = MAX (real_size, instance_size);
1978 if (instance_size & (klass->min_align - 1)) {
1979 instance_size += klass->min_align - 1;
1980 instance_size &= ~(klass->min_align - 1);
1984 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1988 for (i = 0; i < top; i++) {
1993 field = &klass->fields [i];
1996 * There must be info about all the fields in a type if it
1997 * uses explicit layout.
1999 if (mono_field_is_deleted (field))
2001 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2004 size = mono_type_size (field->type, &align);
2005 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2006 klass->min_align = MAX (align, klass->min_align);
2009 * When we get here, field->offset is already set by the
2010 * loader (for either runtime fields or fields loaded from metadata).
2011 * The offset is from the start of the object: this works for both
2012 * classes and valuetypes.
2014 field->offset += sizeof (MonoObject);
2015 ftype = mono_type_get_underlying_type (field->type);
2016 ftype = mono_type_get_basic_type_from_generic (ftype);
2017 if (type_has_references (klass, ftype)) {
2018 if (field->offset % sizeof (gpointer)) {
2019 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2026 real_size = MAX (real_size, size + field->offset);
2029 if (klass->has_references) {
2030 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2032 /* Check for overlapping reference and non-reference fields */
2033 for (i = 0; i < top; i++) {
2036 field = &klass->fields [i];
2038 if (mono_field_is_deleted (field))
2040 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2042 ftype = mono_type_get_underlying_type (field->type);
2043 if (MONO_TYPE_IS_REFERENCE (ftype))
2044 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2046 for (i = 0; i < top; i++) {
2047 field = &klass->fields [i];
2049 if (mono_field_is_deleted (field))
2051 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2054 // FIXME: Too much code does this
2056 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2057 char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", klass->name, field->offset);
2058 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2062 g_free (ref_bitmap);
2065 instance_size = MAX (real_size, instance_size);
2066 if (instance_size & (klass->min_align - 1)) {
2067 instance_size += klass->min_align - 1;
2068 instance_size &= ~(klass->min_align - 1);
2074 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2076 * This leads to all kinds of problems with nested structs, so only
2077 * enable it when a MONO_DEBUG property is set.
2079 * For small structs, set min_align to at least the struct size to improve
2080 * performance, and since the JIT memset/memcpy code assumes this and generates
2081 * unaligned accesses otherwise. See #78990 for a testcase.
2083 if (mono_align_small_structs) {
2084 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2085 klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
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 mono_memory_barrier ();
2096 klass->size_inited = 1;
2099 * Compute static field layout and size
2101 for (i = 0; i < top; i++){
2105 field = &klass->fields [i];
2107 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2109 if (mono_field_is_deleted (field))
2112 if (mono_type_has_exceptions (field->type)) {
2113 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2117 has_static_fields = TRUE;
2119 size = mono_type_size (field->type, &align);
2120 field->offset = klass->sizes.class_size;
2121 /*align is always non-zero here*/
2122 field->offset += align - 1;
2123 field->offset &= ~(align - 1);
2124 klass->sizes.class_size = field->offset + size;
2127 if (has_static_fields && klass->sizes.class_size == 0)
2128 /* Simplify code which depends on class_size != 0 if the class has static fields */
2129 klass->sizes.class_size = 8;
2133 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2137 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2138 method->klass = klass;
2139 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2140 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2141 method->signature = sig;
2142 method->name = name;
2145 if (name [0] == '.') {
2146 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2148 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2154 * mono_class_setup_methods:
2157 * Initializes the 'methods' array in CLASS.
2158 * Calling this method should be avoided if possible since it allocates a lot
2159 * of long-living MonoMethod structures.
2160 * Methods belonging to an interface are assigned a sequential slot starting
2163 * On failure this function sets klass->exception_type
2166 mono_class_setup_methods (MonoClass *klass)
2169 MonoMethod **methods;
2174 if (klass->generic_class) {
2176 MonoClass *gklass = klass->generic_class->container_class;
2178 mono_class_init (gklass);
2179 if (!mono_class_has_failure (gklass))
2180 mono_class_setup_methods (gklass);
2181 if (mono_class_has_failure (gklass)) {
2182 /* FIXME make exception_data less opaque so it's possible to dup it here */
2183 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2187 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2188 count = gklass->method.count;
2189 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2191 for (i = 0; i < count; i++) {
2192 methods [i] = mono_class_inflate_generic_method_full_checked (
2193 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2194 if (!mono_error_ok (&error)) {
2195 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2196 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not inflate method %s due to %s", method, mono_error_get_message (&error)));
2199 mono_error_cleanup (&error);
2203 } else if (klass->rank) {
2205 MonoMethod *amethod;
2206 MonoMethodSignature *sig;
2207 int count_generic = 0, first_generic = 0;
2209 gboolean jagged_ctor = FALSE;
2211 count = 3 + (klass->rank > 1? 2: 1);
2213 mono_class_setup_interfaces (klass, &error);
2214 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2216 if (klass->rank == 1 && klass->element_class->rank) {
2218 klass->method.count ++;
2221 if (klass->interface_count) {
2222 count_generic = generic_array_methods (klass);
2223 first_generic = count;
2224 count += klass->interface_count * count_generic;
2227 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2229 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2230 sig->ret = &mono_defaults.void_class->byval_arg;
2231 sig->pinvoke = TRUE;
2232 sig->hasthis = TRUE;
2233 for (i = 0; i < klass->rank; ++i)
2234 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2236 amethod = create_array_method (klass, ".ctor", sig);
2237 methods [method_num++] = amethod;
2238 if (klass->rank > 1) {
2239 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2240 sig->ret = &mono_defaults.void_class->byval_arg;
2241 sig->pinvoke = TRUE;
2242 sig->hasthis = TRUE;
2243 for (i = 0; i < klass->rank * 2; ++i)
2244 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2246 amethod = create_array_method (klass, ".ctor", sig);
2247 methods [method_num++] = amethod;
2251 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2252 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2253 sig->ret = &mono_defaults.void_class->byval_arg;
2254 sig->pinvoke = TRUE;
2255 sig->hasthis = TRUE;
2256 for (i = 0; i < klass->rank + 1; ++i)
2257 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2258 amethod = create_array_method (klass, ".ctor", sig);
2259 methods [method_num++] = amethod;
2262 /* element Get (idx11, [idx2, ...]) */
2263 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2264 sig->ret = &klass->element_class->byval_arg;
2265 sig->pinvoke = TRUE;
2266 sig->hasthis = TRUE;
2267 for (i = 0; i < klass->rank; ++i)
2268 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2269 amethod = create_array_method (klass, "Get", sig);
2270 methods [method_num++] = amethod;
2271 /* element& Address (idx11, [idx2, ...]) */
2272 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2273 sig->ret = &klass->element_class->this_arg;
2274 sig->pinvoke = TRUE;
2275 sig->hasthis = TRUE;
2276 for (i = 0; i < klass->rank; ++i)
2277 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2278 amethod = create_array_method (klass, "Address", sig);
2279 methods [method_num++] = amethod;
2280 /* void Set (idx11, [idx2, ...], element) */
2281 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2282 sig->ret = &mono_defaults.void_class->byval_arg;
2283 sig->pinvoke = TRUE;
2284 sig->hasthis = TRUE;
2285 for (i = 0; i < klass->rank; ++i)
2286 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2287 sig->params [i] = &klass->element_class->byval_arg;
2288 amethod = create_array_method (klass, "Set", sig);
2289 methods [method_num++] = amethod;
2291 for (i = 0; i < klass->interface_count; i++)
2292 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2296 count = klass->method.count;
2297 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2298 for (i = 0; i < count; ++i) {
2299 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2300 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2302 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load method %d due to %s", i, mono_error_get_message (&error)));
2303 mono_error_cleanup (&error);
2308 if (MONO_CLASS_IS_INTERFACE (klass)) {
2310 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2311 for (i = 0; i < count; ++i) {
2312 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2313 methods [i]->slot = slot++;
2317 mono_image_lock (klass->image);
2319 if (!klass->methods) {
2320 klass->method.count = count;
2322 /* Needed because of the double-checking locking pattern */
2323 mono_memory_barrier ();
2325 klass->methods = methods;
2328 mono_image_unlock (klass->image);
2332 * mono_class_get_method_by_index:
2334 * Returns klass->methods [index], initializing klass->methods if neccesary.
2336 * LOCKING: Acquires the loader lock.
2339 mono_class_get_method_by_index (MonoClass *klass, int index)
2342 /* Avoid calling setup_methods () if possible */
2343 if (klass->generic_class && !klass->methods) {
2344 MonoClass *gklass = klass->generic_class->container_class;
2347 m = mono_class_inflate_generic_method_full_checked (
2348 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2349 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2351 * If setup_methods () is called later for this class, no duplicates are created,
2352 * since inflate_generic_method guarantees that only one instance of a method
2353 * is created for each context.
2356 mono_class_setup_methods (klass);
2357 g_assert (m == klass->methods [index]);
2361 mono_class_setup_methods (klass);
2362 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2364 g_assert (index >= 0 && index < klass->method.count);
2365 return klass->methods [index];
2370 * mono_class_get_inflated_method:
2372 * Given an inflated class CLASS and a method METHOD which should be a method of
2373 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2376 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2378 MonoClass *gklass = klass->generic_class->container_class;
2381 g_assert (method->klass == gklass);
2383 mono_class_setup_methods (gklass);
2384 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2386 for (i = 0; i < gklass->method.count; ++i) {
2387 if (gklass->methods [i] == method) {
2388 if (klass->methods) {
2389 return klass->methods [i];
2392 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2393 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2403 * mono_class_get_vtable_entry:
2405 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2406 * LOCKING: Acquires the loader lock.
2409 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2413 if (klass->rank == 1) {
2415 * szarrays do not overwrite any methods of Array, so we can avoid
2416 * initializing their vtables in some cases.
2418 mono_class_setup_vtable (klass->parent);
2419 if (offset < klass->parent->vtable_size)
2420 return klass->parent->vtable [offset];
2423 if (klass->generic_class) {
2425 MonoClass *gklass = klass->generic_class->container_class;
2426 mono_class_setup_vtable (gklass);
2427 m = gklass->vtable [offset];
2429 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2430 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2432 mono_class_setup_vtable (klass);
2433 if (mono_class_has_failure (klass))
2435 m = klass->vtable [offset];
2442 * mono_class_get_vtable_size:
2444 * Return the vtable size for KLASS.
2447 mono_class_get_vtable_size (MonoClass *klass)
2449 mono_class_setup_vtable (klass);
2451 return klass->vtable_size;
2455 * mono_class_setup_properties:
2457 * Initialize klass->ext.property and klass->ext.properties.
2459 * This method can fail the class.
2462 mono_class_setup_properties (MonoClass *klass)
2464 guint startm, endm, i, j;
2465 guint32 cols [MONO_PROPERTY_SIZE];
2466 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2467 MonoProperty *properties;
2471 if (klass->ext && klass->ext->properties)
2474 if (klass->generic_class) {
2475 MonoClass *gklass = klass->generic_class->container_class;
2477 mono_class_init (gklass);
2478 mono_class_setup_properties (gklass);
2479 if (mono_class_has_failure (gklass)) {
2480 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2484 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2486 for (i = 0; i < gklass->ext->property.count; i++) {
2488 MonoProperty *prop = &properties [i];
2490 *prop = gklass->ext->properties [i];
2493 prop->get = mono_class_inflate_generic_method_full_checked (
2494 prop->get, klass, mono_class_get_context (klass), &error);
2496 prop->set = mono_class_inflate_generic_method_full_checked (
2497 prop->set, klass, mono_class_get_context (klass), &error);
2499 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2500 prop->parent = klass;
2503 first = gklass->ext->property.first;
2504 count = gklass->ext->property.count;
2506 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2507 count = last - first;
2510 mono_class_setup_methods (klass);
2511 if (mono_class_has_failure (klass))
2515 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2516 for (i = first; i < last; ++i) {
2517 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2518 properties [i - first].parent = klass;
2519 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2520 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2522 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2523 for (j = startm; j < endm; ++j) {
2526 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2528 if (klass->image->uncompressed_metadata) {
2530 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2531 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2532 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2534 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2537 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2538 case METHOD_SEMANTIC_SETTER:
2539 properties [i - first].set = method;
2541 case METHOD_SEMANTIC_GETTER:
2542 properties [i - first].get = method;
2551 mono_class_alloc_ext (klass);
2553 mono_image_lock (klass->image);
2555 if (klass->ext->properties) {
2556 /* We leak 'properties' which was allocated from the image mempool */
2557 mono_image_unlock (klass->image);
2561 klass->ext->property.first = first;
2562 klass->ext->property.count = count;
2564 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2565 mono_memory_barrier ();
2567 /* Leave this assignment as the last op in the function */
2568 klass->ext->properties = properties;
2570 mono_image_unlock (klass->image);
2574 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2576 MonoMethod **om, **retval;
2579 for (om = methods, count = 0; *om; ++om, ++count)
2582 retval = g_new0 (MonoMethod*, count + 1);
2584 for (om = methods, count = 0; *om; ++om, ++count) {
2586 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2587 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2593 /*This method can fail the class.*/
2595 mono_class_setup_events (MonoClass *klass)
2598 guint startm, endm, i, j;
2599 guint32 cols [MONO_EVENT_SIZE];
2600 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2604 if (klass->ext && klass->ext->events)
2607 if (klass->generic_class) {
2608 MonoClass *gklass = klass->generic_class->container_class;
2609 MonoGenericContext *context = NULL;
2611 mono_class_setup_events (gklass);
2612 if (mono_class_has_failure (gklass)) {
2613 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2617 first = gklass->ext->event.first;
2618 count = gklass->ext->event.count;
2620 events = mono_class_new0 (klass, MonoEvent, count);
2623 context = mono_class_get_context (klass);
2625 for (i = 0; i < count; i++) {
2627 MonoEvent *event = &events [i];
2628 MonoEvent *gevent = &gklass->ext->events [i];
2630 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2632 event->parent = klass;
2633 event->name = gevent->name;
2634 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2635 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2636 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2637 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2638 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2639 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2641 #ifndef MONO_SMALL_CONFIG
2642 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2644 event->attrs = gevent->attrs;
2647 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2648 count = last - first;
2651 mono_class_setup_methods (klass);
2652 if (mono_class_has_failure (klass)) {
2653 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2658 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2659 for (i = first; i < last; ++i) {
2660 MonoEvent *event = &events [i - first];
2662 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2663 event->parent = klass;
2664 event->attrs = cols [MONO_EVENT_FLAGS];
2665 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2667 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2668 for (j = startm; j < endm; ++j) {
2671 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2673 if (klass->image->uncompressed_metadata) {
2675 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2676 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2677 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2679 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2682 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2683 case METHOD_SEMANTIC_ADD_ON:
2684 event->add = method;
2686 case METHOD_SEMANTIC_REMOVE_ON:
2687 event->remove = method;
2689 case METHOD_SEMANTIC_FIRE:
2690 event->raise = method;
2692 case METHOD_SEMANTIC_OTHER: {
2693 #ifndef MONO_SMALL_CONFIG
2696 if (event->other == NULL) {
2697 event->other = g_new0 (MonoMethod*, 2);
2699 while (event->other [n])
2701 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2703 event->other [n] = method;
2704 /* NULL terminated */
2705 event->other [n + 1] = NULL;
2716 mono_class_alloc_ext (klass);
2718 mono_image_lock (klass->image);
2720 if (klass->ext->events) {
2721 mono_image_unlock (klass->image);
2725 klass->ext->event.first = first;
2726 klass->ext->event.count = count;
2728 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2729 mono_memory_barrier ();
2731 /* Leave this assignment as the last op in the function */
2732 klass->ext->events = events;
2734 mono_image_unlock (klass->image);
2738 * Global pool of interface IDs, represented as a bitset.
2739 * LOCKING: Protected by the classes lock.
2741 static MonoBitSet *global_interface_bitset = NULL;
2744 * mono_unload_interface_ids:
2745 * @bitset: bit set of interface IDs
2747 * When an image is unloaded, the interface IDs associated with
2748 * the image are put back in the global pool of IDs so the numbers
2752 mono_unload_interface_ids (MonoBitSet *bitset)
2755 mono_bitset_sub (global_interface_bitset, bitset);
2760 mono_unload_interface_id (MonoClass *klass)
2762 if (global_interface_bitset && klass->interface_id) {
2764 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2770 * mono_get_unique_iid:
2773 * Assign a unique integer ID to the interface represented by @class.
2774 * The ID will positive and as small as possible.
2775 * LOCKING: Acquires the classes lock.
2776 * Returns: The new ID.
2779 mono_get_unique_iid (MonoClass *klass)
2783 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2787 if (!global_interface_bitset) {
2788 global_interface_bitset = mono_bitset_new (128, 0);
2791 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2793 int old_size = mono_bitset_size (global_interface_bitset);
2794 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2795 mono_bitset_free (global_interface_bitset);
2796 global_interface_bitset = new_set;
2799 mono_bitset_set (global_interface_bitset, iid);
2800 /* set the bit also in the per-image set */
2801 if (!klass->generic_class) {
2802 if (klass->image->interface_bitset) {
2803 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2804 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2805 mono_bitset_free (klass->image->interface_bitset);
2806 klass->image->interface_bitset = new_set;
2809 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2811 mono_bitset_set (klass->image->interface_bitset, iid);
2816 #ifndef MONO_SMALL_CONFIG
2817 if (mono_print_vtable) {
2819 char *type_name = mono_type_full_name (&klass->byval_arg);
2820 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2821 generic_id = klass->generic_class->context.class_inst->id;
2822 g_assert (generic_id != 0);
2826 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2831 g_assert (iid <= 65535);
2836 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2841 mono_class_setup_interfaces (klass, error);
2842 return_if_nok (error);
2844 for (i = 0; i < klass->interface_count; i++) {
2845 ic = klass->interfaces [i];
2848 *res = g_ptr_array_new ();
2849 g_ptr_array_add (*res, ic);
2850 mono_class_init (ic);
2851 if (mono_class_has_failure (ic)) {
2852 mono_error_set_type_load_class (error, ic, "Error Loading class");
2856 collect_implemented_interfaces_aux (ic, res, error);
2857 return_if_nok (error);
2862 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2864 GPtrArray *res = NULL;
2866 collect_implemented_interfaces_aux (klass, &res, error);
2867 if (!mono_error_ok (error)) {
2869 g_ptr_array_free (res, TRUE);
2876 compare_interface_ids (const void *p_key, const void *p_element) {
2877 const MonoClass *key = (const MonoClass *)p_key;
2878 const MonoClass *element = *(const MonoClass **)p_element;
2880 return (key->interface_id - element->interface_id);
2883 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2885 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2886 MonoClass **result = (MonoClass **)mono_binary_search (
2888 klass->interfaces_packed,
2889 klass->interface_offsets_count,
2890 sizeof (MonoClass *),
2891 compare_interface_ids);
2893 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2900 * mono_class_interface_offset_with_variance:
2902 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2903 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2905 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2907 * FIXME figure out MS disambiguation rules and fix this function.
2910 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2911 int i = mono_class_interface_offset (klass, itf);
2912 *non_exact_match = FALSE;
2916 if (!mono_class_has_variant_generic_params (itf))
2919 for (i = 0; i < klass->interface_offsets_count; i++) {
2920 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2921 *non_exact_match = TRUE;
2922 return klass->interface_offsets_packed [i];
2930 print_implemented_interfaces (MonoClass *klass) {
2933 GPtrArray *ifaces = NULL;
2935 int ancestor_level = 0;
2937 name = mono_type_get_full_name (klass);
2938 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2941 for (i = 0; i < klass->interface_offsets_count; i++)
2942 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2943 klass->interfaces_packed [i]->interface_id,
2944 klass->interface_offsets_packed [i],
2945 klass->interfaces_packed [i]->method.count,
2946 klass->interfaces_packed [i]->name_space,
2947 klass->interfaces_packed [i]->name );
2948 printf ("Interface flags: ");
2949 for (i = 0; i <= klass->max_interface_id; i++)
2950 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2951 printf ("(%d,T)", i);
2953 printf ("(%d,F)", i);
2955 printf ("Dump interface flags:");
2956 #ifdef COMPRESSED_INTERFACE_BITMAP
2958 const uint8_t* p = klass->interface_bitmap;
2959 i = klass->max_interface_id;
2961 printf (" %d x 00 %02X", p [0], p [1]);
2967 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2968 printf (" %02X", klass->interface_bitmap [i]);
2971 while (klass != NULL) {
2972 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2973 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2974 if (!mono_error_ok (&error)) {
2975 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2976 mono_error_cleanup (&error);
2977 } else if (ifaces) {
2978 for (i = 0; i < ifaces->len; i++) {
2979 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
2980 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2981 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2983 mono_class_interface_offset (klass, ic),
2988 g_ptr_array_free (ifaces, TRUE);
2991 klass = klass->parent;
2996 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2999 args [0] = &arg0->byval_arg;
3001 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3005 array_class_get_if_rank (MonoClass *klass, guint rank)
3007 return rank ? mono_array_class_get (klass, rank) : klass;
3011 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3013 valuetype_types [0] = eclass;
3014 if (eclass == mono_defaults.int16_class)
3015 valuetype_types [1] = mono_defaults.uint16_class;
3016 else if (eclass == mono_defaults.uint16_class)
3017 valuetype_types [1] = mono_defaults.int16_class;
3018 else if (eclass == mono_defaults.int32_class)
3019 valuetype_types [1] = mono_defaults.uint32_class;
3020 else if (eclass == mono_defaults.uint32_class)
3021 valuetype_types [1] = mono_defaults.int32_class;
3022 else if (eclass == mono_defaults.int64_class)
3023 valuetype_types [1] = mono_defaults.uint64_class;
3024 else if (eclass == mono_defaults.uint64_class)
3025 valuetype_types [1] = mono_defaults.int64_class;
3026 else if (eclass == mono_defaults.byte_class)
3027 valuetype_types [1] = mono_defaults.sbyte_class;
3028 else if (eclass == mono_defaults.sbyte_class)
3029 valuetype_types [1] = mono_defaults.byte_class;
3030 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3031 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3034 /* this won't be needed once bug #325495 is completely fixed
3035 * though we'll need something similar to know which interfaces to allow
3036 * in arrays when they'll be lazyly created
3038 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3039 * MS returns diferrent types based on which instance is called. For example:
3040 * object obj = new byte[10][];
3041 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3042 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3045 * Fixing this should kill quite some code, save some bits and improve compatibility.
3048 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3050 MonoClass *eclass = klass->element_class;
3051 static MonoClass* generic_icollection_class = NULL;
3052 static MonoClass* generic_ienumerable_class = NULL;
3053 static MonoClass* generic_ienumerator_class = NULL;
3054 static MonoClass* generic_ireadonlylist_class = NULL;
3055 static MonoClass* generic_ireadonlycollection_class = NULL;
3056 MonoClass *valuetype_types[2] = { NULL, NULL };
3057 MonoClass **interfaces = NULL;
3058 int i, nifaces, interface_count, real_count, original_rank;
3060 gboolean internal_enumerator;
3061 gboolean eclass_is_valuetype;
3063 if (!mono_defaults.generic_ilist_class) {
3067 internal_enumerator = FALSE;
3068 eclass_is_valuetype = FALSE;
3069 original_rank = eclass->rank;
3070 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3071 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3073 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3075 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3076 original_rank = eclass->rank;
3078 eclass = eclass->element_class;
3079 internal_enumerator = TRUE;
3080 *is_enumerator = TRUE;
3088 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3089 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3091 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3093 if (!generic_icollection_class) {
3094 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3095 "System.Collections.Generic", "ICollection`1");
3096 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3097 "System.Collections.Generic", "IEnumerable`1");
3098 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3099 "System.Collections.Generic", "IEnumerator`1");
3100 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3101 "System.Collections.Generic", "IReadOnlyList`1");
3102 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3103 "System.Collections.Generic", "IReadOnlyCollection`1");
3106 mono_class_init (eclass);
3109 * Arrays in 2.0 need to implement a number of generic interfaces
3110 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3111 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3112 * We collect the types needed to build the
3113 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3114 * the generic interfaces needed to implement.
3116 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3117 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3119 if (eclass->valuetype) {
3120 nifaces = generic_ireadonlylist_class ? 5 : 3;
3121 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3123 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3124 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3125 if (internal_enumerator) {
3127 if (valuetype_types [1])
3131 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3132 interfaces [0] = valuetype_types [0];
3133 if (valuetype_types [1])
3134 interfaces [nifaces] = valuetype_types [1];
3136 eclass_is_valuetype = TRUE;
3139 int idepth = eclass->idepth;
3140 if (!internal_enumerator)
3142 nifaces = generic_ireadonlylist_class ? 2 : 3;
3144 // FIXME: This doesn't seem to work/required for generic params
3145 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3146 mono_class_setup_interface_offsets (eclass);
3148 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3149 /* we add object for interfaces and the supertypes for the other
3150 * types. The last of the supertypes is the element class itself which we
3151 * already created the explicit interfaces for (so we include it for IEnumerator
3152 * and exclude it for arrays).
3154 if (MONO_CLASS_IS_INTERFACE (eclass))
3157 interface_count += idepth;
3158 if (eclass->rank && eclass->element_class->valuetype) {
3159 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3160 if (valuetype_types [1])
3163 /* IList, ICollection, IEnumerable, IReadOnlyList */
3164 interface_count *= nifaces;
3165 real_count = interface_count;
3166 if (internal_enumerator) {
3167 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3168 if (valuetype_types [1])
3171 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3172 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3173 interfaces [0] = mono_defaults.object_class;
3177 for (i = 0; i < idepth; i++) {
3178 mono_class_init (eclass->supertypes [i]);
3179 interfaces [j] = eclass->supertypes [i];
3183 if (all_interfaces) {
3184 for (i = 0; i < eclass->interface_offsets_count; i++) {
3185 interfaces [j] = eclass->interfaces_packed [i];
3189 for (i = 0; i < eclass->interface_count; i++) {
3190 interfaces [j] = eclass->interfaces [i];
3194 if (valuetype_types [1]) {
3195 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3200 /* instantiate the generic interfaces */
3201 for (i = 0; i < interface_count; i += nifaces) {
3202 MonoClass *iface = interfaces [i];
3204 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3205 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3207 if (eclass->valuetype) {
3208 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3209 if (generic_ireadonlylist_class) {
3210 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3211 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3214 if (!generic_ireadonlylist_class)
3215 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3218 if (internal_enumerator) {
3220 /* instantiate IEnumerator<iface> */
3221 for (i = 0; i < interface_count; i++) {
3222 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3224 j = interface_count;
3225 if (!eclass_is_valuetype) {
3226 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3227 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3230 for (i = 0; i < eclass->idepth; i++) {
3231 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3235 for (i = 0; i < eclass->interface_offsets_count; i++) {
3236 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3240 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3242 if (valuetype_types [1])
3243 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3247 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3248 for (i = 0; i < real_count; ++i) {
3249 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3250 g_print ("%s implements %s\n", type_name, name);
3261 find_array_interface (MonoClass *klass, const char *name)
3264 for (i = 0; i < klass->interface_count; ++i) {
3265 if (strcmp (klass->interfaces [i]->name, name) == 0)
3272 * Return the number of virtual methods.
3273 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3274 * Return -1 on failure.
3275 * FIXME It would be nice if this information could be cached somewhere.
3278 count_virtual_methods (MonoClass *klass)
3282 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3284 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3285 mono_class_setup_methods (klass);
3286 if (mono_class_has_failure (klass))
3289 for (i = 0; i < klass->method.count; ++i) {
3290 flags = klass->methods [i]->flags;
3291 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3295 for (i = 0; i < klass->method.count; ++i) {
3296 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3298 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3306 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3314 m = (l + num_ifaces) / 2;
3315 if (interfaces_full [m] == ic)
3317 if (l == num_ifaces)
3319 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3328 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3330 int i = find_interface (num_ifaces, interfaces_full, ic);
3332 return interface_offsets_full [i];
3337 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3339 int i = find_interface (num_ifaces, interfaces_full, ic);
3343 interface_offsets_full [i] = offset;
3346 for (i = 0; i < num_ifaces; ++i) {
3347 if (interfaces_full [i]) {
3349 if (interfaces_full [i]->interface_id < ic->interface_id)
3352 while (end < num_ifaces && interfaces_full [end]) end++;
3353 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3354 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3356 interfaces_full [i] = ic;
3357 interface_offsets_full [i] = offset;
3363 #ifdef COMPRESSED_INTERFACE_BITMAP
3366 * Compressed interface bitmap design.
3368 * Interface bitmaps take a large amount of memory, because their size is
3369 * linear with the maximum interface id assigned in the process (each interface
3370 * is assigned a unique id as it is loaded). The number of interface classes
3371 * is high because of the many implicit interfaces implemented by arrays (we'll
3372 * need to lazy-load them in the future).
3373 * Most classes implement a very small number of interfaces, so the bitmap is
3374 * sparse. This bitmap needs to be checked by interface casts, so access to the
3375 * needed bit must be fast and doable with few jit instructions.
3377 * The current compression format is as follows:
3378 * *) it is a sequence of one or more two-byte elements
3379 * *) the first byte in the element is the count of empty bitmap bytes
3380 * at the current bitmap position
3381 * *) the second byte in the element is an actual bitmap byte at the current
3384 * As an example, the following compressed bitmap bytes:
3385 * 0x07 0x01 0x00 0x7
3386 * correspond to the following bitmap:
3387 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3389 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3390 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3391 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3395 * mono_compress_bitmap:
3396 * @dest: destination buffer
3397 * @bitmap: bitmap buffer
3398 * @size: size of @bitmap in bytes
3400 * This is a mono internal function.
3401 * The @bitmap data is compressed into a format that is small but
3402 * still searchable in few instructions by the JIT and runtime.
3403 * The compressed data is stored in the buffer pointed to by the
3404 * @dest array. Passing a #NULL value for @dest allows to just compute
3405 * the size of the buffer.
3406 * This compression algorithm assumes the bits set in the bitmap are
3407 * few and far between, like in interface bitmaps.
3408 * Returns: The size of the compressed bitmap in bytes.
3411 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3415 const uint8_t *end = bitmap + size;
3416 while (bitmap < end) {
3417 if (*bitmap || numz == 255) {
3441 * mono_class_interface_match:
3442 * @bitmap: a compressed bitmap buffer
3443 * @id: the index to check in the bitmap
3445 * This is a mono internal function.
3446 * Checks if a bit is set in a compressed interface bitmap. @id must
3447 * be already checked for being smaller than the maximum id encoded in the
3450 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3454 mono_class_interface_match (const uint8_t *bitmap, int id)
3457 id -= bitmap [0] * 8;
3461 return bitmap [1] & (1 << id);
3470 * LOCKING: this is supposed to be called with the loader lock held.
3471 * Return -1 on failure and set exception_type
3474 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3478 int i, j, max_iid, num_ifaces;
3479 MonoClass **interfaces_full = NULL;
3480 int *interface_offsets_full = NULL;
3482 GPtrArray **ifaces_array = NULL;
3483 int interface_offsets_count;
3484 MonoClass **array_interfaces = NULL;
3485 int num_array_interfaces;
3486 int is_enumerator = FALSE;
3488 mono_class_setup_supertypes (klass);
3490 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3491 * implicit interfaces have the property that they are assigned the same slot in the
3492 * vtables for compatible interfaces
3494 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3496 /* compute maximum number of slots and maximum interface id */
3498 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3499 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3500 for (j = 0; j < klass->idepth; j++) {
3501 k = klass->supertypes [j];
3502 num_ifaces += k->interface_count;
3503 for (i = 0; i < k->interface_count; i++) {
3504 ic = k->interfaces [i];
3507 mono_class_init (ic);
3509 if (max_iid < ic->interface_id)
3510 max_iid = ic->interface_id;
3512 ifaces = mono_class_get_implemented_interfaces (k, &error);
3513 if (!mono_error_ok (&error)) {
3514 char *name = mono_type_get_full_name (k);
3515 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error)));
3517 mono_error_cleanup (&error);
3522 num_ifaces += ifaces->len;
3523 for (i = 0; i < ifaces->len; ++i) {
3524 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3525 if (max_iid < ic->interface_id)
3526 max_iid = ic->interface_id;
3528 ifaces_array [j] = ifaces;
3532 for (i = 0; i < num_array_interfaces; ++i) {
3533 ic = array_interfaces [i];
3534 mono_class_init (ic);
3535 if (max_iid < ic->interface_id)
3536 max_iid = ic->interface_id;
3539 if (MONO_CLASS_IS_INTERFACE (klass)) {
3541 if (max_iid < klass->interface_id)
3542 max_iid = klass->interface_id;
3544 klass->max_interface_id = max_iid;
3545 /* compute vtable offset for interfaces */
3546 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3547 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3549 for (i = 0; i < num_ifaces; i++) {
3550 interface_offsets_full [i] = -1;
3553 /* skip the current class */
3554 for (j = 0; j < klass->idepth - 1; j++) {
3555 k = klass->supertypes [j];
3556 ifaces = ifaces_array [j];
3559 for (i = 0; i < ifaces->len; ++i) {
3561 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3563 /*Force the sharing of interface offsets between parent and subtypes.*/
3564 io = mono_class_interface_offset (k, ic);
3566 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3571 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3572 ifaces = ifaces_array [klass->idepth - 1];
3574 for (i = 0; i < ifaces->len; ++i) {
3576 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3577 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3579 count = count_virtual_methods (ic);
3581 char *name = mono_type_get_full_name (ic);
3582 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3591 if (MONO_CLASS_IS_INTERFACE (klass))
3592 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3594 if (num_array_interfaces) {
3595 if (is_enumerator) {
3596 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3597 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3598 g_assert (ienumerator_offset >= 0);
3599 for (i = 0; i < num_array_interfaces; ++i) {
3600 ic = array_interfaces [i];
3601 if (strcmp (ic->name, "IEnumerator`1") == 0)
3602 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3604 g_assert_not_reached ();
3605 /*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);*/
3608 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3609 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3610 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3611 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3612 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3613 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3614 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3615 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3616 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3617 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3618 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3619 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3620 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3621 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3622 for (i = 0; i < num_array_interfaces; ++i) {
3624 ic = array_interfaces [i];
3625 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3626 offset = ilist_offset;
3627 else if (strcmp (ic->name, "ICollection`1") == 0)
3628 offset = icollection_offset;
3629 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3630 offset = ienumerable_offset;
3631 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3632 offset = ireadonlylist_offset;
3633 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3634 offset = ireadonlycollection_offset;
3636 g_assert_not_reached ();
3637 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3638 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3643 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3644 if (interface_offsets_full [i] != -1) {
3645 interface_offsets_count ++;
3650 * We might get called multiple times:
3651 * - mono_class_init ()
3652 * - mono_class_setup_vtable ().
3653 * - mono_class_setup_interface_offsets ().
3654 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3655 * means we have to overwrite those when called from other places (#4440).
3657 if (klass->interfaces_packed) {
3659 g_assert (klass->interface_offsets_count == interface_offsets_count);
3663 klass->interface_offsets_count = interface_offsets_count;
3664 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3665 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3666 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3667 #ifdef COMPRESSED_INTERFACE_BITMAP
3668 bitmap = g_malloc0 (bsize);
3670 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3672 for (i = 0; i < interface_offsets_count; i++) {
3673 int id = interfaces_full [i]->interface_id;
3674 bitmap [id >> 3] |= (1 << (id & 7));
3675 klass->interfaces_packed [i] = interfaces_full [i];
3676 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3677 /*if (num_array_interfaces)
3678 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]);*/
3680 #ifdef COMPRESSED_INTERFACE_BITMAP
3681 i = mono_compress_bitmap (NULL, bitmap, bsize);
3682 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3683 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3686 klass->interface_bitmap = bitmap;
3691 g_free (interfaces_full);
3692 g_free (interface_offsets_full);
3693 g_free (array_interfaces);
3694 for (i = 0; i < klass->idepth; i++) {
3695 ifaces = ifaces_array [i];
3697 g_ptr_array_free (ifaces, TRUE);
3699 g_free (ifaces_array);
3701 //printf ("JUST DONE: ");
3702 //print_implemented_interfaces (klass);
3708 * Setup interface offsets for interfaces.
3710 * - klass->max_interface_id
3711 * - klass->interface_offsets_count
3712 * - klass->interfaces_packed
3713 * - klass->interface_offsets_packed
3714 * - klass->interface_bitmap
3716 * This function can fail @class.
3719 mono_class_setup_interface_offsets (MonoClass *klass)
3721 mono_loader_lock ();
3723 setup_interface_offsets (klass, 0, FALSE);
3725 mono_loader_unlock ();
3728 /*Checks if @klass has @parent as one of it's parents type gtd
3732 * Bar<T> : Foo<Bar<Bar<T>>>
3736 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3738 klass = mono_class_get_generic_type_definition (klass);
3739 parent = mono_class_get_generic_type_definition (parent);
3740 mono_class_setup_supertypes (klass);
3741 mono_class_setup_supertypes (parent);
3743 return klass->idepth >= parent->idepth &&
3744 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3748 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3750 MonoGenericInst *ginst;
3752 if (!klass->generic_class) {
3753 mono_class_setup_vtable_full (klass, in_setup);
3754 return !mono_class_has_failure (klass);
3757 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3758 if (mono_class_has_failure (klass->generic_class->container_class)) {
3759 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3763 ginst = klass->generic_class->context.class_inst;
3764 for (i = 0; i < ginst->type_argc; ++i) {
3766 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3768 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3769 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3770 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3772 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3773 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3781 * mono_class_setup_vtable:
3783 * Creates the generic vtable of CLASS.
3784 * Initializes the following fields in MonoClass:
3787 * Plus all the fields initialized by setup_interface_offsets ().
3788 * If there is an error during vtable construction, klass->exception_type is set.
3790 * LOCKING: Acquires the loader lock.
3793 mono_class_setup_vtable (MonoClass *klass)
3795 mono_class_setup_vtable_full (klass, NULL);
3799 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3802 MonoMethod **overrides;
3803 MonoGenericContext *context;
3811 if (MONO_CLASS_IS_INTERFACE (klass)) {
3812 /* This sets method->slot for all methods if this is an interface */
3813 mono_class_setup_methods (klass);
3817 if (mono_class_has_failure (klass))
3820 if (g_list_find (in_setup, klass))
3823 mono_loader_lock ();
3825 if (klass->vtable) {
3826 mono_loader_unlock ();
3830 mono_stats.generic_vtable_count ++;
3831 in_setup = g_list_prepend (in_setup, klass);
3833 if (klass->generic_class) {
3834 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3835 mono_loader_unlock ();
3836 g_list_remove (in_setup, klass);
3840 context = mono_class_get_context (klass);
3841 type_token = klass->generic_class->container_class->type_token;
3843 context = (MonoGenericContext *) klass->generic_container;
3844 type_token = klass->type_token;
3847 if (image_is_dynamic (klass->image)) {
3848 /* Generic instances can have zero method overrides without causing any harm.
3849 * This is true since we don't do layout all over again for them, we simply inflate
3850 * the layout of the parent.
3852 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3853 if (!is_ok (&error)) {
3854 mono_loader_unlock ();
3855 g_list_remove (in_setup, klass);
3856 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf("Could not load list of method overrides due to %s", mono_error_get_message (&error)));
3857 mono_error_cleanup (&error);
3861 /* The following call fails if there are missing methods in the type */
3862 /* FIXME it's probably a good idea to avoid this for generic instances. */
3863 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3867 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3869 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3873 mono_loader_unlock ();
3874 g_list_remove (in_setup, klass);
3879 #define DEBUG_INTERFACE_VTABLE_CODE 0
3880 #define TRACE_INTERFACE_VTABLE_CODE 0
3881 #define VERIFY_INTERFACE_VTABLE_CODE 0
3882 #define VTABLE_SELECTOR (1)
3884 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3885 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3886 if (!(VTABLE_SELECTOR)) break; \
3890 #define DEBUG_INTERFACE_VTABLE(stmt)
3893 #if TRACE_INTERFACE_VTABLE_CODE
3894 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3895 if (!(VTABLE_SELECTOR)) break; \
3899 #define TRACE_INTERFACE_VTABLE(stmt)
3902 #if VERIFY_INTERFACE_VTABLE_CODE
3903 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3904 if (!(VTABLE_SELECTOR)) break; \
3908 #define VERIFY_INTERFACE_VTABLE(stmt)
3912 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3914 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3918 GString *res = g_string_new ("");
3920 g_string_append_c (res, '(');
3921 for (i = 0; i < sig->param_count; ++i) {
3923 g_string_append_c (res, ',');
3924 mono_type_get_desc (res, sig->params [i], include_namespace);
3926 g_string_append (res, ")=>");
3927 if (sig->ret != NULL) {
3928 mono_type_get_desc (res, sig->ret, include_namespace);
3930 g_string_append (res, "NULL");
3933 g_string_free (res, FALSE);
3937 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3938 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3939 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3940 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3948 is_wcf_hack_disabled (void)
3950 static gboolean disabled;
3951 static gboolean inited = FALSE;
3953 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3960 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3962 MonoMethodSignature *cmsig, *imsig;
3963 if (strcmp (im->name, cm->name) == 0) {
3964 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3965 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3968 if (! slot_is_empty) {
3969 if (require_newslot) {
3970 if (! interface_is_explicitly_implemented_by_class) {
3971 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3974 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3975 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3979 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3982 cmsig = mono_method_signature (cm);
3983 imsig = mono_method_signature (im);
3984 if (!cmsig || !imsig) {
3985 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3989 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3990 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3991 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3992 TRACE_INTERFACE_VTABLE (printf ("]"));
3995 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3996 if (mono_security_core_clr_enabled ())
3997 mono_security_core_clr_check_override (klass, cm, im);
3999 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4000 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4001 char *body_name = mono_method_full_name (cm, TRUE);
4002 char *decl_name = mono_method_full_name (im, TRUE);
4003 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4011 MonoClass *ic = im->klass;
4012 const char *ic_name_space = ic->name_space;
4013 const char *ic_name = ic->name;
4016 if (! require_newslot) {
4017 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4020 if (cm->klass->rank == 0) {
4021 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4024 cmsig = mono_method_signature (cm);
4025 imsig = mono_method_signature (im);
4026 if (!cmsig || !imsig) {
4027 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4031 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4032 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4033 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4034 TRACE_INTERFACE_VTABLE (printf ("]"));
4037 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4038 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4041 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4042 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4045 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))) {
4046 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4050 subname = strstr (cm->name, ic_name_space);
4051 if (subname != cm->name) {
4052 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4055 subname += strlen (ic_name_space);
4056 if (subname [0] != '.') {
4057 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4061 if (strstr (subname, ic_name) != subname) {
4062 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4065 subname += strlen (ic_name);
4066 if (subname [0] != '.') {
4067 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4071 if (strcmp (subname, im->name) != 0) {
4072 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4076 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4077 if (mono_security_core_clr_enabled ())
4078 mono_security_core_clr_check_override (klass, cm, im);
4080 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4081 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4082 char *body_name = mono_method_full_name (cm, TRUE);
4083 char *decl_name = mono_method_full_name (im, TRUE);
4084 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4094 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4096 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4097 MonoMethod *method = key;
4098 MonoMethod *override = value;
4099 MonoClass *method_class = mono_method_get_class (method);
4100 MonoClass *override_class = mono_method_get_class (override);
4102 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4103 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4104 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4107 print_overrides (GHashTable *override_map, const char *message) {
4109 printf ("Override map \"%s\" START:\n", message);
4110 g_hash_table_foreach (override_map, foreach_override, NULL);
4111 printf ("Override map \"%s\" END.\n", message);
4113 printf ("Override map \"%s\" EMPTY.\n", message);
4117 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4118 char *full_name = mono_type_full_name (&klass->byval_arg);
4122 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4124 if (print_interfaces) {
4125 print_implemented_interfaces (klass);
4126 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4129 if (klass->parent) {
4130 parent_size = klass->parent->vtable_size;
4134 for (i = 0; i < size; ++i) {
4135 MonoMethod *cm = vtable [i];
4136 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4137 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4139 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4147 #if VERIFY_INTERFACE_VTABLE_CODE
4149 mono_method_try_get_vtable_index (MonoMethod *method)
4151 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4152 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4153 if (imethod->declaring->is_generic)
4154 return imethod->declaring->slot;
4156 return method->slot;
4160 mono_class_verify_vtable (MonoClass *klass)
4163 char *full_name = mono_type_full_name (&klass->byval_arg);
4165 printf ("*** Verifying VTable of class '%s' \n", full_name);
4169 if (!klass->methods)
4172 for (i = 0; i < klass->method.count; ++i) {
4173 MonoMethod *cm = klass->methods [i];
4176 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4180 full_name = mono_method_full_name (cm, TRUE);
4182 slot = mono_method_try_get_vtable_index (cm);
4184 if (slot >= klass->vtable_size) {
4185 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4189 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4190 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4191 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4192 g_free (other_name);
4195 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4202 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4204 char *method_signature;
4207 for (index = 0; index < onum; ++index) {
4208 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4209 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4211 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4212 type_name = mono_type_full_name (&klass->byval_arg);
4213 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4214 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4215 g_free (method_signature);
4217 mono_class_setup_methods (klass);
4218 if (mono_class_has_failure (klass)) {
4219 char *name = mono_type_get_full_name (klass);
4220 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4224 for (index = 0; index < klass->method.count; ++index) {
4225 MonoMethod *cm = klass->methods [index];
4226 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4228 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4229 g_free (method_signature);
4234 mono_method_get_method_definition (MonoMethod *method)
4236 while (method->is_inflated)
4237 method = ((MonoMethodInflated*)method)->declaring;
4242 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4246 for (i = 0; i < onum; ++i) {
4247 MonoMethod *decl = overrides [i * 2];
4248 MonoMethod *body = overrides [i * 2 + 1];
4250 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4251 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4255 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4256 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4257 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4259 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4263 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4264 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4265 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4267 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4271 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4272 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that is not extended or implemented by this type"));
4276 body = mono_method_get_method_definition (body);
4277 decl = mono_method_get_method_definition (decl);
4279 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4280 char *body_name = mono_method_full_name (body, TRUE);
4281 char *decl_name = mono_method_full_name (decl, TRUE);
4282 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4292 mono_class_need_stelemref_method (MonoClass *klass)
4294 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4298 * LOCKING: this is supposed to be called with the loader lock held.
4301 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4305 MonoMethod **vtable;
4306 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4307 GPtrArray *ifaces = NULL;
4308 GHashTable *override_map = NULL;
4310 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4311 int first_non_interface_slot;
4313 GSList *virt_methods = NULL, *l;
4314 int stelemref_slot = 0;
4319 if (overrides && !verify_class_overrides (klass, overrides, onum))
4322 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4323 if (!mono_error_ok (&error)) {
4324 char *name = mono_type_get_full_name (klass);
4325 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error)));
4327 mono_error_cleanup (&error);
4329 } else if (ifaces) {
4330 for (i = 0; i < ifaces->len; i++) {
4331 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4332 max_vtsize += ic->method.count;
4334 g_ptr_array_free (ifaces, TRUE);
4338 if (klass->parent) {
4339 mono_class_init (klass->parent);
4340 mono_class_setup_vtable_full (klass->parent, in_setup);
4342 if (mono_class_has_failure (klass->parent)) {
4343 char *name = mono_type_get_full_name (klass->parent);
4344 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4349 max_vtsize += klass->parent->vtable_size;
4350 cur_slot = klass->parent->vtable_size;
4353 max_vtsize += klass->method.count;
4355 /*Array have a slot for stelemref*/
4356 if (mono_class_need_stelemref_method (klass)) {
4357 stelemref_slot = cur_slot;
4362 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4363 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4365 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4367 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4368 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4371 max_iid = klass->max_interface_id;
4372 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4374 /* Optimized version for generic instances */
4375 if (klass->generic_class) {
4377 MonoClass *gklass = klass->generic_class->container_class;
4380 mono_class_setup_vtable_full (gklass, in_setup);
4381 if (mono_class_has_failure (gklass)) {
4382 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4386 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4387 klass->vtable_size = gklass->vtable_size;
4388 for (i = 0; i < gklass->vtable_size; ++i)
4389 if (gklass->vtable [i]) {
4390 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4391 if (!mono_error_ok (&error)) {
4392 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4393 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4395 mono_error_cleanup (&error);
4399 tmp [i]->slot = gklass->vtable [i]->slot;
4401 mono_memory_barrier ();
4402 klass->vtable = tmp;
4404 /* Have to set method->slot for abstract virtual methods */
4405 if (klass->methods && gklass->methods) {
4406 for (i = 0; i < klass->method.count; ++i)
4407 if (klass->methods [i]->slot == -1)
4408 klass->methods [i]->slot = gklass->methods [i]->slot;
4414 if (klass->parent && klass->parent->vtable_size) {
4415 MonoClass *parent = klass->parent;
4418 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4420 // Also inherit parent interface vtables, just as a starting point.
4421 // This is needed otherwise bug-77127.exe fails when the property methods
4422 // have different names in the iterface and the class, because for child
4423 // classes the ".override" information is not used anymore.
4424 for (i = 0; i < parent->interface_offsets_count; i++) {
4425 MonoClass *parent_interface = parent->interfaces_packed [i];
4426 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4427 /*FIXME this is now dead code as this condition will never hold true.
4428 Since interface offsets are inherited then the offset of an interface implemented
4429 by a parent will never be the out of it's vtable boundary.
4431 if (interface_offset >= parent->vtable_size) {
4432 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4435 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4436 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4437 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4438 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4439 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4440 parent_interface_offset + j, parent_interface_offset, j,
4441 interface_offset + j, interface_offset, j));
4448 /*Array have a slot for stelemref*/
4449 if (mono_class_need_stelemref_method (klass)) {
4450 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4452 method->slot = stelemref_slot;
4454 g_assert (method->slot == stelemref_slot);
4456 vtable [stelemref_slot] = method;
4459 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4460 /* override interface methods */
4461 for (i = 0; i < onum; i++) {
4462 MonoMethod *decl = overrides [i*2];
4463 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4465 dslot = mono_method_get_vtable_slot (decl);
4467 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4471 dslot += mono_class_interface_offset (klass, decl->klass);
4472 vtable [dslot] = overrides [i*2 + 1];
4473 vtable [dslot]->slot = dslot;
4475 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4477 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4479 if (mono_security_core_clr_enabled ())
4480 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4483 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4484 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4487 * Create a list of virtual methods to avoid calling
4488 * mono_class_get_virtual_methods () which is slow because of the metadata
4492 gpointer iter = NULL;
4495 virt_methods = NULL;
4496 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4497 virt_methods = g_slist_prepend (virt_methods, cm);
4499 if (mono_class_has_failure (klass))
4503 // Loop on all implemented interfaces...
4504 for (i = 0; i < klass->interface_offsets_count; i++) {
4505 MonoClass *parent = klass->parent;
4507 gboolean interface_is_explicitly_implemented_by_class;
4510 ic = klass->interfaces_packed [i];
4511 ic_offset = mono_class_interface_offset (klass, ic);
4513 mono_class_setup_methods (ic);
4514 if (mono_class_has_failure (ic))
4517 // Check if this interface is explicitly implemented (instead of just inherited)
4518 if (parent != NULL) {
4519 int implemented_interfaces_index;
4520 interface_is_explicitly_implemented_by_class = FALSE;
4521 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4522 if (ic == klass->interfaces [implemented_interfaces_index]) {
4523 interface_is_explicitly_implemented_by_class = TRUE;
4528 interface_is_explicitly_implemented_by_class = TRUE;
4531 // Loop on all interface methods...
4532 for (im_index = 0; im_index < ic->method.count; im_index++) {
4533 MonoMethod *im = ic->methods [im_index];
4534 int im_slot = ic_offset + im->slot;
4535 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4537 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4540 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4542 // If there is an explicit implementation, just use it right away,
4543 // otherwise look for a matching method
4544 if (override_im == NULL) {
4548 // First look for a suitable method among the class methods
4549 for (l = virt_methods; l; l = l->next) {
4550 cm = (MonoMethod *)l->data;
4551 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)));
4552 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4553 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4554 vtable [im_slot] = cm;
4555 /* Why do we need this? */
4560 TRACE_INTERFACE_VTABLE (printf ("\n"));
4561 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4565 // If the slot is still empty, look in all the inherited virtual methods...
4566 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4567 MonoClass *parent = klass->parent;
4568 // Reverse order, so that last added methods are preferred
4569 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4570 MonoMethod *cm = parent->vtable [cm_index];
4572 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));
4573 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4574 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4575 vtable [im_slot] = cm;
4576 /* Why do we need this? */
4582 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4584 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4588 g_assert (vtable [im_slot] == override_im);
4593 // If the class is not abstract, check that all its interface slots are full.
4594 // The check is done here and not directly at the end of the loop above because
4595 // it can happen (for injected generic array interfaces) that the same slot is
4596 // processed multiple times (those interfaces have overlapping slots), and it
4597 // will not always be the first pass the one that fills the slot.
4598 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4599 for (i = 0; i < klass->interface_offsets_count; i++) {
4603 ic = klass->interfaces_packed [i];
4604 ic_offset = mono_class_interface_offset (klass, ic);
4606 for (im_index = 0; im_index < ic->method.count; im_index++) {
4607 MonoMethod *im = ic->methods [im_index];
4608 int im_slot = ic_offset + im->slot;
4610 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4613 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4614 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4615 if (vtable [im_slot] == NULL) {
4616 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4623 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4624 for (l = virt_methods; l; l = l->next) {
4625 cm = (MonoMethod *)l->data;
4627 * If the method is REUSE_SLOT, we must check in the
4628 * base class for a method to override.
4630 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4632 for (k = klass->parent; k ; k = k->parent) {
4637 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4638 MonoMethodSignature *cmsig, *m1sig;
4640 cmsig = mono_method_signature (cm);
4641 m1sig = mono_method_signature (m1);
4643 if (!cmsig || !m1sig) {
4644 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4648 if (!strcmp(cm->name, m1->name) &&
4649 mono_metadata_signature_equal (cmsig, m1sig)) {
4651 if (mono_security_core_clr_enabled ())
4652 mono_security_core_clr_check_override (klass, cm, m1);
4654 slot = mono_method_get_vtable_slot (m1);
4658 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4659 char *body_name = mono_method_full_name (cm, TRUE);
4660 char *decl_name = mono_method_full_name (m1, TRUE);
4661 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4667 g_assert (cm->slot < max_vtsize);
4669 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4670 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4671 mono_method_full_name (m1, 1), m1,
4672 mono_method_full_name (cm, 1), cm));
4673 g_hash_table_insert (override_map, m1, cm);
4677 if (mono_class_has_failure (k))
4687 /*Non final newslot methods must be given a non-interface vtable slot*/
4688 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4692 cm->slot = cur_slot++;
4694 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4695 vtable [cm->slot] = cm;
4698 /* override non interface methods */
4699 for (i = 0; i < onum; i++) {
4700 MonoMethod *decl = overrides [i*2];
4701 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4702 g_assert (decl->slot != -1);
4703 vtable [decl->slot] = overrides [i*2 + 1];
4704 overrides [i * 2 + 1]->slot = decl->slot;
4706 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4707 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4708 mono_method_full_name (decl, 1), decl,
4709 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4710 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4712 if (mono_security_core_clr_enabled ())
4713 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4718 * If a method occupies more than one place in the vtable, and it is
4719 * overriden, then change the other occurances too.
4724 for (i = 0; i < max_vtsize; ++i)
4726 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4728 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4733 g_hash_table_destroy (override_map);
4734 override_map = NULL;
4737 g_slist_free (virt_methods);
4738 virt_methods = NULL;
4740 /* Ensure that all vtable slots are filled with concrete instance methods */
4741 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4742 for (i = 0; i < cur_slot; ++i) {
4743 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4744 char *type_name = mono_type_get_full_name (klass);
4745 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4746 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name));
4748 g_free (method_name);
4754 if (klass->generic_class) {
4755 MonoClass *gklass = klass->generic_class->container_class;
4757 mono_class_init (gklass);
4759 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4761 /* Check that the vtable_size value computed in mono_class_init () is correct */
4762 if (klass->vtable_size)
4763 g_assert (cur_slot == klass->vtable_size);
4764 klass->vtable_size = cur_slot;
4767 /* Try to share the vtable with our parent. */
4768 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4769 mono_memory_barrier ();
4770 klass->vtable = klass->parent->vtable;
4772 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4773 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4774 mono_memory_barrier ();
4775 klass->vtable = tmp;
4778 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4779 if (mono_print_vtable) {
4782 print_implemented_interfaces (klass);
4784 for (i = 0; i <= max_iid; i++)
4785 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4788 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4789 klass->vtable_size, icount);
4791 for (i = 0; i < cur_slot; ++i) {
4796 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4797 mono_method_full_name (cm, TRUE));
4803 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4804 klass->name, max_iid);
4806 for (i = 0; i < klass->interface_count; i++) {
4807 ic = klass->interfaces [i];
4808 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4809 mono_class_interface_offset (klass, ic),
4810 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4813 for (k = klass->parent; k ; k = k->parent) {
4814 for (i = 0; i < k->interface_count; i++) {
4815 ic = k->interfaces [i];
4816 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4817 mono_class_interface_offset (klass, ic),
4818 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4824 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4829 char *name = mono_type_get_full_name (klass);
4830 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4833 g_hash_table_destroy (override_map);
4835 g_slist_free (virt_methods);
4840 * mono_method_get_vtable_slot:
4842 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4843 * LOCKING: Acquires the loader lock.
4845 * FIXME Use proper MonoError machinery here.
4848 mono_method_get_vtable_slot (MonoMethod *method)
4850 if (method->slot == -1) {
4851 mono_class_setup_vtable (method->klass);
4852 if (mono_class_has_failure (method->klass))
4854 if (method->slot == -1) {
4858 if (!method->klass->generic_class) {
4859 g_assert (method->is_inflated);
4860 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4863 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4864 g_assert (method->klass->generic_class);
4865 gklass = method->klass->generic_class->container_class;
4866 mono_class_setup_methods (method->klass);
4867 g_assert (method->klass->methods);
4868 for (i = 0; i < method->klass->method.count; ++i) {
4869 if (method->klass->methods [i] == method)
4872 g_assert (i < method->klass->method.count);
4873 g_assert (gklass->methods);
4874 method->slot = gklass->methods [i]->slot;
4876 g_assert (method->slot != -1);
4878 return method->slot;
4882 * mono_method_get_vtable_index:
4885 * Returns the index into the runtime vtable to access the method or,
4886 * in the case of a virtual generic method, the virtual generic method
4887 * thunk. Returns -1 on failure.
4889 * FIXME Use proper MonoError machinery here.
4892 mono_method_get_vtable_index (MonoMethod *method)
4894 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4895 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4896 if (imethod->declaring->is_generic)
4897 return mono_method_get_vtable_slot (imethod->declaring);
4899 return mono_method_get_vtable_slot (method);
4902 static MonoMethod *default_ghc = NULL;
4903 static MonoMethod *default_finalize = NULL;
4904 static int finalize_slot = -1;
4905 static int ghc_slot = -1;
4908 initialize_object_slots (MonoClass *klass)
4913 if (klass == mono_defaults.object_class) {
4914 mono_class_setup_vtable (klass);
4915 for (i = 0; i < klass->vtable_size; ++i) {
4916 MonoMethod *cm = klass->vtable [i];
4918 if (!strcmp (cm->name, "GetHashCode"))
4920 else if (!strcmp (cm->name, "Finalize"))
4924 g_assert (ghc_slot > 0);
4925 default_ghc = klass->vtable [ghc_slot];
4927 g_assert (finalize_slot > 0);
4928 default_finalize = klass->vtable [finalize_slot];
4933 MonoMethod *array_method;
4935 } GenericArrayMethodInfo;
4937 static int generic_array_method_num = 0;
4938 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4941 generic_array_methods (MonoClass *klass)
4943 int i, count_generic = 0;
4944 GList *list = NULL, *tmp;
4945 if (generic_array_method_num)
4946 return generic_array_method_num;
4947 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4948 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4949 for (i = 0; i < klass->parent->method.count; i++) {
4950 MonoMethod *m = klass->parent->methods [i];
4951 if (!strncmp (m->name, "InternalArray__", 15)) {
4953 list = g_list_prepend (list, m);
4956 list = g_list_reverse (list);
4957 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4959 for (tmp = list; tmp; tmp = tmp->next) {
4960 const char *mname, *iname;
4962 MonoMethod *m = (MonoMethod *)tmp->data;
4963 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4964 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4966 generic_array_method_info [i].array_method = m;
4967 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4968 iname = "System.Collections.Generic.ICollection`1.";
4969 mname = m->name + 27;
4970 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4971 iname = "System.Collections.Generic.IEnumerable`1.";
4972 mname = m->name + 27;
4973 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4974 iname = "System.Collections.Generic.IReadOnlyList`1.";
4975 mname = m->name + strlen (ireadonlylist_prefix);
4976 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4977 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4978 mname = m->name + strlen (ireadonlycollection_prefix);
4979 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4980 iname = "System.Collections.Generic.IList`1.";
4981 mname = m->name + 15;
4983 g_assert_not_reached ();
4986 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4987 strcpy (name, iname);
4988 strcpy (name + strlen (iname), mname);
4989 generic_array_method_info [i].name = name;
4992 /*g_print ("array generic methods: %d\n", count_generic);*/
4994 generic_array_method_num = count_generic;
4996 return generic_array_method_num;
5000 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5002 MonoGenericContext tmp_context;
5005 tmp_context.class_inst = NULL;
5006 tmp_context.method_inst = iface->generic_class->context.class_inst;
5007 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5009 for (i = 0; i < generic_array_method_num; i++) {
5011 MonoMethod *m = generic_array_method_info [i].array_method;
5012 MonoMethod *inflated;
5014 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5015 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5016 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5021 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5023 int null_length = strlen ("(null)");
5024 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5025 char *s = (char *)mono_image_alloc (image, len);
5028 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5029 g_assert (result == len - 1);
5035 set_failure_from_loader_error (MonoClass *klass, MonoLoaderError *error)
5037 gpointer exception_data = NULL;
5039 switch (error->exception_type) {
5040 case MONO_EXCEPTION_TYPE_LOAD:
5041 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->assembly_name);
5044 case MONO_EXCEPTION_MISSING_METHOD:
5045 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->member_name);
5048 case MONO_EXCEPTION_MISSING_FIELD: {
5049 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5050 const char *class_name;
5053 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5055 class_name = error->klass->name;
5057 exception_data = concat_two_strings_with_zero (klass->image, class_name, error->member_name);
5060 g_free ((void*)class_name);
5064 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5067 if (error->ref_only)
5068 msg = "Cannot resolve dependency to assembly '%s' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.";
5070 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5072 exception_data = concat_two_strings_with_zero (klass->image, msg, error->assembly_name);
5076 case MONO_EXCEPTION_BAD_IMAGE:
5077 exception_data = error->msg;
5081 g_assert_not_reached ();
5084 mono_class_set_failure (klass, error->exception_type, exception_data);
5089 * @class: the class to initialize
5091 * Compute the instance_size, class_size and other infos that cannot be
5092 * computed at mono_class_get() time. Also compute vtable_size if possible.
5093 * Returns TRUE on success or FALSE if there was a problem in loading
5094 * the type (incorrect assemblies, missing assemblies, methods, etc).
5096 * LOCKING: Acquires the loader lock.
5099 mono_class_init (MonoClass *klass)
5102 MonoCachedClassInfo cached_info;
5103 gboolean has_cached_info;
5107 /* Double-checking locking pattern */
5108 if (klass->inited || mono_class_has_failure (klass))
5109 return !mono_class_has_failure (klass);
5111 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5113 /* We do everything inside the lock to prevent races */
5114 mono_loader_lock ();
5116 if (klass->inited || mono_class_has_failure (klass)) {
5117 mono_loader_unlock ();
5118 /* Somebody might have gotten in before us */
5119 return !mono_class_has_failure (klass);
5122 if (klass->init_pending) {
5123 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5127 klass->init_pending = 1;
5129 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5130 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5135 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5136 MonoClass *element_class = klass->element_class;
5137 if (!element_class->inited)
5138 mono_class_init (element_class);
5139 if (mono_class_has_failure (element_class)) {
5140 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5145 mono_stats.initialized_class_count++;
5147 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5148 MonoClass *gklass = klass->generic_class->container_class;
5150 mono_stats.generic_class_count++;
5152 klass->method = gklass->method;
5153 klass->field = gklass->field;
5155 mono_class_init (gklass);
5156 // FIXME: Why is this needed ?
5157 if (!mono_class_has_failure (gklass))
5158 mono_class_setup_methods (gklass);
5159 if (mono_class_has_failure (gklass)) {
5160 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5164 if (MONO_CLASS_IS_INTERFACE (klass))
5165 klass->interface_id = mono_get_unique_iid (klass);
5168 if (klass->parent && !klass->parent->inited)
5169 mono_class_init (klass->parent);
5171 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5173 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5174 klass->nested_classes_inited = TRUE;
5177 * Computes the size used by the fields, and their locations
5179 if (has_cached_info) {
5180 klass->instance_size = cached_info.instance_size;
5181 klass->sizes.class_size = cached_info.class_size;
5182 klass->packing_size = cached_info.packing_size;
5183 klass->min_align = cached_info.min_align;
5184 klass->blittable = cached_info.blittable;
5185 klass->has_references = cached_info.has_references;
5186 klass->has_static_refs = cached_info.has_static_refs;
5187 klass->no_special_static_fields = cached_info.no_special_static_fields;
5190 if (!klass->size_inited){
5191 mono_class_setup_fields (klass);
5192 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
5196 /* Initialize arrays */
5198 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5200 if (klass->interface_count) {
5201 int count_generic = generic_array_methods (klass);
5202 klass->method.count += klass->interface_count * count_generic;
5206 mono_class_setup_supertypes (klass);
5209 initialize_object_slots (klass);
5212 * Initialize the rest of the data without creating a generic vtable if possible.
5213 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5214 * also avoid computing a generic vtable.
5216 if (has_cached_info) {
5218 klass->vtable_size = cached_info.vtable_size;
5219 klass->has_finalize = cached_info.has_finalize;
5220 klass->has_finalize_inited = TRUE;
5221 klass->ghcimpl = cached_info.ghcimpl;
5222 klass->has_cctor = cached_info.has_cctor;
5223 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5224 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5225 * The first slot if for array with.
5227 static int szarray_vtable_size[2] = { 0 };
5229 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5232 if (!szarray_vtable_size [slot]) {
5233 mono_class_setup_vtable (klass);
5234 szarray_vtable_size [slot] = klass->vtable_size;
5236 klass->vtable_size = szarray_vtable_size[slot];
5238 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5239 MonoClass *gklass = klass->generic_class->container_class;
5241 /* Generic instance case */
5242 klass->ghcimpl = gklass->ghcimpl;
5243 klass->has_cctor = gklass->has_cctor;
5245 mono_class_setup_vtable (gklass);
5246 if (mono_class_has_failure (gklass)) {
5247 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5251 klass->vtable_size = gklass->vtable_size;
5255 /* ghcimpl is not currently used
5257 if (klass->parent) {
5258 MonoMethod *cmethod = klass->vtable [ghc_slot];
5259 if (cmethod->is_inflated)
5260 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5261 if (cmethod == default_ghc) {
5267 /* C# doesn't allow interfaces to have cctors */
5268 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5269 MonoMethod *cmethod = NULL;
5271 if (klass->type_token && !image_is_dynamic(klass->image)) {
5272 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5273 /* The find_method function ignores the 'flags' argument */
5274 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5275 klass->has_cctor = 1;
5277 mono_class_setup_methods (klass);
5278 if (mono_class_has_failure (klass))
5281 for (i = 0; i < klass->method.count; ++i) {
5282 MonoMethod *method = klass->methods [i];
5283 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5284 (strcmp (".cctor", method->name) == 0)) {
5285 klass->has_cctor = 1;
5293 if (klass->parent) {
5294 int first_iface_slot;
5295 /* This will compute klass->parent->vtable_size for some classes */
5296 mono_class_init (klass->parent);
5297 if (mono_class_has_failure (klass->parent)) {
5298 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5301 if (mono_loader_get_last_error ())
5303 if (!klass->parent->vtable_size) {
5304 /* FIXME: Get rid of this somehow */
5305 mono_class_setup_vtable (klass->parent);
5306 if (mono_class_has_failure (klass->parent)) {
5307 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5310 if (mono_loader_get_last_error ())
5313 first_iface_slot = klass->parent->vtable_size;
5314 if (mono_class_need_stelemref_method (klass))
5316 setup_interface_offsets (klass, first_iface_slot, TRUE);
5318 setup_interface_offsets (klass, 0, TRUE);
5321 if (mono_security_core_clr_enabled ())
5322 mono_security_core_clr_check_inheritance (klass);
5324 if (mono_loader_get_last_error ()) {
5325 if (!mono_class_has_failure (klass)) {
5326 set_failure_from_loader_error (klass, mono_loader_get_last_error ());
5328 mono_loader_clear_error ();
5331 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5332 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5337 /* Because of the double-checking locking pattern */
5338 mono_memory_barrier ();
5340 klass->init_pending = 0;
5342 mono_loader_unlock ();
5344 return !mono_class_has_failure (klass);
5348 * mono_class_has_finalizer:
5350 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5354 mono_class_has_finalizer (MonoClass *klass)
5356 gboolean has_finalize = FALSE;
5358 if (klass->has_finalize_inited)
5359 return klass->has_finalize;
5361 /* Interfaces and valuetypes are not supposed to have finalizers */
5362 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5363 MonoMethod *cmethod = NULL;
5365 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5366 } else if (klass->generic_class) {
5367 MonoClass *gklass = klass->generic_class->container_class;
5369 has_finalize = mono_class_has_finalizer (gklass);
5370 } else if (klass->parent && klass->parent->has_finalize) {
5371 has_finalize = TRUE;
5373 if (klass->parent) {
5375 * Can't search in metadata for a method named Finalize, because that
5376 * ignores overrides.
5378 mono_class_setup_vtable (klass);
5379 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
5382 cmethod = klass->vtable [finalize_slot];
5386 g_assert (klass->vtable_size > finalize_slot);
5388 if (klass->parent) {
5389 if (cmethod->is_inflated)
5390 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5391 if (cmethod != default_finalize)
5392 has_finalize = TRUE;
5398 mono_image_lock (klass->image);
5400 if (!klass->has_finalize_inited) {
5401 klass->has_finalize = has_finalize ? 1 : 0;
5403 mono_memory_barrier ();
5404 klass->has_finalize_inited = TRUE;
5407 mono_image_unlock (klass->image);
5409 return klass->has_finalize;
5413 mono_is_corlib_image (MonoImage *image)
5415 /* FIXME: allow the dynamic case for our compilers and with full trust */
5416 if (image_is_dynamic (image))
5417 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5419 return image == mono_defaults.corlib;
5423 * LOCKING: this assumes the loader lock is held
5426 mono_class_setup_mono_type (MonoClass *klass)
5428 const char *name = klass->name;
5429 const char *nspace = klass->name_space;
5430 gboolean is_corlib = mono_is_corlib_image (klass->image);
5432 klass->this_arg.byref = 1;
5433 klass->this_arg.data.klass = klass;
5434 klass->this_arg.type = MONO_TYPE_CLASS;
5435 klass->byval_arg.data.klass = klass;
5436 klass->byval_arg.type = MONO_TYPE_CLASS;
5438 if (is_corlib && !strcmp (nspace, "System")) {
5439 if (!strcmp (name, "ValueType")) {
5441 * do not set the valuetype bit for System.ValueType.
5442 * klass->valuetype = 1;
5444 klass->blittable = TRUE;
5445 } else if (!strcmp (name, "Enum")) {
5447 * do not set the valuetype bit for System.Enum.
5448 * klass->valuetype = 1;
5450 klass->valuetype = 0;
5451 klass->enumtype = 0;
5452 } else if (!strcmp (name, "Object")) {
5453 klass->byval_arg.type = MONO_TYPE_OBJECT;
5454 klass->this_arg.type = MONO_TYPE_OBJECT;
5455 } else if (!strcmp (name, "String")) {
5456 klass->byval_arg.type = MONO_TYPE_STRING;
5457 klass->this_arg.type = MONO_TYPE_STRING;
5458 } else if (!strcmp (name, "TypedReference")) {
5459 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5460 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5464 if (klass->valuetype) {
5465 int t = MONO_TYPE_VALUETYPE;
5467 if (is_corlib && !strcmp (nspace, "System")) {
5470 if (!strcmp (name, "Boolean")) {
5471 t = MONO_TYPE_BOOLEAN;
5472 } else if (!strcmp(name, "Byte")) {
5474 klass->blittable = TRUE;
5478 if (!strcmp (name, "Char")) {
5483 if (!strcmp (name, "Double")) {
5485 klass->blittable = TRUE;
5489 if (!strcmp (name, "Int32")) {
5491 klass->blittable = TRUE;
5492 } else if (!strcmp(name, "Int16")) {
5494 klass->blittable = TRUE;
5495 } else if (!strcmp(name, "Int64")) {
5497 klass->blittable = TRUE;
5498 } else if (!strcmp(name, "IntPtr")) {
5500 klass->blittable = TRUE;
5504 if (!strcmp (name, "Single")) {
5506 klass->blittable = TRUE;
5507 } else if (!strcmp(name, "SByte")) {
5509 klass->blittable = TRUE;
5513 if (!strcmp (name, "UInt32")) {
5515 klass->blittable = TRUE;
5516 } else if (!strcmp(name, "UInt16")) {
5518 klass->blittable = TRUE;
5519 } else if (!strcmp(name, "UInt64")) {
5521 klass->blittable = TRUE;
5522 } else if (!strcmp(name, "UIntPtr")) {
5524 klass->blittable = TRUE;
5528 if (!strcmp (name, "TypedReference")) {
5529 t = MONO_TYPE_TYPEDBYREF;
5530 klass->blittable = TRUE;
5534 if (!strcmp (name, "Void")) {
5542 klass->byval_arg.type = (MonoTypeEnum)t;
5543 klass->this_arg.type = (MonoTypeEnum)t;
5546 if (MONO_CLASS_IS_INTERFACE (klass))
5547 klass->interface_id = mono_get_unique_iid (klass);
5553 * COM initialization is delayed until needed.
5554 * However when a [ComImport] attribute is present on a type it will trigger
5555 * the initialization. This is not a problem unless the BCL being executed
5556 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5559 init_com_from_comimport (MonoClass *klass)
5561 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5562 if (mono_security_core_clr_enabled ()) {
5563 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5564 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5565 /* but it can not be made available for application (i.e. user code) since all COM calls
5566 * are considered native calls. In this case we fail with a TypeLoadException (just like
5567 * Silverlight 2 does */
5568 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5573 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5575 #endif /*DISABLE_COM*/
5578 * LOCKING: this assumes the loader lock is held
5581 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5583 gboolean system_namespace;
5584 gboolean is_corlib = mono_is_corlib_image (klass->image);
5586 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5588 /* if root of the hierarchy */
5589 if (system_namespace && !strcmp (klass->name, "Object")) {
5590 klass->parent = NULL;
5591 klass->instance_size = sizeof (MonoObject);
5594 if (!strcmp (klass->name, "<Module>")) {
5595 klass->parent = NULL;
5596 klass->instance_size = 0;
5600 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5601 /* Imported COM Objects always derive from __ComObject. */
5603 if (MONO_CLASS_IS_IMPORT (klass)) {
5604 init_com_from_comimport (klass);
5605 if (parent == mono_defaults.object_class)
5606 parent = mono_class_get_com_object_class ();
5610 /* set the parent to something useful and safe, but mark the type as broken */
5611 parent = mono_defaults.object_class;
5612 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5615 klass->parent = parent;
5617 if (parent->generic_class && !parent->name) {
5619 * If the parent is a generic instance, we may get
5620 * called before it is fully initialized, especially
5621 * before it has its name.
5626 #ifndef DISABLE_REMOTING
5627 klass->marshalbyref = parent->marshalbyref;
5628 klass->contextbound = parent->contextbound;
5631 klass->delegate = parent->delegate;
5633 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5634 mono_class_set_is_com_object (klass);
5636 if (system_namespace) {
5637 #ifndef DISABLE_REMOTING
5638 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5639 klass->marshalbyref = 1;
5641 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5642 klass->contextbound = 1;
5644 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5645 klass->delegate = 1;
5648 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5649 (strcmp (klass->parent->name_space, "System") == 0)))
5650 klass->valuetype = 1;
5651 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5652 klass->valuetype = klass->enumtype = 1;
5654 /*klass->enumtype = klass->parent->enumtype; */
5656 /* initialize com types if COM interfaces are present */
5658 if (MONO_CLASS_IS_IMPORT (klass))
5659 init_com_from_comimport (klass);
5661 klass->parent = NULL;
5667 * mono_class_setup_supertypes:
5670 * Build the data structure needed to make fast type checks work.
5671 * This currently sets two fields in @class:
5672 * - idepth: distance between @class and System.Object in the type
5674 * - supertypes: array of classes: each element has a class in the hierarchy
5675 * starting from @class up to System.Object
5677 * LOCKING: This function is atomic, in case of contention we waste memory.
5680 mono_class_setup_supertypes (MonoClass *klass)
5683 MonoClass **supertypes;
5685 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5689 if (klass->parent && !klass->parent->supertypes)
5690 mono_class_setup_supertypes (klass->parent);
5692 klass->idepth = klass->parent->idepth + 1;
5696 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5697 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5699 if (klass->parent) {
5700 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5703 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5704 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5706 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5709 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5713 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5715 MonoClass *gtd = (MonoClass*)user_data;
5716 /* Only try to fix generic instances of @gtd */
5717 if (gclass->generic_class->container_class != gtd)
5720 /* Check if the generic instance has no parent. */
5721 if (gtd->parent && !gclass->parent)
5722 mono_generic_class_setup_parent (gclass, gtd);
5728 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5730 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5731 mono_error_set_type_load_class (error, klass, msg);
5735 * mono_class_create_from_typedef:
5736 * @image: image where the token is valid
5737 * @type_token: typedef token
5738 * @error: used to return any error found while creating the type
5740 * Create the MonoClass* representing the specified type token.
5741 * @type_token must be a TypeDef token.
5743 * FIXME: don't return NULL on failure, just the the caller figure it out.
5746 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5748 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5749 MonoClass *klass, *parent = NULL;
5750 guint32 cols [MONO_TYPEDEF_SIZE];
5751 guint32 cols_next [MONO_TYPEDEF_SIZE];
5752 guint tidx = mono_metadata_token_index (type_token);
5753 MonoGenericContext *context = NULL;
5754 const char *name, *nspace;
5756 MonoClass **interfaces;
5757 guint32 field_last, method_last;
5758 guint32 nesting_tokeen;
5760 mono_error_init (error);
5762 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5763 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5764 mono_loader_assert_no_error ();
5768 mono_loader_lock ();
5770 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5771 mono_loader_unlock ();
5772 mono_loader_assert_no_error ();
5776 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5778 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5779 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5781 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5784 klass->name_space = nspace;
5786 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5788 klass->image = image;
5789 klass->type_token = type_token;
5790 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5792 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5794 classes_size += sizeof (MonoClass);
5797 * Check whether we're a generic type definition.
5799 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5800 if (klass->generic_container) {
5801 klass->is_generic = 1;
5802 klass->generic_container->owner.klass = klass;
5803 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5804 context = &klass->generic_container->context;
5807 if (klass->generic_container)
5808 enable_gclass_recording ();
5810 if (cols [MONO_TYPEDEF_EXTENDS]) {
5812 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5814 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5815 /*WARNING: this must satisfy mono_metadata_type_hash*/
5816 klass->this_arg.byref = 1;
5817 klass->this_arg.data.klass = klass;
5818 klass->this_arg.type = MONO_TYPE_CLASS;
5819 klass->byval_arg.data.klass = klass;
5820 klass->byval_arg.type = MONO_TYPE_CLASS;
5822 parent = mono_class_get_checked (image, parent_token, error);
5823 if (parent && context) /* Always inflate */
5824 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5826 if (parent == NULL) {
5827 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5828 goto parent_failure;
5831 for (tmp = parent; tmp; tmp = tmp->parent) {
5833 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5834 goto parent_failure;
5836 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5837 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5838 goto parent_failure;
5843 mono_class_setup_parent (klass, parent);
5845 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5846 mono_class_setup_mono_type (klass);
5848 if (klass->generic_container)
5849 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5852 * This might access klass->byval_arg for recursion generated by generic constraints,
5853 * so it has to come after setup_mono_type ().
5855 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5856 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5857 if (!mono_error_ok (error)) {
5858 /*FIXME implement a mono_class_set_failure_from_mono_error */
5859 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5860 mono_loader_unlock ();
5861 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5862 mono_loader_assert_no_error ();
5867 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5871 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5875 klass->cast_class = klass->element_class = klass;
5877 if (!klass->enumtype) {
5878 if (!mono_metadata_interfaces_from_typedef_full (
5879 image, type_token, &interfaces, &icount, FALSE, context, error)){
5881 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5882 mono_loader_unlock ();
5883 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5887 klass->interfaces = interfaces;
5888 klass->interface_count = icount;
5889 klass->interfaces_inited = 1;
5892 /*g_print ("Load class %s\n", name);*/
5895 * Compute the field and method lists
5897 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5898 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5900 if (tt->rows > tidx){
5901 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5902 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5903 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5905 field_last = image->tables [MONO_TABLE_FIELD].rows;
5906 method_last = image->tables [MONO_TABLE_METHOD].rows;
5909 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5910 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5911 klass->field.count = field_last - klass->field.first;
5913 klass->field.count = 0;
5915 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5916 klass->method.count = method_last - klass->method.first;
5918 klass->method.count = 0;
5920 /* reserve space to store vector pointer in arrays */
5921 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5922 klass->instance_size += 2 * sizeof (gpointer);
5923 g_assert (klass->field.count == 0);
5926 if (klass->enumtype) {
5927 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5928 if (!enum_basetype) {
5929 /*set it to a default value as the whole runtime can't handle this to be null*/
5930 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5931 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5932 mono_loader_unlock ();
5933 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5934 mono_loader_assert_no_error ();
5937 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5941 * If we're a generic type definition, load the constraints.
5942 * We must do this after the class has been constructed to make certain recursive scenarios
5945 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5946 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
5947 mono_loader_unlock ();
5948 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5949 mono_loader_assert_no_error ();
5953 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5954 if (!strncmp (name, "Vector", 6))
5955 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");
5958 mono_loader_unlock ();
5960 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5961 mono_loader_assert_no_error ();
5966 mono_class_setup_mono_type (klass);
5967 mono_loader_unlock ();
5968 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5969 mono_loader_assert_no_error ();
5973 /** Is klass a Nullable<T> ginst? */
5975 mono_class_is_nullable (MonoClass *klass)
5977 return klass->generic_class != NULL &&
5978 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5982 /** if klass is T? return T */
5984 mono_class_get_nullable_param (MonoClass *klass)
5986 g_assert (mono_class_is_nullable (klass));
5987 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5991 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5995 MonoGenericClass *gclass = klass->generic_class;
5997 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5998 if (!mono_error_ok (&error)) {
5999 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6000 klass->parent = mono_defaults.object_class;
6001 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6002 mono_error_cleanup (&error);
6006 mono_class_setup_parent (klass, klass->parent);
6008 if (klass->enumtype) {
6009 klass->cast_class = gtd->cast_class;
6010 klass->element_class = gtd->element_class;
6016 * Create the `MonoClass' for an instantiation of a generic type.
6017 * We only do this if we actually need it.
6020 mono_generic_class_get_class (MonoGenericClass *gclass)
6022 MonoClass *klass, *gklass;
6024 if (gclass->cached_class)
6025 return gclass->cached_class;
6027 mono_loader_lock ();
6028 if (gclass->cached_class) {
6029 mono_loader_unlock ();
6030 return gclass->cached_class;
6033 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6035 gklass = gclass->container_class;
6037 if (record_gclass_instantiation > 0)
6038 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6040 if (gklass->nested_in) {
6041 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6042 klass->nested_in = gklass->nested_in;
6045 klass->name = gklass->name;
6046 klass->name_space = gklass->name_space;
6048 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6050 klass->image = gklass->image;
6051 klass->flags = gklass->flags;
6052 klass->type_token = gklass->type_token;
6053 klass->field.count = gklass->field.count;
6055 klass->is_inflated = 1;
6056 klass->generic_class = gclass;
6058 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6059 klass->this_arg.type = klass->byval_arg.type;
6060 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6061 klass->this_arg.byref = TRUE;
6062 klass->enumtype = gklass->enumtype;
6063 klass->valuetype = gklass->valuetype;
6065 klass->cast_class = klass->element_class = klass;
6067 if (mono_class_is_nullable (klass))
6068 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6071 * We're not interested in the nested classes of a generic instance.
6072 * We use the generic type definition to look for nested classes.
6075 mono_generic_class_setup_parent (klass, gklass);
6077 if (gclass->is_dynamic) {
6079 * 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.
6080 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6081 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6083 if (!gklass->wastypebuilder)
6086 mono_class_setup_supertypes (klass);
6088 if (klass->enumtype) {
6090 * For enums, gklass->fields might not been set, but instance_size etc. is
6091 * already set in mono_reflection_create_internal_class (). For non-enums,
6092 * these will be computed normally in mono_class_layout_fields ().
6094 klass->instance_size = gklass->instance_size;
6095 klass->sizes.class_size = gklass->sizes.class_size;
6096 mono_memory_barrier ();
6097 klass->size_inited = 1;
6101 mono_memory_barrier ();
6102 gclass->cached_class = klass;
6104 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6106 inflated_classes ++;
6107 inflated_classes_size += sizeof (MonoClass);
6109 mono_loader_unlock ();
6115 get_image_for_container (MonoGenericContainer *container)
6118 if (container->is_anonymous) {
6119 result = container->owner.image;
6122 if (container->is_method) {
6123 MonoMethod *method = container->owner.method;
6124 g_assert_checked (method);
6125 klass = method->klass;
6127 klass = container->owner.klass;
6129 g_assert_checked (klass);
6130 result = klass->image;
6137 get_image_for_generic_param (MonoGenericParam *param)
6139 MonoGenericContainer *container = mono_generic_param_owner (param);
6140 g_assert_checked (container);
6141 return get_image_for_container (container);
6144 // Make a string in the designated image consisting of a single integer.
6145 #define INT_STRING_SIZE 16
6147 make_generic_name_string (MonoImage *image, int num)
6149 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6150 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6154 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6155 // pinfo is derived from param by the caller for us.
6157 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6159 MonoClass *klass, **ptr;
6161 MonoGenericContainer *container = mono_generic_param_owner (param);
6162 g_assert_checked (container);
6164 MonoImage *image = get_image_for_container (container);
6165 gboolean is_mvar = container->is_method;
6166 gboolean is_anonymous = container->is_anonymous;
6168 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6169 classes_size += sizeof (MonoClass);
6172 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6174 int n = mono_generic_param_num (param);
6175 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6179 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6180 } else if (is_mvar) {
6181 MonoMethod *omethod = container->owner.method;
6182 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6184 MonoClass *oklass = container->owner.klass;
6185 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6188 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6190 // Count non-NULL items in pinfo->constraints
6193 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6197 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6198 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6200 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6201 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6203 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6206 if (count - pos > 0) {
6207 klass->interface_count = count - pos;
6208 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6209 klass->interfaces_inited = TRUE;
6210 for (i = pos; i < count; i++)
6211 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6214 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6216 klass->inited = TRUE;
6217 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6218 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6219 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6221 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6222 klass->this_arg.type = klass->byval_arg.type;
6223 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6224 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6225 klass->this_arg.byref = TRUE;
6227 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6228 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6230 /*Init these fields to sane values*/
6231 klass->min_align = 1;
6233 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6234 * constrained to, the JIT depends on this.
6236 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6237 mono_memory_barrier ();
6238 klass->size_inited = 1;
6239 klass->setup_fields_called = 1;
6241 mono_class_setup_supertypes (klass);
6243 if (count - pos > 0) {
6244 mono_class_setup_vtable (klass->parent);
6245 if (mono_class_has_failure (klass->parent))
6246 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6248 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6254 #define FAST_CACHE_SIZE 16
6257 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6258 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6259 * we cache the MonoClasses.
6260 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6261 * LOCKING: Takes the image lock depending on @take_lock.
6264 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6266 int n = mono_generic_param_num (param);
6267 MonoImage *image = get_image_for_generic_param (param);
6268 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6269 MonoClass *klass = NULL;
6274 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6275 // For high numbers or constraints we have to use pointer hashes.
6276 if (param->gshared_constraint) {
6277 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6280 mono_image_lock (image);
6281 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6283 mono_image_unlock (image);
6288 if (n < FAST_CACHE_SIZE) {
6290 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6292 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6294 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6297 mono_image_lock (image);
6298 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6300 mono_image_unlock (image);
6307 * LOCKING: Image lock (param->image) must be held
6310 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6312 int n = mono_generic_param_num (param);
6313 MonoImage *image = get_image_for_generic_param (param);
6314 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6318 if (param->gshared_constraint) {
6319 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6321 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6322 mono_memory_barrier ();
6324 image->mvar_cache_constrained = ht;
6326 image->var_cache_constrained = ht;
6328 g_hash_table_insert (ht, param, klass);
6329 } else if (n < FAST_CACHE_SIZE) {
6331 /* Requires locking to avoid droping an already published class */
6332 if (!image->mvar_cache_fast)
6333 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6334 image->mvar_cache_fast [n] = klass;
6336 if (!image->var_cache_fast)
6337 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6338 image->var_cache_fast [n] = klass;
6341 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6343 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6345 ht = g_hash_table_new (NULL, NULL);
6346 mono_memory_barrier ();
6348 image->mvar_cache_slow = ht;
6350 image->var_cache_slow = ht;
6353 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6358 * LOCKING: Acquires the image lock (@image).
6361 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6363 MonoImage *image = get_image_for_generic_param (param);
6364 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6365 MonoClass *klass, *klass2;
6367 // If a klass already exists for this object and is cached, return it.
6368 if (pinfo) // Non-anonymous
6369 klass = pinfo->pklass;
6371 klass = get_anon_gparam_class (param, TRUE);
6376 // Create a new klass
6377 klass = make_generic_param_class (param, pinfo);
6379 // Now we need to cache the klass we created.
6380 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6381 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6382 // and allow our newly-created klass object to just leak.
6383 mono_memory_barrier ();
6385 mono_image_lock (image);
6387 // Here "klass2" refers to the klass potentially created by the other thread.
6388 if (pinfo) // Repeat check from above
6389 klass2 = pinfo->pklass;
6391 klass2 = get_anon_gparam_class (param, FALSE);
6398 pinfo->pklass = klass;
6400 set_anon_gparam_class (param, klass);
6402 mono_image_unlock (image);
6404 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6406 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6408 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6414 * mono_class_from_generic_parameter:
6415 * @param: Parameter to find/construct a class for.
6416 * @arg2: Is ignored.
6417 * @arg3: Is ignored.
6420 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6422 return mono_class_from_generic_parameter_internal (param);
6427 mono_ptr_class_get (MonoType *type)
6430 MonoClass *el_class;
6434 el_class = mono_class_from_mono_type (type);
6435 image = el_class->image;
6437 mono_image_lock (image);
6438 if (image->ptr_cache) {
6439 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6440 mono_image_unlock (image);
6444 mono_image_unlock (image);
6446 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6448 classes_size += sizeof (MonoClass);
6450 result->parent = NULL; /* no parent for PTR types */
6451 result->name_space = el_class->name_space;
6452 name = g_strdup_printf ("%s*", el_class->name);
6453 result->name = mono_image_strdup (image, name);
6456 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6458 result->image = el_class->image;
6459 result->inited = TRUE;
6460 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6461 /* Can pointers get boxed? */
6462 result->instance_size = sizeof (gpointer);
6463 result->cast_class = result->element_class = el_class;
6464 result->blittable = TRUE;
6466 result->byval_arg.type = MONO_TYPE_PTR;
6467 result->this_arg.type = result->byval_arg.type;
6468 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6469 result->this_arg.byref = TRUE;
6471 mono_class_setup_supertypes (result);
6473 mono_image_lock (image);
6474 if (image->ptr_cache) {
6476 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6477 mono_image_unlock (image);
6478 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6482 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6484 g_hash_table_insert (image->ptr_cache, el_class, result);
6485 mono_image_unlock (image);
6487 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6493 mono_fnptr_class_get (MonoMethodSignature *sig)
6496 static GHashTable *ptr_hash = NULL;
6498 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6500 mono_loader_lock ();
6503 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6505 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6506 mono_loader_unlock ();
6509 result = g_new0 (MonoClass, 1);
6511 result->parent = NULL; /* no parent for PTR types */
6512 result->name_space = "System";
6513 result->name = "MonoFNPtrFakeClass";
6515 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6517 result->image = mono_defaults.corlib; /* need to fix... */
6518 result->inited = TRUE;
6519 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6520 /* Can pointers get boxed? */
6521 result->instance_size = sizeof (gpointer);
6522 result->cast_class = result->element_class = result;
6523 result->blittable = TRUE;
6525 result->byval_arg.type = MONO_TYPE_FNPTR;
6526 result->this_arg.type = result->byval_arg.type;
6527 result->this_arg.data.method = result->byval_arg.data.method = sig;
6528 result->this_arg.byref = TRUE;
6529 result->blittable = TRUE;
6531 mono_class_setup_supertypes (result);
6533 g_hash_table_insert (ptr_hash, sig, result);
6535 mono_loader_unlock ();
6537 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6543 * mono_class_from_mono_type:
6544 * @type: describes the type to return
6546 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6549 mono_class_from_mono_type (MonoType *type)
6551 switch (type->type) {
6552 case MONO_TYPE_OBJECT:
6553 return type->data.klass? type->data.klass: mono_defaults.object_class;
6554 case MONO_TYPE_VOID:
6555 return type->data.klass? type->data.klass: mono_defaults.void_class;
6556 case MONO_TYPE_BOOLEAN:
6557 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6558 case MONO_TYPE_CHAR:
6559 return type->data.klass? type->data.klass: mono_defaults.char_class;
6561 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6563 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6565 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6567 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6569 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6571 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6573 return type->data.klass? type->data.klass: mono_defaults.int_class;
6575 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6577 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6579 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6581 return type->data.klass? type->data.klass: mono_defaults.single_class;
6583 return type->data.klass? type->data.klass: mono_defaults.double_class;
6584 case MONO_TYPE_STRING:
6585 return type->data.klass? type->data.klass: mono_defaults.string_class;
6586 case MONO_TYPE_TYPEDBYREF:
6587 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6588 case MONO_TYPE_ARRAY:
6589 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6591 return mono_ptr_class_get (type->data.type);
6592 case MONO_TYPE_FNPTR:
6593 return mono_fnptr_class_get (type->data.method);
6594 case MONO_TYPE_SZARRAY:
6595 return mono_array_class_get (type->data.klass, 1);
6596 case MONO_TYPE_CLASS:
6597 case MONO_TYPE_VALUETYPE:
6598 return type->data.klass;
6599 case MONO_TYPE_GENERICINST:
6600 return mono_generic_class_get_class (type->data.generic_class);
6601 case MONO_TYPE_MVAR:
6603 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6605 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6606 g_assert_not_reached ();
6609 // Yes, this returns NULL, even if it is documented as not doing so, but there
6610 // is no way for the code to make it this far, due to the assert above.
6615 * mono_type_retrieve_from_typespec
6616 * @image: context where the image is created
6617 * @type_spec: typespec token
6618 * @context: the generic context used to evaluate generic instantiations in
6621 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6623 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6625 *did_inflate = FALSE;
6630 if (context && (context->class_inst || context->method_inst)) {
6631 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6633 if (!mono_error_ok (error)) {
6634 mono_loader_assert_no_error ();
6640 *did_inflate = TRUE;
6647 * mono_class_create_from_typespec
6648 * @image: context where the image is created
6649 * @type_spec: typespec token
6650 * @context: the generic context used to evaluate generic instantiations in
6653 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6656 gboolean inflated = FALSE;
6657 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6658 return_val_if_nok (error, NULL);
6659 ret = mono_class_from_mono_type (t);
6661 mono_metadata_free_type (t);
6666 * mono_bounded_array_class_get:
6667 * @element_class: element class
6668 * @rank: the dimension of the array class
6669 * @bounded: whenever the array has non-zero bounds
6671 * Returns: A class object describing the array with element type @element_type and
6675 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6679 MonoClass *parent = NULL;
6680 GSList *list, *rootlist = NULL;
6683 gboolean corlib_type = FALSE;
6685 g_assert (rank <= 255);
6688 /* bounded only matters for one-dimensional arrays */
6691 image = eclass->image;
6693 if (rank == 1 && !bounded) {
6695 * This case is very frequent not just during compilation because of calls
6696 * from mono_class_from_mono_type (), mono_array_new (),
6697 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6699 mono_os_mutex_lock (&image->szarray_cache_lock);
6700 if (!image->szarray_cache)
6701 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6702 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6703 mono_os_mutex_unlock (&image->szarray_cache_lock);
6707 mono_loader_lock ();
6709 mono_loader_lock ();
6711 if (!image->array_cache)
6712 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6714 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6715 for (; list; list = list->next) {
6716 klass = (MonoClass *)list->data;
6717 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6718 mono_loader_unlock ();
6725 /* for the building corlib use System.Array from it */
6726 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6727 parent = mono_class_load_from_name (image, "System", "Array");
6730 parent = mono_defaults.array_class;
6731 if (!parent->inited)
6732 mono_class_init (parent);
6735 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6737 klass->image = image;
6738 klass->name_space = eclass->name_space;
6739 nsize = strlen (eclass->name);
6740 name = (char *)g_malloc (nsize + 2 + rank + 1);
6741 memcpy (name, eclass->name, nsize);
6744 memset (name + nsize + 1, ',', rank - 1);
6746 name [nsize + rank] = '*';
6747 name [nsize + rank + bounded] = ']';
6748 name [nsize + rank + bounded + 1] = 0;
6749 klass->name = mono_image_strdup (image, name);
6752 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6754 classes_size += sizeof (MonoClass);
6756 klass->type_token = 0;
6757 /* all arrays are marked serializable and sealed, bug #42779 */
6758 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6759 klass->parent = parent;
6760 klass->instance_size = mono_class_instance_size (klass->parent);
6762 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6763 /*Arrays of those two types are invalid.*/
6764 mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL);
6765 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6766 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6767 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6768 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6770 /* element_size -1 is ok as this is not an instantitable type*/
6771 klass->sizes.element_size = -1;
6773 klass->sizes.element_size = mono_class_array_element_size (eclass);
6775 mono_class_setup_supertypes (klass);
6777 if (eclass->generic_class)
6778 mono_class_init (eclass);
6779 if (!eclass->size_inited)
6780 mono_class_setup_fields (eclass);
6781 if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6782 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6784 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6788 if (eclass->enumtype)
6789 klass->cast_class = eclass->element_class;
6791 klass->cast_class = eclass;
6793 switch (klass->cast_class->byval_arg.type) {
6795 klass->cast_class = mono_defaults.byte_class;
6798 klass->cast_class = mono_defaults.int16_class;
6801 #if SIZEOF_VOID_P == 4
6805 klass->cast_class = mono_defaults.int32_class;
6808 #if SIZEOF_VOID_P == 8
6812 klass->cast_class = mono_defaults.int64_class;
6818 klass->element_class = eclass;
6820 if ((rank > 1) || bounded) {
6821 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6822 klass->byval_arg.type = MONO_TYPE_ARRAY;
6823 klass->byval_arg.data.array = at;
6824 at->eklass = eclass;
6826 /* FIXME: complete.... */
6828 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6829 klass->byval_arg.data.klass = eclass;
6831 klass->this_arg = klass->byval_arg;
6832 klass->this_arg.byref = 1;
6837 klass->generic_container = eclass->generic_container;
6839 if (rank == 1 && !bounded) {
6840 MonoClass *prev_class;
6842 mono_os_mutex_lock (&image->szarray_cache_lock);
6843 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6845 /* Someone got in before us */
6848 g_hash_table_insert (image->szarray_cache, eclass, klass);
6849 mono_os_mutex_unlock (&image->szarray_cache_lock);
6851 list = g_slist_append (rootlist, klass);
6852 g_hash_table_insert (image->array_cache, eclass, list);
6855 mono_loader_unlock ();
6857 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6863 * mono_array_class_get:
6864 * @element_class: element class
6865 * @rank: the dimension of the array class
6867 * Returns: A class object describing the array with element type @element_type and
6871 mono_array_class_get (MonoClass *eclass, guint32 rank)
6873 return mono_bounded_array_class_get (eclass, rank, FALSE);
6877 * mono_class_instance_size:
6880 * Use to get the size of a class in bytes.
6882 * Returns: The size of an object instance
6885 mono_class_instance_size (MonoClass *klass)
6887 if (!klass->size_inited)
6888 mono_class_init (klass);
6890 return klass->instance_size;
6894 * mono_class_min_align:
6897 * Use to get the computed minimum alignment requirements for the specified class.
6899 * Returns: minimm alignment requirements
6902 mono_class_min_align (MonoClass *klass)
6904 if (!klass->size_inited)
6905 mono_class_init (klass);
6907 return klass->min_align;
6911 * mono_class_value_size:
6914 * This function is used for value types, and return the
6915 * space and the alignment to store that kind of value object.
6917 * Returns: the size of a value of kind @klass
6920 mono_class_value_size (MonoClass *klass, guint32 *align)
6924 /* fixme: check disable, because we still have external revereces to
6925 * mscorlib and Dummy Objects
6927 /*g_assert (klass->valuetype);*/
6929 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6932 *align = klass->min_align;
6938 * mono_class_data_size:
6941 * Returns: The size of the static class data
6944 mono_class_data_size (MonoClass *klass)
6947 mono_class_init (klass);
6948 /* This can happen with dynamically created types */
6949 if (!klass->fields_inited)
6950 mono_class_setup_fields_locking (klass);
6952 /* in arrays, sizes.class_size is unioned with element_size
6953 * and arrays have no static fields
6957 return klass->sizes.class_size;
6961 * Auxiliary routine to mono_class_get_field
6963 * Takes a field index instead of a field token.
6965 static MonoClassField *
6966 mono_class_get_field_idx (MonoClass *klass, int idx)
6968 mono_class_setup_fields_locking (klass);
6969 if (mono_class_has_failure (klass))
6973 if (klass->image->uncompressed_metadata) {
6975 * klass->field.first points to the FieldPtr table, while idx points into the
6976 * Field table, so we have to do a search.
6978 /*FIXME this is broken for types with multiple fields with the same name.*/
6979 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6982 for (i = 0; i < klass->field.count; ++i)
6983 if (mono_field_get_name (&klass->fields [i]) == name)
6984 return &klass->fields [i];
6985 g_assert_not_reached ();
6987 if (klass->field.count) {
6988 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6989 return &klass->fields [idx - klass->field.first];
6993 klass = klass->parent;
6999 * mono_class_get_field:
7000 * @class: the class to lookup the field.
7001 * @field_token: the field token
7003 * Returns: A MonoClassField representing the type and offset of
7004 * the field, or a NULL value if the field does not belong to this
7008 mono_class_get_field (MonoClass *klass, guint32 field_token)
7010 int idx = mono_metadata_token_index (field_token);
7012 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7014 return mono_class_get_field_idx (klass, idx - 1);
7018 * mono_class_get_field_from_name:
7019 * @klass: the class to lookup the field.
7020 * @name: the field name
7022 * Search the class @klass and it's parents for a field with the name @name.
7024 * Returns: The MonoClassField pointer of the named field or NULL
7027 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7029 return mono_class_get_field_from_name_full (klass, name, NULL);
7033 * mono_class_get_field_from_name_full:
7034 * @klass: the class to lookup the field.
7035 * @name: the field name
7036 * @type: the type of the fields. This optional.
7038 * Search the class @klass and it's parents for a field with the name @name and type @type.
7040 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7041 * of its generic type definition.
7043 * Returns: The MonoClassField pointer of the named field or NULL
7046 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7050 mono_class_setup_fields_locking (klass);
7051 if (mono_class_has_failure (klass))
7055 for (i = 0; i < klass->field.count; ++i) {
7056 MonoClassField *field = &klass->fields [i];
7058 if (strcmp (name, mono_field_get_name (field)) != 0)
7062 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7063 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7068 klass = klass->parent;
7074 * mono_class_get_field_token:
7075 * @field: the field we need the token of
7077 * Get the token of a field. Note that the tokesn is only valid for the image
7078 * the field was loaded from. Don't use this function for fields in dynamic types.
7080 * Returns: The token representing the field in the image it was loaded from.
7083 mono_class_get_field_token (MonoClassField *field)
7085 MonoClass *klass = field->parent;
7088 mono_class_setup_fields_locking (klass);
7093 for (i = 0; i < klass->field.count; ++i) {
7094 if (&klass->fields [i] == field) {
7095 int idx = klass->field.first + i + 1;
7097 if (klass->image->uncompressed_metadata)
7098 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7099 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7102 klass = klass->parent;
7105 g_assert_not_reached ();
7110 mono_field_get_index (MonoClassField *field)
7112 int index = field - field->parent->fields;
7114 g_assert (index >= 0 && index < field->parent->field.count);
7120 * mono_class_get_field_default_value:
7122 * Return the default value of the field as a pointer into the metadata blob.
7125 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7128 guint32 constant_cols [MONO_CONSTANT_SIZE];
7130 MonoClass *klass = field->parent;
7132 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7134 if (!klass->ext || !klass->ext->field_def_values) {
7135 MonoFieldDefaultValue *def_values;
7137 mono_class_alloc_ext (klass);
7139 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7141 mono_image_lock (klass->image);
7142 mono_memory_barrier ();
7143 if (!klass->ext->field_def_values)
7144 klass->ext->field_def_values = def_values;
7145 mono_image_unlock (klass->image);
7148 field_index = mono_field_get_index (field);
7150 if (!klass->ext->field_def_values [field_index].data) {
7151 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7155 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7157 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7158 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7159 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7162 *def_type = klass->ext->field_def_values [field_index].def_type;
7163 return klass->ext->field_def_values [field_index].data;
7167 mono_property_get_index (MonoProperty *prop)
7169 int index = prop - prop->parent->ext->properties;
7171 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7177 * mono_class_get_property_default_value:
7179 * Return the default value of the field as a pointer into the metadata blob.
7182 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7185 guint32 constant_cols [MONO_CONSTANT_SIZE];
7186 MonoClass *klass = property->parent;
7188 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7190 * We don't cache here because it is not used by C# so it's quite rare, but
7191 * we still do the lookup in klass->ext because that is where the data
7192 * is stored for dynamic assemblies.
7195 if (image_is_dynamic (klass->image)) {
7196 int prop_index = mono_property_get_index (property);
7197 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7198 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7199 return klass->ext->prop_def_values [prop_index].data;
7203 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7207 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7208 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7209 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7213 mono_class_get_event_token (MonoEvent *event)
7215 MonoClass *klass = event->parent;
7220 for (i = 0; i < klass->ext->event.count; ++i) {
7221 if (&klass->ext->events [i] == event)
7222 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7225 klass = klass->parent;
7228 g_assert_not_reached ();
7233 * mono_class_get_property_from_name:
7235 * @name: name of the property to lookup in the specified class
7237 * Use this method to lookup a property in a class
7238 * Returns: the MonoProperty with the given name, or NULL if the property
7239 * does not exist on the @klass.
7242 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7246 gpointer iter = NULL;
7247 while ((p = mono_class_get_properties (klass, &iter))) {
7248 if (! strcmp (name, p->name))
7251 klass = klass->parent;
7257 * mono_class_get_property_token:
7258 * @prop: MonoProperty to query
7260 * Returns: The ECMA token for the specified property.
7263 mono_class_get_property_token (MonoProperty *prop)
7265 MonoClass *klass = prop->parent;
7269 gpointer iter = NULL;
7270 while ((p = mono_class_get_properties (klass, &iter))) {
7271 if (&klass->ext->properties [i] == prop)
7272 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7276 klass = klass->parent;
7279 g_assert_not_reached ();
7284 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7286 const char *name, *nspace;
7287 if (image_is_dynamic (image))
7288 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7290 switch (type_token & 0xff000000){
7291 case MONO_TOKEN_TYPE_DEF: {
7292 guint32 cols [MONO_TYPEDEF_SIZE];
7293 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7294 guint tidx = mono_metadata_token_index (type_token);
7296 if (tidx > tt->rows)
7297 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7299 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7300 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7301 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7302 if (strlen (nspace) == 0)
7303 return g_strdup_printf ("%s", name);
7305 return g_strdup_printf ("%s.%s", nspace, name);
7308 case MONO_TOKEN_TYPE_REF: {
7310 guint32 cols [MONO_TYPEREF_SIZE];
7311 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7312 guint tidx = mono_metadata_token_index (type_token);
7315 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7317 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7318 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7319 mono_error_cleanup (&error);
7323 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7324 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7325 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7326 if (strlen (nspace) == 0)
7327 return g_strdup_printf ("%s", name);
7329 return g_strdup_printf ("%s.%s", nspace, name);
7332 case MONO_TOKEN_TYPE_SPEC:
7333 return g_strdup_printf ("Typespec 0x%08x", type_token);
7335 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7340 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7342 if (image_is_dynamic (image))
7343 return g_strdup_printf ("DynamicAssembly %s", image->name);
7345 switch (type_token & 0xff000000){
7346 case MONO_TOKEN_TYPE_DEF:
7347 if (image->assembly)
7348 return mono_stringify_assembly_name (&image->assembly->aname);
7349 else if (image->assembly_name)
7350 return g_strdup (image->assembly_name);
7351 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7352 case MONO_TOKEN_TYPE_REF: {
7354 MonoAssemblyName aname;
7355 guint32 cols [MONO_TYPEREF_SIZE];
7356 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7357 guint32 idx = mono_metadata_token_index (type_token);
7360 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7362 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7363 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7364 mono_error_cleanup (&error);
7367 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7369 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7370 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7371 case MONO_RESOLUTION_SCOPE_MODULE:
7373 return g_strdup ("");
7374 case MONO_RESOLUTION_SCOPE_MODULEREF:
7376 return g_strdup ("");
7377 case MONO_RESOLUTION_SCOPE_TYPEREF:
7379 return g_strdup ("");
7380 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7381 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7382 return mono_stringify_assembly_name (&aname);
7384 g_assert_not_reached ();
7388 case MONO_TOKEN_TYPE_SPEC:
7390 return g_strdup ("");
7392 g_assert_not_reached ();
7399 * mono_class_get_full:
7400 * @image: the image where the class resides
7401 * @type_token: the token for the class
7402 * @context: the generic context used to evaluate generic instantiations in
7403 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7405 * Returns: The MonoClass that represents @type_token in @image
7408 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7412 klass = mono_class_get_checked (image, type_token, &error);
7414 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7415 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7417 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7423 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7427 mono_error_init (error);
7428 klass = mono_class_get_checked (image, type_token, error);
7430 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7431 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7436 * mono_class_get_checked:
7437 * @image: the image where the class resides
7438 * @type_token: the token for the class
7439 * @error: error object to return any error
7441 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7444 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7446 MonoClass *klass = NULL;
7448 mono_error_init (error);
7450 if (image_is_dynamic (image)) {
7451 int table = mono_metadata_token_table (type_token);
7453 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7454 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7457 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7461 switch (type_token & 0xff000000){
7462 case MONO_TOKEN_TYPE_DEF:
7463 klass = mono_class_create_from_typedef (image, type_token, error);
7465 case MONO_TOKEN_TYPE_REF:
7466 klass = mono_class_from_typeref_checked (image, type_token, error);
7468 case MONO_TOKEN_TYPE_SPEC:
7469 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7472 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7476 /* Generic case, should be avoided for when a better error is possible. */
7477 if (!klass && mono_error_ok (error)) {
7478 char *name = mono_class_name_from_token (image, type_token);
7479 char *assembly = mono_assembly_name_from_token (image, type_token);
7480 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7488 * mono_type_get_checked:
7489 * @image: the image where the type resides
7490 * @type_token: the token for the type
7491 * @context: the generic context used to evaluate generic instantiations in
7492 * @error: Error handling context
7494 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7496 * Returns: The MonoType that represents @type_token in @image
7499 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7501 MonoType *type = NULL;
7502 gboolean inflated = FALSE;
7504 mono_error_init (error);
7506 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7507 if (image_is_dynamic (image)) {
7508 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7509 return_val_if_nok (error, NULL);
7510 return mono_class_get_type (klass);
7513 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7514 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7517 mono_loader_assert_no_error ();
7522 return mono_class_get_type (klass);
7525 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7528 mono_loader_assert_no_error ();
7533 MonoType *tmp = type;
7534 type = mono_class_get_type (mono_class_from_mono_type (type));
7535 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7536 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7537 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7539 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7541 if (type->type != tmp->type)
7544 mono_metadata_free_type (tmp);
7551 * @image: image where the class token will be looked up.
7552 * @type_token: a type token from the image
7554 * Returns the MonoClass with the given @type_token on the @image
7557 mono_class_get (MonoImage *image, guint32 type_token)
7559 return mono_class_get_full (image, type_token, NULL);
7563 * mono_image_init_name_cache:
7565 * Initializes the class name cache stored in image->name_cache.
7567 * LOCKING: Acquires the corresponding image lock.
7570 mono_image_init_name_cache (MonoImage *image)
7572 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7573 guint32 cols [MONO_TYPEDEF_SIZE];
7576 guint32 i, visib, nspace_index;
7577 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7579 if (image->name_cache)
7582 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7584 if (image_is_dynamic (image)) {
7585 mono_image_lock (image);
7586 if (image->name_cache) {
7587 /* Somebody initialized it before us */
7588 g_hash_table_destroy (the_name_cache);
7590 mono_atomic_store_release (&image->name_cache, the_name_cache);
7592 mono_image_unlock (image);
7596 /* Temporary hash table to avoid lookups in the nspace_table */
7597 name_cache2 = g_hash_table_new (NULL, NULL);
7599 for (i = 1; i <= t->rows; ++i) {
7600 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7601 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7603 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7604 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7606 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7608 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7609 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7611 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7612 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7613 if (!nspace_table) {
7614 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7615 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7616 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7619 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7622 /* Load type names from EXPORTEDTYPES table */
7624 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7625 guint32 cols [MONO_EXP_TYPE_SIZE];
7628 for (i = 0; i < t->rows; ++i) {
7629 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7631 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7632 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7636 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7637 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7639 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7640 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7641 if (!nspace_table) {
7642 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7643 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7644 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7647 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7651 g_hash_table_destroy (name_cache2);
7653 mono_image_lock (image);
7654 if (image->name_cache) {
7655 /* Somebody initialized it before us */
7656 g_hash_table_destroy (the_name_cache);
7658 mono_atomic_store_release (&image->name_cache, the_name_cache);
7660 mono_image_unlock (image);
7663 /*FIXME Only dynamic assemblies should allow this operation.*/
7665 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7666 const char *name, guint32 index)
7668 GHashTable *nspace_table;
7669 GHashTable *name_cache;
7672 mono_image_init_name_cache (image);
7673 mono_image_lock (image);
7675 name_cache = image->name_cache;
7676 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7677 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7678 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7681 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7682 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7684 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7686 mono_image_unlock (image);
7695 find_nocase (gpointer key, gpointer value, gpointer user_data)
7697 char *name = (char*)key;
7698 FindUserData *data = (FindUserData*)user_data;
7700 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7701 data->value = value;
7705 * mono_class_from_name_case:
7706 * @image: The MonoImage where the type is looked up in
7707 * @name_space: the type namespace
7708 * @name: the type short name.
7709 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7711 * Obtains a MonoClass with a given namespace and a given name which
7712 * is located in the given MonoImage. The namespace and name
7713 * lookups are case insensitive.
7716 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7719 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7720 mono_error_cleanup (&error);
7726 * mono_class_from_name_case:
7727 * @image: The MonoImage where the type is looked up in
7728 * @name_space: the type namespace
7729 * @name: the type short name.
7732 * Obtains a MonoClass with a given namespace and a given name which
7733 * is located in the given MonoImage. The namespace and name
7734 * lookups are case insensitive.
7736 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7737 * was not found. The @error object will contain information about the problem
7741 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7743 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7744 guint32 cols [MONO_TYPEDEF_SIZE];
7749 mono_error_init (error);
7751 if (image_is_dynamic (image)) {
7753 FindUserData user_data;
7755 mono_image_init_name_cache (image);
7756 mono_image_lock (image);
7758 user_data.key = name_space;
7759 user_data.value = NULL;
7760 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7762 if (user_data.value) {
7763 GHashTable *nspace_table = (GHashTable*)user_data.value;
7765 user_data.key = name;
7766 user_data.value = NULL;
7768 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7770 if (user_data.value)
7771 token = GPOINTER_TO_UINT (user_data.value);
7774 mono_image_unlock (image);
7777 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7783 /* add a cache if needed */
7784 for (i = 1; i <= t->rows; ++i) {
7785 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7786 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7788 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7789 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7791 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7793 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7794 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7795 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7796 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7802 return_nested_in (MonoClass *klass, char *nested)
7805 char *s = strchr (nested, '/');
7806 gpointer iter = NULL;
7813 while ((found = mono_class_get_nested_types (klass, &iter))) {
7814 if (strcmp (found->name, nested) == 0) {
7816 return return_nested_in (found, s);
7824 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7826 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7827 MonoImage *file_image;
7831 mono_error_init (error);
7834 * The EXPORTEDTYPES table only contains public types, so have to search the
7836 * Note: image->modules contains the contents of the MODULEREF table, while
7837 * the real module list is in the FILE table.
7839 for (i = 0; i < file_table->rows; i++) {
7840 guint32 cols [MONO_FILE_SIZE];
7841 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7842 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7845 file_image = mono_image_load_file_for_image (image, i + 1);
7847 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7848 if (klass || !is_ok (error))
7857 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7859 GHashTable *nspace_table;
7860 MonoImage *loaded_image;
7867 mono_error_init (error);
7869 // Checking visited images avoids stack overflows when cyclic references exist.
7870 if (g_hash_table_lookup (visited_images, image))
7873 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7875 if ((nested = strchr (name, '/'))) {
7876 int pos = nested - name;
7877 int len = strlen (name);
7880 memcpy (buf, name, len + 1);
7882 nested = buf + pos + 1;
7886 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7887 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7888 gboolean res = get_class_from_name (image, name_space, name, &klass);
7891 klass = search_modules (image, name_space, name, error);
7896 return klass ? return_nested_in (klass, nested) : NULL;
7902 mono_image_init_name_cache (image);
7903 mono_image_lock (image);
7905 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7908 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7910 mono_image_unlock (image);
7912 if (!token && image_is_dynamic (image) && image->modules) {
7913 /* Search modules as well */
7914 for (i = 0; i < image->module_count; ++i) {
7915 MonoImage *module = image->modules [i];
7917 klass = mono_class_from_name_checked (module, name_space, name, error);
7918 if (klass || !is_ok (error))
7924 klass = search_modules (image, name_space, name, error);
7925 if (klass || !is_ok (error))
7932 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7933 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7934 guint32 cols [MONO_EXP_TYPE_SIZE];
7937 idx = mono_metadata_token_index (token);
7939 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7941 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7942 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7943 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7946 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7948 return klass ? return_nested_in (klass, nested) : NULL;
7950 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7951 guint32 assembly_idx;
7953 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7955 mono_assembly_load_reference (image, assembly_idx - 1);
7956 g_assert (image->references [assembly_idx - 1]);
7957 if (image->references [assembly_idx - 1] == (gpointer)-1)
7959 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7961 return klass ? return_nested_in (klass, nested) : NULL;
7964 g_assert_not_reached ();
7968 token = MONO_TOKEN_TYPE_DEF | token;
7970 klass = mono_class_get_checked (image, token, error);
7972 return return_nested_in (klass, nested);
7977 * mono_class_from_name_checked:
7978 * @image: The MonoImage where the type is looked up in
7979 * @name_space: the type namespace
7980 * @name: the type short name.
7982 * Obtains a MonoClass with a given namespace and a given name which
7983 * is located in the given MonoImage.
7985 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7986 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7989 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7992 GHashTable *visited_images;
7994 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7996 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7998 g_hash_table_destroy (visited_images);
8004 * mono_class_from_name:
8005 * @image: The MonoImage where the type is looked up in
8006 * @name_space: the type namespace
8007 * @name: the type short name.
8009 * Obtains a MonoClass with a given namespace and a given name which
8010 * is located in the given MonoImage.
8012 * To reference nested classes, use the "/" character as a separator.
8013 * For example use "Foo/Bar" to reference the class Bar that is nested
8014 * inside Foo, like this: "class Foo { class Bar {} }".
8017 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8022 klass = mono_class_from_name_checked (image, name_space, name, &error);
8023 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8029 * mono_class_load_from_name:
8030 * @image: The MonoImage where the type is looked up in
8031 * @name_space: the type namespace
8032 * @name: the type short name.
8034 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8035 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8036 * If they are missing. Thing of System.Object or System.String.
8039 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8044 klass = mono_class_from_name_checked (image, name_space, name, &error);
8046 g_error ("Runtime critical type %s.%s not found", name_space, name);
8047 if (!mono_error_ok (&error))
8048 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8053 * mono_class_try_load_from_name:
8054 * @image: The MonoImage where the type is looked up in
8055 * @name_space: the type namespace
8056 * @name: the type short name.
8058 * This function tries to load a type, returning the class was found or NULL otherwise.
8059 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8061 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8062 * a type that we would otherwise assume to be available but was not due some error.
8066 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8071 klass = mono_class_from_name_checked (image, name_space, name, &error);
8072 if (!mono_error_ok (&error))
8073 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8079 * mono_class_is_subclass_of:
8080 * @klass: class to probe if it is a subclass of another one
8081 * @klassc: the class we suspect is the base class
8082 * @check_interfaces: whether we should perform interface checks
8084 * This method determines whether @klass is a subclass of @klassc.
8086 * If the @check_interfaces flag is set, then if @klassc is an interface
8087 * this method return TRUE if the @klass implements the interface or
8088 * if @klass is an interface, if one of its base classes is @klass.
8090 * If @check_interfaces is false then, then if @klass is not an interface
8091 * then it returns TRUE if the @klass is a subclass of @klassc.
8093 * if @klass is an interface and @klassc is System.Object, then this function
8098 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8099 gboolean check_interfaces)
8101 /*FIXME test for interfaces with variant generic arguments*/
8103 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8104 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8106 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8109 for (i = 0; i < klass->interface_count; i ++) {
8110 MonoClass *ic = klass->interfaces [i];
8115 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8120 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8123 if (klassc == mono_defaults.object_class)
8130 mono_type_is_generic_argument (MonoType *type)
8132 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8136 mono_class_has_variant_generic_params (MonoClass *klass)
8139 MonoGenericContainer *container;
8141 if (!klass->generic_class)
8144 container = klass->generic_class->container_class->generic_container;
8146 for (i = 0; i < container->type_argc; ++i)
8147 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8154 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8156 if (target == candidate)
8159 if (check_for_reference_conv &&
8160 mono_type_is_generic_argument (&target->byval_arg) &&
8161 mono_type_is_generic_argument (&candidate->byval_arg)) {
8162 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8163 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8165 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8168 if (!mono_class_is_assignable_from (target, candidate))
8174 * @container the generic container from the GTD
8175 * @klass: the class to be assigned to
8176 * @oklass: the source class
8178 * Both @klass and @oklass must be instances of the same generic interface.
8180 * Returns: TRUE if @klass can be assigned to a @klass variable
8183 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8186 MonoType **klass_argv, **oklass_argv;
8187 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8188 MonoGenericContainer *container = klass_gtd->generic_container;
8190 if (klass == oklass)
8193 /*Viable candidates are instances of the same generic interface*/
8194 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8197 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8198 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8200 for (j = 0; j < container->type_argc; ++j) {
8201 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8202 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8204 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8208 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8209 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8211 if (param1_class != param2_class) {
8212 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8213 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8215 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8216 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8226 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8228 MonoGenericParam *gparam, *ogparam;
8229 MonoGenericParamInfo *tinfo, *cinfo;
8230 MonoClass **candidate_class;
8231 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8234 if (target == candidate)
8236 if (target->byval_arg.type != candidate->byval_arg.type)
8239 gparam = target->byval_arg.data.generic_param;
8240 ogparam = candidate->byval_arg.data.generic_param;
8241 tinfo = mono_generic_param_info (gparam);
8242 cinfo = mono_generic_param_info (ogparam);
8244 class_constraint_satisfied = FALSE;
8245 valuetype_constraint_satisfied = FALSE;
8247 /*candidate must have a super set of target's special constraints*/
8248 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8249 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8251 if (cinfo->constraints) {
8252 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8253 MonoClass *cc = *candidate_class;
8255 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8256 class_constraint_satisfied = TRUE;
8257 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8258 valuetype_constraint_satisfied = TRUE;
8261 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8262 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8264 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8266 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8268 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8269 valuetype_constraint_satisfied)) {
8274 /*candidate type constraints must be a superset of target's*/
8275 if (tinfo->constraints) {
8276 MonoClass **target_class;
8277 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8278 MonoClass *tc = *target_class;
8281 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8282 * check it's constraints since it satisfy the constraint by itself.
8284 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8287 if (!cinfo->constraints)
8290 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8291 MonoClass *cc = *candidate_class;
8293 if (mono_class_is_assignable_from (tc, cc))
8297 * This happens when we have the following:
8299 * Bar<K> where K : IFace
8300 * Foo<T, U> where T : U where U : IFace
8302 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8305 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8306 if (mono_gparam_is_assignable_from (target, cc))
8310 if (!*candidate_class)
8315 /*candidate itself must have a constraint that satisfy target*/
8316 if (cinfo->constraints) {
8317 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8318 MonoClass *cc = *candidate_class;
8319 if (mono_class_is_assignable_from (target, cc))
8327 * mono_class_is_assignable_from:
8328 * @klass: the class to be assigned to
8329 * @oklass: the source class
8331 * Returns: TRUE if an instance of object oklass can be assigned to an
8332 * instance of object @klass
8335 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8338 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8340 mono_class_init (klass);
8342 if (!oklass->inited)
8343 mono_class_init (oklass);
8345 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8348 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8349 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8351 return mono_gparam_is_assignable_from (klass, oklass);
8354 if (MONO_CLASS_IS_INTERFACE (klass)) {
8355 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8356 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8357 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8361 for (i = 0; constraints [i]; ++i) {
8362 if (mono_class_is_assignable_from (klass, constraints [i]))
8370 /* interface_offsets might not be set for dynamic classes */
8371 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8373 * oklass might be a generic type parameter but they have
8374 * interface_offsets set.
8376 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8377 if (!is_ok (&error)) {
8378 mono_error_cleanup (&error);
8383 if (!oklass->interface_bitmap)
8384 /* Happens with generic instances of not-yet created dynamic types */
8386 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8389 if (mono_class_has_variant_generic_params (klass)) {
8391 mono_class_setup_interfaces (oklass, &error);
8392 if (!mono_error_ok (&error)) {
8393 mono_error_cleanup (&error);
8397 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8398 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8399 MonoClass *iface = oklass->interfaces_packed [i];
8401 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8406 } else if (klass->delegate) {
8407 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8409 }else if (klass->rank) {
8410 MonoClass *eclass, *eoclass;
8412 if (oklass->rank != klass->rank)
8415 /* vectors vs. one dimensional arrays */
8416 if (oklass->byval_arg.type != klass->byval_arg.type)
8419 eclass = klass->cast_class;
8420 eoclass = oklass->cast_class;
8423 * a is b does not imply a[] is b[] when a is a valuetype, and
8424 * b is a reference type.
8427 if (eoclass->valuetype) {
8428 if ((eclass == mono_defaults.enum_class) ||
8429 (eclass == mono_defaults.enum_class->parent) ||
8430 (eclass == mono_defaults.object_class))
8434 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8435 } else if (mono_class_is_nullable (klass)) {
8436 if (mono_class_is_nullable (oklass))
8437 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8439 return mono_class_is_assignable_from (klass->cast_class, oklass);
8440 } else if (klass == mono_defaults.object_class)
8443 return mono_class_has_parent (oklass, klass);
8446 /*Check if @oklass is variant compatible with @klass.*/
8448 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8451 MonoType **klass_argv, **oklass_argv;
8452 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8453 MonoGenericContainer *container = klass_gtd->generic_container;
8455 /*Viable candidates are instances of the same generic interface*/
8456 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8459 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8460 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8462 for (j = 0; j < container->type_argc; ++j) {
8463 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8464 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8466 if (param1_class->valuetype != param2_class->valuetype)
8470 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8471 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8473 if (param1_class != param2_class) {
8474 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8475 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8477 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8478 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8486 /*Check if @candidate implements the interface @target*/
8488 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8492 gboolean is_variant = mono_class_has_variant_generic_params (target);
8494 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8495 if (mono_class_is_variant_compatible_slow (target, candidate))
8500 if (candidate == target)
8503 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8504 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8505 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8507 if (tb && tb->interfaces) {
8508 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8509 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8510 MonoClass *iface_class;
8512 /* we can't realize the type here since it can do pretty much anything. */
8515 iface_class = mono_class_from_mono_type (iface->type);
8516 if (iface_class == target)
8518 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8520 if (mono_class_implement_interface_slow (target, iface_class))
8525 /*setup_interfaces don't mono_class_init anything*/
8526 /*FIXME this doesn't handle primitive type arrays.
8527 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8528 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8530 mono_class_setup_interfaces (candidate, &error);
8531 if (!mono_error_ok (&error)) {
8532 mono_error_cleanup (&error);
8536 for (i = 0; i < candidate->interface_count; ++i) {
8537 if (candidate->interfaces [i] == target)
8540 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8543 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8547 candidate = candidate->parent;
8548 } while (candidate);
8554 * Check if @oklass can be assigned to @klass.
8555 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8558 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8560 if (candidate == target)
8562 if (target == mono_defaults.object_class)
8565 if (mono_class_has_parent (candidate, target))
8568 /*If target is not an interface there is no need to check them.*/
8569 if (MONO_CLASS_IS_INTERFACE (target))
8570 return mono_class_implement_interface_slow (target, candidate);
8572 if (target->delegate && mono_class_has_variant_generic_params (target))
8573 return mono_class_is_variant_compatible (target, candidate, FALSE);
8576 MonoClass *eclass, *eoclass;
8578 if (target->rank != candidate->rank)
8581 /* vectors vs. one dimensional arrays */
8582 if (target->byval_arg.type != candidate->byval_arg.type)
8585 eclass = target->cast_class;
8586 eoclass = candidate->cast_class;
8589 * a is b does not imply a[] is b[] when a is a valuetype, and
8590 * b is a reference type.
8593 if (eoclass->valuetype) {
8594 if ((eclass == mono_defaults.enum_class) ||
8595 (eclass == mono_defaults.enum_class->parent) ||
8596 (eclass == mono_defaults.object_class))
8600 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8602 /*FIXME properly handle nullables */
8603 /*FIXME properly handle (M)VAR */
8608 * mono_class_get_cctor:
8609 * @klass: A MonoClass pointer
8611 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8614 mono_class_get_cctor (MonoClass *klass)
8616 MonoCachedClassInfo cached_info;
8618 if (image_is_dynamic (klass->image)) {
8620 * has_cctor is not set for these classes because mono_class_init () is
8623 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8626 if (!klass->has_cctor)
8629 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8631 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8632 if (!mono_error_ok (&error))
8633 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8637 if (klass->generic_class && !klass->methods)
8638 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8640 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8644 * mono_class_get_finalizer:
8645 * @klass: The MonoClass pointer
8647 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8650 mono_class_get_finalizer (MonoClass *klass)
8652 MonoCachedClassInfo cached_info;
8655 mono_class_init (klass);
8656 if (!mono_class_has_finalizer (klass))
8659 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8661 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8662 if (!mono_error_ok (&error))
8663 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8666 mono_class_setup_vtable (klass);
8667 return klass->vtable [finalize_slot];
8672 * mono_class_needs_cctor_run:
8673 * @klass: the MonoClass pointer
8674 * @caller: a MonoMethod describing the caller
8676 * Determines whenever the class has a static constructor and whenever it
8677 * needs to be called when executing CALLER.
8680 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8684 method = mono_class_get_cctor (klass);
8686 return (method == caller) ? FALSE : TRUE;
8692 * mono_class_array_element_size:
8695 * Returns: The number of bytes an element of type @klass
8696 * uses when stored into an array.
8699 mono_class_array_element_size (MonoClass *klass)
8701 MonoType *type = &klass->byval_arg;
8704 switch (type->type) {
8707 case MONO_TYPE_BOOLEAN:
8711 case MONO_TYPE_CHAR:
8720 case MONO_TYPE_CLASS:
8721 case MONO_TYPE_STRING:
8722 case MONO_TYPE_OBJECT:
8723 case MONO_TYPE_SZARRAY:
8724 case MONO_TYPE_ARRAY:
8725 return sizeof (gpointer);
8730 case MONO_TYPE_VALUETYPE:
8731 if (type->data.klass->enumtype) {
8732 type = mono_class_enum_basetype (type->data.klass);
8733 klass = klass->element_class;
8736 return mono_class_instance_size (klass) - sizeof (MonoObject);
8737 case MONO_TYPE_GENERICINST:
8738 type = &type->data.generic_class->container_class->byval_arg;
8741 case MONO_TYPE_MVAR: {
8744 return mono_type_size (type, &align);
8746 case MONO_TYPE_VOID:
8750 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8756 * mono_array_element_size:
8757 * @ac: pointer to a #MonoArrayClass
8759 * Returns: The size of single array element.
8762 mono_array_element_size (MonoClass *ac)
8764 g_assert (ac->rank);
8765 return ac->sizes.element_size;
8769 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8770 MonoGenericContext *context)
8773 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8774 g_assert (mono_error_ok (&error));
8779 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8780 MonoGenericContext *context, MonoError *error)
8782 mono_error_init (error);
8784 if (image_is_dynamic (image)) {
8785 MonoClass *tmp_handle_class;
8786 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8788 mono_error_assert_ok (error);
8789 g_assert (tmp_handle_class);
8791 *handle_class = tmp_handle_class;
8793 if (tmp_handle_class == mono_defaults.typehandle_class)
8794 return &((MonoClass*)obj)->byval_arg;
8799 switch (token & 0xff000000) {
8800 case MONO_TOKEN_TYPE_DEF:
8801 case MONO_TOKEN_TYPE_REF:
8802 case MONO_TOKEN_TYPE_SPEC: {
8805 *handle_class = mono_defaults.typehandle_class;
8806 type = mono_type_get_checked (image, token, context, error);
8810 mono_class_init (mono_class_from_mono_type (type));
8811 /* We return a MonoType* as handle */
8814 case MONO_TOKEN_FIELD_DEF: {
8816 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8818 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8822 *handle_class = mono_defaults.fieldhandle_class;
8823 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8827 mono_class_init (klass);
8828 return mono_class_get_field (klass, token);
8830 case MONO_TOKEN_METHOD_DEF:
8831 case MONO_TOKEN_METHOD_SPEC: {
8833 meth = mono_get_method_checked (image, token, NULL, context, error);
8835 *handle_class = mono_defaults.methodhandle_class;
8841 case MONO_TOKEN_MEMBER_REF: {
8842 guint32 cols [MONO_MEMBERREF_SIZE];
8844 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8845 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8846 mono_metadata_decode_blob_size (sig, &sig);
8847 if (*sig == 0x6) { /* it's a field */
8849 MonoClassField *field;
8850 field = mono_field_from_token_checked (image, token, &klass, context, error);
8852 *handle_class = mono_defaults.fieldhandle_class;
8856 meth = mono_get_method_checked (image, token, NULL, context, error);
8858 *handle_class = mono_defaults.methodhandle_class;
8863 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8869 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8871 MonoClass *handle_class;
8872 mono_error_init (error);
8873 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8877 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8879 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8882 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8885 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8887 get_cached_class_info = func;
8891 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8893 if (!get_cached_class_info)
8896 return get_cached_class_info (klass, res);
8900 mono_install_get_class_from_name (MonoGetClassFromName func)
8902 get_class_from_name = func;
8906 * mono_class_get_image:
8908 * Use this method to get the `MonoImage*` where this class came from.
8910 * Returns: The image where this class is defined.
8913 mono_class_get_image (MonoClass *klass)
8915 return klass->image;
8919 * mono_class_get_element_class:
8920 * @klass: the MonoClass to act on
8922 * Use this function to get the element class of an array.
8924 * Returns: The element class of an array.
8927 mono_class_get_element_class (MonoClass *klass)
8929 return klass->element_class;
8933 * mono_class_is_valuetype:
8934 * @klass: the MonoClass to act on
8936 * Use this method to determine if the provided `MonoClass*` represents a value type,
8937 * or a reference type.
8939 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8942 mono_class_is_valuetype (MonoClass *klass)
8944 return klass->valuetype;
8948 * mono_class_is_enum:
8949 * @klass: the MonoClass to act on
8951 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8953 * Returns: TRUE if the MonoClass represents an enumeration.
8956 mono_class_is_enum (MonoClass *klass)
8958 return klass->enumtype;
8962 * mono_class_enum_basetype:
8963 * @klass: the MonoClass to act on
8965 * Use this function to get the underlying type for an enumeration value.
8967 * Returns: The underlying type representation for an enumeration.
8970 mono_class_enum_basetype (MonoClass *klass)
8972 if (klass->element_class == klass)
8973 /* SRE or broken types */
8976 return &klass->element_class->byval_arg;
8980 * mono_class_get_parent
8981 * @klass: the MonoClass to act on
8983 * Returns: The parent class for this class.
8986 mono_class_get_parent (MonoClass *klass)
8988 return klass->parent;
8992 * mono_class_get_nesting_type:
8993 * @klass: the MonoClass to act on
8995 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8997 * If the return is NULL, this indicates that this class is not nested.
8999 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9002 mono_class_get_nesting_type (MonoClass *klass)
9004 return klass->nested_in;
9008 * mono_class_get_rank:
9009 * @klass: the MonoClass to act on
9011 * Returns: The rank for the array (the number of dimensions).
9014 mono_class_get_rank (MonoClass *klass)
9020 * mono_class_get_flags:
9021 * @klass: the MonoClass to act on
9023 * The type flags from the TypeDef table from the metadata.
9024 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
9027 * Returns: The flags from the TypeDef table.
9030 mono_class_get_flags (MonoClass *klass)
9032 return klass->flags;
9036 * mono_class_get_name
9037 * @klass: the MonoClass to act on
9039 * Returns: The name of the class.
9042 mono_class_get_name (MonoClass *klass)
9048 * mono_class_get_namespace:
9049 * @klass: the MonoClass to act on
9051 * Returns: The namespace of the class.
9054 mono_class_get_namespace (MonoClass *klass)
9056 return klass->name_space;
9060 * mono_class_get_type:
9061 * @klass: the MonoClass to act on
9063 * This method returns the internal Type representation for the class.
9065 * Returns: The MonoType from the class.
9068 mono_class_get_type (MonoClass *klass)
9070 return &klass->byval_arg;
9074 * mono_class_get_type_token:
9075 * @klass: the MonoClass to act on
9077 * This method returns type token for the class.
9079 * Returns: The type token for the class.
9082 mono_class_get_type_token (MonoClass *klass)
9084 return klass->type_token;
9088 * mono_class_get_byref_type:
9089 * @klass: the MonoClass to act on
9094 mono_class_get_byref_type (MonoClass *klass)
9096 return &klass->this_arg;
9100 * mono_class_num_fields:
9101 * @klass: the MonoClass to act on
9103 * Returns: The number of static and instance fields in the class.
9106 mono_class_num_fields (MonoClass *klass)
9108 return klass->field.count;
9112 * mono_class_num_methods:
9113 * @klass: the MonoClass to act on
9115 * Returns: The number of methods in the class.
9118 mono_class_num_methods (MonoClass *klass)
9120 return klass->method.count;
9124 * mono_class_num_properties
9125 * @klass: the MonoClass to act on
9127 * Returns: The number of properties in the class.
9130 mono_class_num_properties (MonoClass *klass)
9132 mono_class_setup_properties (klass);
9134 return klass->ext->property.count;
9138 * mono_class_num_events:
9139 * @klass: the MonoClass to act on
9141 * Returns: The number of events in the class.
9144 mono_class_num_events (MonoClass *klass)
9146 mono_class_setup_events (klass);
9148 return klass->ext->event.count;
9152 * mono_class_get_fields:
9153 * @klass: the MonoClass to act on
9155 * This routine is an iterator routine for retrieving the fields in a class.
9157 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9158 * iterate over all of the elements. When no more values are
9159 * available, the return value is NULL.
9161 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9164 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9166 MonoClassField* field;
9170 mono_class_setup_fields_locking (klass);
9171 if (mono_class_has_failure (klass))
9173 /* start from the first */
9174 if (klass->field.count) {
9175 *iter = &klass->fields [0];
9176 return &klass->fields [0];
9182 field = (MonoClassField *)*iter;
9184 if (field < &klass->fields [klass->field.count]) {
9192 * mono_class_get_methods
9193 * @klass: the MonoClass to act on
9195 * This routine is an iterator routine for retrieving the fields in a class.
9197 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9198 * iterate over all of the elements. When no more values are
9199 * available, the return value is NULL.
9201 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9204 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9206 MonoMethod** method;
9210 mono_class_setup_methods (klass);
9213 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9214 * FIXME we should better report this error to the caller
9216 if (!klass->methods)
9218 /* start from the first */
9219 if (klass->method.count) {
9220 *iter = &klass->methods [0];
9221 return klass->methods [0];
9227 method = (MonoMethod **)*iter;
9229 if (method < &klass->methods [klass->method.count]) {
9237 * mono_class_get_virtual_methods:
9239 * Iterate over the virtual methods of KLASS.
9241 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9244 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9246 MonoMethod** method;
9249 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9251 mono_class_setup_methods (klass);
9253 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9254 * FIXME we should better report this error to the caller
9256 if (!klass->methods)
9258 /* start from the first */
9259 method = &klass->methods [0];
9261 method = (MonoMethod **)*iter;
9264 while (method < &klass->methods [klass->method.count]) {
9265 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9269 if (method < &klass->methods [klass->method.count]) {
9276 /* Search directly in metadata to avoid calling setup_methods () */
9277 MonoMethod *res = NULL;
9283 start_index = GPOINTER_TO_UINT (*iter);
9286 for (i = start_index; i < klass->method.count; ++i) {
9289 /* klass->method.first points into the methodptr table */
9290 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9292 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9296 if (i < klass->method.count) {
9298 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9299 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9301 /* Add 1 here so the if (*iter) check fails */
9302 *iter = GUINT_TO_POINTER (i + 1);
9311 * mono_class_get_properties:
9312 * @klass: the MonoClass to act on
9314 * This routine is an iterator routine for retrieving the properties in a class.
9316 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9317 * iterate over all of the elements. When no more values are
9318 * available, the return value is NULL.
9320 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9323 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9325 MonoProperty* property;
9329 mono_class_setup_properties (klass);
9330 /* start from the first */
9331 if (klass->ext->property.count) {
9332 *iter = &klass->ext->properties [0];
9333 return (MonoProperty *)*iter;
9339 property = (MonoProperty *)*iter;
9341 if (property < &klass->ext->properties [klass->ext->property.count]) {
9343 return (MonoProperty *)*iter;
9349 * mono_class_get_events:
9350 * @klass: the MonoClass to act on
9352 * This routine is an iterator routine for retrieving the properties in a class.
9354 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9355 * iterate over all of the elements. When no more values are
9356 * available, the return value is NULL.
9358 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9361 mono_class_get_events (MonoClass* klass, gpointer *iter)
9367 mono_class_setup_events (klass);
9368 /* start from the first */
9369 if (klass->ext->event.count) {
9370 *iter = &klass->ext->events [0];
9371 return (MonoEvent *)*iter;
9377 event = (MonoEvent *)*iter;
9379 if (event < &klass->ext->events [klass->ext->event.count]) {
9381 return (MonoEvent *)*iter;
9387 * mono_class_get_interfaces
9388 * @klass: the MonoClass to act on
9390 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9392 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9393 * iterate over all of the elements. When no more values are
9394 * available, the return value is NULL.
9396 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9399 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9407 mono_class_init (klass);
9408 if (!klass->interfaces_inited) {
9409 mono_class_setup_interfaces (klass, &error);
9410 if (!mono_error_ok (&error)) {
9411 mono_error_cleanup (&error);
9415 /* start from the first */
9416 if (klass->interface_count) {
9417 *iter = &klass->interfaces [0];
9418 return klass->interfaces [0];
9424 iface = (MonoClass **)*iter;
9426 if (iface < &klass->interfaces [klass->interface_count]) {
9434 setup_nested_types (MonoClass *klass)
9437 GList *classes, *nested_classes, *l;
9440 if (klass->nested_classes_inited)
9443 if (!klass->type_token)
9444 klass->nested_classes_inited = TRUE;
9446 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9450 guint32 cols [MONO_NESTED_CLASS_SIZE];
9451 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9452 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9453 if (!mono_error_ok (&error)) {
9454 /*FIXME don't swallow the error message*/
9455 mono_error_cleanup (&error);
9457 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9461 classes = g_list_prepend (classes, nclass);
9463 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9466 mono_class_alloc_ext (klass);
9468 nested_classes = NULL;
9469 for (l = classes; l; l = l->next)
9470 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9471 g_list_free (classes);
9473 mono_image_lock (klass->image);
9475 mono_memory_barrier ();
9476 if (!klass->nested_classes_inited) {
9477 klass->ext->nested_classes = nested_classes;
9478 mono_memory_barrier ();
9479 klass->nested_classes_inited = TRUE;
9482 mono_image_unlock (klass->image);
9486 * mono_class_get_nested_types
9487 * @klass: the MonoClass to act on
9489 * This routine is an iterator routine for retrieving the nested types of a class.
9490 * This works only if @klass is non-generic, or a generic type definition.
9492 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9493 * iterate over all of the elements. When no more values are
9494 * available, the return value is NULL.
9496 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9499 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9505 if (!klass->nested_classes_inited)
9506 setup_nested_types (klass);
9509 /* start from the first */
9510 if (klass->ext && klass->ext->nested_classes) {
9511 *iter = klass->ext->nested_classes;
9512 return (MonoClass *)klass->ext->nested_classes->data;
9514 /* no nested types */
9518 item = (GList *)*iter;
9522 return (MonoClass *)item->data;
9529 * mono_class_is_delegate
9530 * @klass: the MonoClass to act on
9532 * Returns: TRUE if the MonoClass represents a System.Delegate.
9535 mono_class_is_delegate (MonoClass *klass)
9537 return klass->delegate;
9541 * mono_class_implements_interface
9542 * @klass: The MonoClass to act on
9543 * @interface: The interface to check if @klass implements.
9545 * Returns: TRUE if @klass implements @interface.
9548 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9550 return mono_class_is_assignable_from (iface, klass);
9554 * mono_field_get_name:
9555 * @field: the MonoClassField to act on
9557 * Returns: The name of the field.
9560 mono_field_get_name (MonoClassField *field)
9566 * mono_field_get_type:
9567 * @field: the MonoClassField to act on
9569 * Returns: MonoType of the field.
9572 mono_field_get_type (MonoClassField *field)
9575 MonoType *type = mono_field_get_type_checked (field, &error);
9576 if (!mono_error_ok (&error)) {
9577 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9578 mono_error_cleanup (&error);
9585 * mono_field_get_type_checked:
9586 * @field: the MonoClassField to act on
9587 * @error: used to return any erro found while retrieving @field type
9589 * Returns: MonoType of the field.
9592 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9594 mono_error_init (error);
9596 mono_field_resolve_type (field, error);
9601 * mono_field_get_parent:
9602 * @field: the MonoClassField to act on
9604 * Returns: MonoClass where the field was defined.
9607 mono_field_get_parent (MonoClassField *field)
9609 return field->parent;
9613 * mono_field_get_flags;
9614 * @field: the MonoClassField to act on
9616 * The metadata flags for a field are encoded using the
9617 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9619 * Returns: The flags for the field.
9622 mono_field_get_flags (MonoClassField *field)
9625 return mono_field_resolve_flags (field);
9626 return field->type->attrs;
9630 * mono_field_get_offset:
9631 * @field: the MonoClassField to act on
9633 * Returns: The field offset.
9636 mono_field_get_offset (MonoClassField *field)
9638 return field->offset;
9642 mono_field_get_rva (MonoClassField *field)
9646 MonoClass *klass = field->parent;
9647 MonoFieldDefaultValue *field_def_values;
9649 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9651 if (!klass->ext || !klass->ext->field_def_values) {
9652 mono_class_alloc_ext (klass);
9654 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9656 mono_image_lock (klass->image);
9657 if (!klass->ext->field_def_values)
9658 klass->ext->field_def_values = field_def_values;
9659 mono_image_unlock (klass->image);
9662 field_index = mono_field_get_index (field);
9664 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9665 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9667 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9668 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9671 return klass->ext->field_def_values [field_index].data;
9675 * mono_field_get_data:
9676 * @field: the MonoClassField to act on
9678 * Returns: A pointer to the metadata constant value or to the field
9679 * data if it has an RVA flag.
9682 mono_field_get_data (MonoClassField *field)
9684 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9685 MonoTypeEnum def_type;
9687 return mono_class_get_field_default_value (field, &def_type);
9688 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9689 return mono_field_get_rva (field);
9696 * mono_property_get_name:
9697 * @prop: the MonoProperty to act on
9699 * Returns: The name of the property
9702 mono_property_get_name (MonoProperty *prop)
9708 * mono_property_get_set_method
9709 * @prop: the MonoProperty to act on.
9711 * Returns: The setter method of the property (A MonoMethod)
9714 mono_property_get_set_method (MonoProperty *prop)
9720 * mono_property_get_get_method
9721 * @prop: the MonoProperty to act on.
9723 * Returns: The setter method of the property (A MonoMethod)
9726 mono_property_get_get_method (MonoProperty *prop)
9732 * mono_property_get_parent:
9733 * @prop: the MonoProperty to act on.
9735 * Returns: The MonoClass where the property was defined.
9738 mono_property_get_parent (MonoProperty *prop)
9740 return prop->parent;
9744 * mono_property_get_flags:
9745 * @prop: the MonoProperty to act on.
9747 * The metadata flags for a property are encoded using the
9748 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9750 * Returns: The flags for the property.
9753 mono_property_get_flags (MonoProperty *prop)
9759 * mono_event_get_name:
9760 * @event: the MonoEvent to act on
9762 * Returns: The name of the event.
9765 mono_event_get_name (MonoEvent *event)
9771 * mono_event_get_add_method:
9772 * @event: The MonoEvent to act on.
9774 * Returns: The @add' method for the event (a MonoMethod).
9777 mono_event_get_add_method (MonoEvent *event)
9783 * mono_event_get_remove_method:
9784 * @event: The MonoEvent to act on.
9786 * Returns: The @remove method for the event (a MonoMethod).
9789 mono_event_get_remove_method (MonoEvent *event)
9791 return event->remove;
9795 * mono_event_get_raise_method:
9796 * @event: The MonoEvent to act on.
9798 * Returns: The @raise method for the event (a MonoMethod).
9801 mono_event_get_raise_method (MonoEvent *event)
9803 return event->raise;
9807 * mono_event_get_parent:
9808 * @event: the MonoEvent to act on.
9810 * Returns: The MonoClass where the event is defined.
9813 mono_event_get_parent (MonoEvent *event)
9815 return event->parent;
9819 * mono_event_get_flags
9820 * @event: the MonoEvent to act on.
9822 * The metadata flags for an event are encoded using the
9823 * EVENT_* constants. See the tabledefs.h file for details.
9825 * Returns: The flags for the event.
9828 mono_event_get_flags (MonoEvent *event)
9830 return event->attrs;
9834 * mono_class_get_method_from_name:
9835 * @klass: where to look for the method
9836 * @name: name of the method
9837 * @param_count: number of parameters. -1 for any number.
9839 * Obtains a MonoMethod with a given name and number of parameters.
9840 * It only works if there are no multiple signatures for any given method name.
9843 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9845 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9849 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9851 MonoMethod *res = NULL;
9854 /* Search directly in the metadata to avoid calling setup_methods () */
9855 for (i = 0; i < klass->method.count; ++i) {
9857 guint32 cols [MONO_METHOD_SIZE];
9859 MonoMethodSignature *sig;
9861 /* klass->method.first points into the methodptr table */
9862 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9864 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9865 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9867 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9870 if (param_count == -1) {
9874 sig = mono_method_signature_checked (method, &error);
9876 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9879 if (sig->param_count == param_count) {
9890 * mono_class_get_method_from_name_flags:
9891 * @klass: where to look for the method
9892 * @name_space: name of the method
9893 * @param_count: number of parameters. -1 for any number.
9894 * @flags: flags which must be set in the method
9896 * Obtains a MonoMethod with a given name and number of parameters.
9897 * It only works if there are no multiple signatures for any given method name.
9900 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9902 MonoMethod *res = NULL;
9905 mono_class_init (klass);
9907 if (klass->generic_class && !klass->methods) {
9908 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9911 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9912 if (!mono_error_ok (&error))
9913 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9918 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9919 mono_class_setup_methods (klass);
9921 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9922 See mono/tests/array_load_exception.il
9923 FIXME we should better report this error to the caller
9925 if (!klass->methods)
9927 for (i = 0; i < klass->method.count; ++i) {
9928 MonoMethod *method = klass->methods [i];
9930 if (method->name[0] == name [0] &&
9931 !strcmp (name, method->name) &&
9932 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9933 ((method->flags & flags) == flags)) {
9940 res = find_method_in_metadata (klass, name, param_count, flags);
9947 * mono_class_set_failure:
9948 * @klass: class in which the failure was detected
9949 * @ex_type: the kind of exception/error to be thrown (later)
9950 * @ex_data: exception data (specific to each type of exception/error)
9952 * Keep a detected failure informations in the class for later processing.
9953 * Note that only the first failure is kept.
9955 * LOCKING: Acquires the loader lock.
9958 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9960 if (mono_class_has_failure (klass))
9963 mono_loader_lock ();
9964 klass->exception_type = ex_type;
9966 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9967 mono_loader_unlock ();
9973 * mono_class_get_exception_data:
9975 * Return the exception_data property of KLASS.
9977 * LOCKING: Acquires the loader lock.
9980 mono_class_get_exception_data (MonoClass *klass)
9982 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9986 * mono_classes_init:
9988 * Initialize the resources used by this module.
9991 mono_classes_init (void)
9993 mono_os_mutex_init (&classes_mutex);
9995 mono_counters_register ("Inflated methods size",
9996 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9997 mono_counters_register ("Inflated classes",
9998 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9999 mono_counters_register ("Inflated classes size",
10000 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10001 mono_counters_register ("MonoClass size",
10002 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10003 mono_counters_register ("MonoClassExt size",
10004 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10008 * mono_classes_cleanup:
10010 * Free the resources used by this module.
10013 mono_classes_cleanup (void)
10015 if (global_interface_bitset)
10016 mono_bitset_free (global_interface_bitset);
10017 global_interface_bitset = NULL;
10018 mono_os_mutex_destroy (&classes_mutex);
10022 * mono_class_get_exception_for_failure:
10023 * @klass: class in which the failure was detected
10025 * Return a constructed MonoException than the caller can then throw
10026 * using mono_raise_exception - or NULL if no failure is present (or
10027 * doesn't result in an exception).
10030 mono_class_get_exception_for_failure (MonoClass *klass)
10032 gpointer exception_data = mono_class_get_exception_data (klass);
10034 switch (mono_class_get_failure(klass)) {
10035 case MONO_EXCEPTION_TYPE_LOAD: {
10038 char *str = mono_type_get_full_name (klass);
10039 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
10040 name = mono_string_new (mono_domain_get (), str);
10042 ex = mono_get_exception_type_load (name, astr);
10046 case MONO_EXCEPTION_MISSING_METHOD: {
10047 char *class_name = (char *)exception_data;
10048 char *assembly_name = class_name + strlen (class_name) + 1;
10050 return mono_get_exception_missing_method (class_name, assembly_name);
10052 case MONO_EXCEPTION_MISSING_FIELD: {
10053 char *class_name = (char *)exception_data;
10054 char *member_name = class_name + strlen (class_name) + 1;
10056 return mono_get_exception_missing_field (class_name, member_name);
10058 case MONO_EXCEPTION_FILE_NOT_FOUND: {
10059 char *msg_format = (char *)exception_data;
10060 char *assembly_name = msg_format + strlen (msg_format) + 1;
10061 char *msg = g_strdup_printf (msg_format, assembly_name);
10064 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10070 case MONO_EXCEPTION_BAD_IMAGE: {
10071 return mono_get_exception_bad_image_format ((const char *)exception_data);
10073 case MONO_EXCEPTION_INVALID_PROGRAM: {
10074 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10077 /* TODO - handle other class related failures */
10078 return mono_get_exception_execution_engine ("Unknown class failure");
10084 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10086 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10087 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10089 if (outer_klass == inner_klass)
10091 inner_klass = inner_klass->nested_in;
10092 } while (inner_klass);
10097 mono_class_get_generic_type_definition (MonoClass *klass)
10099 return klass->generic_class ? klass->generic_class->container_class : klass;
10103 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10105 * Generic instantiations are ignored for all super types of @klass.
10107 * Visibility checks ignoring generic instantiations.
10110 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10113 klass = mono_class_get_generic_type_definition (klass);
10114 parent = mono_class_get_generic_type_definition (parent);
10115 mono_class_setup_supertypes (klass);
10117 for (i = 0; i < klass->idepth; ++i) {
10118 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10124 * Subtype can only access parent members with family protection if the site object
10125 * is subclass of Subtype. For example:
10126 * class A { protected int x; }
10128 * void valid_access () {
10132 * void invalid_access () {
10139 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10141 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10144 if (context_klass == NULL)
10146 /*if access_klass is not member_klass context_klass must be type compat*/
10147 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10153 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10156 if (accessing == accessed)
10158 if (!accessed || !accessing)
10161 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10162 * anywhere so untrusted friends are not safe to access platform's code internals */
10163 if (mono_security_core_clr_enabled ()) {
10164 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10168 mono_assembly_load_friends (accessed);
10169 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10170 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10171 /* Be conservative with checks */
10172 if (!friend_->name)
10174 if (strcmp (accessing->aname.name, friend_->name))
10176 if (friend_->public_key_token [0]) {
10177 if (!accessing->aname.public_key_token [0])
10179 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10188 * If klass is a generic type or if it is derived from a generic type, return the
10189 * MonoClass of the generic definition
10190 * Returns NULL if not found
10193 get_generic_definition_class (MonoClass *klass)
10196 if (klass->generic_class && klass->generic_class->container_class)
10197 return klass->generic_class->container_class;
10198 klass = klass->parent;
10204 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10207 for (i = 0; i < ginst->type_argc; ++i) {
10208 MonoType *type = ginst->type_argv[i];
10209 switch (type->type) {
10210 case MONO_TYPE_SZARRAY:
10211 if (!can_access_type (access_klass, type->data.klass))
10214 case MONO_TYPE_ARRAY:
10215 if (!can_access_type (access_klass, type->data.array->eklass))
10218 case MONO_TYPE_PTR:
10219 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10222 case MONO_TYPE_CLASS:
10223 case MONO_TYPE_VALUETYPE:
10224 case MONO_TYPE_GENERICINST:
10225 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10235 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10239 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10242 if (access_klass->element_class && !access_klass->enumtype)
10243 access_klass = access_klass->element_class;
10245 if (member_klass->element_class && !member_klass->enumtype)
10246 member_klass = member_klass->element_class;
10248 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10250 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10253 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10256 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10259 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10262 /*Non nested type with nested visibility. We just fail it.*/
10263 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10266 switch (access_level) {
10267 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10268 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10270 case TYPE_ATTRIBUTE_PUBLIC:
10273 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10276 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10277 return is_nesting_type (member_klass, access_klass);
10279 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10280 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10282 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10283 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10285 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10286 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10287 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10289 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10290 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10291 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10296 /* FIXME: check visibility of type, too */
10298 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10300 MonoClass *member_generic_def;
10301 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10304 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10305 access_klass->generic_container) &&
10306 (member_generic_def = get_generic_definition_class (member_klass))) {
10307 MonoClass *access_container;
10309 if (access_klass->generic_container)
10310 access_container = access_klass;
10312 access_container = access_klass->generic_class->container_class;
10314 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10318 /* Partition I 8.5.3.2 */
10319 /* the access level values are the same for fields and methods */
10320 switch (access_level) {
10321 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10322 /* same compilation unit */
10323 return access_klass->image == member_klass->image;
10324 case FIELD_ATTRIBUTE_PRIVATE:
10325 return access_klass == member_klass;
10326 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10327 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10328 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10331 case FIELD_ATTRIBUTE_ASSEMBLY:
10332 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10333 case FIELD_ATTRIBUTE_FAMILY:
10334 if (is_valid_family_access (access_klass, member_klass, context_klass))
10337 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10338 if (is_valid_family_access (access_klass, member_klass, context_klass))
10340 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10341 case FIELD_ATTRIBUTE_PUBLIC:
10348 * mono_method_can_access_field:
10349 * @method: Method that will attempt to access the field
10350 * @field: the field to access
10352 * Used to determine if a method is allowed to access the specified field.
10354 * Returns: TRUE if the given @method is allowed to access the @field while following
10355 * the accessibility rules of the CLI.
10358 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10360 /* FIXME: check all overlapping fields */
10361 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10363 MonoClass *nested = method->klass->nested_in;
10365 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10368 nested = nested->nested_in;
10375 * mono_method_can_access_method:
10376 * @method: Method that will attempt to access the other method
10377 * @called: the method that we want to probe for accessibility.
10379 * Used to determine if the @method is allowed to access the specified @called method.
10381 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10382 * the accessibility rules of the CLI.
10385 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10387 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10389 MonoClass *nested = method->klass->nested_in;
10391 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10394 nested = nested->nested_in;
10399 * with generics calls to explicit interface implementations can be expressed
10400 * directly: the method is private, but we must allow it. This may be opening
10401 * a hole or the generics code should handle this differently.
10402 * Maybe just ensure the interface type is public.
10404 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10410 * mono_method_can_access_method_full:
10411 * @method: The caller method
10412 * @called: The called method
10413 * @context_klass: The static type on stack of the owner @called object used
10415 * This function must be used with instance calls, as they have more strict family accessibility.
10416 * It can be used with static methods, but context_klass should be NULL.
10418 * Returns: TRUE if caller have proper visibility and acessibility to @called
10421 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10423 MonoClass *access_class = method->klass;
10424 MonoClass *member_class = called->klass;
10425 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10427 MonoClass *nested = access_class->nested_in;
10429 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10432 nested = nested->nested_in;
10439 can = can_access_type (access_class, member_class);
10441 MonoClass *nested = access_class->nested_in;
10443 can = can_access_type (nested, member_class);
10446 nested = nested->nested_in;
10453 if (called->is_inflated) {
10454 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10455 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10464 * mono_method_can_access_field_full:
10465 * @method: The caller method
10466 * @field: The accessed field
10467 * @context_klass: The static type on stack of the owner @field object used
10469 * This function must be used with instance fields, as they have more strict family accessibility.
10470 * It can be used with static fields, but context_klass should be NULL.
10472 * Returns: TRUE if caller have proper visibility and acessibility to @field
10475 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10477 MonoClass *access_class = method->klass;
10478 MonoClass *member_class = field->parent;
10479 /* FIXME: check all overlapping fields */
10480 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10482 MonoClass *nested = access_class->nested_in;
10484 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10487 nested = nested->nested_in;
10494 can = can_access_type (access_class, member_class);
10496 MonoClass *nested = access_class->nested_in;
10498 can = can_access_type (nested, member_class);
10501 nested = nested->nested_in;
10511 * mono_class_can_access_class:
10512 * @source_class: The source class
10513 * @target_class: The accessed class
10515 * This function returns is @target_class is visible to @source_class
10517 * Returns: TRUE if source have proper visibility and acessibility to target
10520 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10522 return can_access_type (source_class, target_class);
10526 * mono_type_is_valid_enum_basetype:
10527 * @type: The MonoType to check
10529 * Returns: TRUE if the type can be used as the basetype of an enum
10531 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10532 switch (type->type) {
10535 case MONO_TYPE_BOOLEAN:
10538 case MONO_TYPE_CHAR:
10552 * mono_class_is_valid_enum:
10553 * @klass: An enum class to be validated
10555 * This method verify the required properties an enum should have.
10557 * Returns: TRUE if the informed enum class is valid
10559 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10560 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10561 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10563 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10564 MonoClassField * field;
10565 gpointer iter = NULL;
10566 gboolean found_base_field = FALSE;
10568 g_assert (klass->enumtype);
10569 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10570 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10574 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10577 while ((field = mono_class_get_fields (klass, &iter))) {
10578 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10579 if (found_base_field)
10581 found_base_field = TRUE;
10582 if (!mono_type_is_valid_enum_basetype (field->type))
10587 if (!found_base_field)
10590 if (klass->method.count > 0)
10597 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10599 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10603 * mono_class_setup_interface_id:
10605 * Initializes MonoClass::interface_id if required.
10607 * LOCKING: Acquires the loader lock.
10610 mono_class_setup_interface_id (MonoClass *klass)
10612 mono_loader_lock ();
10613 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10614 klass->interface_id = mono_get_unique_iid (klass);
10615 mono_loader_unlock ();
10619 * mono_class_alloc_ext:
10621 * Allocate klass->ext if not already done.
10624 mono_class_alloc_ext (MonoClass *klass)
10631 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10632 mono_image_lock (klass->image);
10633 mono_memory_barrier ();
10636 class_ext_size += sizeof (MonoClassExt);
10637 mono_image_unlock (klass->image);
10641 * mono_class_setup_interfaces:
10643 * Initialize klass->interfaces/interfaces_count.
10644 * LOCKING: Acquires the loader lock.
10645 * This function can fail the type.
10648 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10650 int i, interface_count;
10651 MonoClass **interfaces;
10653 mono_error_init (error);
10655 if (klass->interfaces_inited)
10658 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10659 MonoType *args [1];
10661 /* generic IList, ICollection, IEnumerable */
10662 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10663 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10665 args [0] = &klass->element_class->byval_arg;
10666 interfaces [0] = mono_class_bind_generic_parameters (
10667 mono_defaults.generic_ilist_class, 1, args, FALSE);
10668 if (interface_count > 1)
10669 interfaces [1] = mono_class_bind_generic_parameters (
10670 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10671 } else if (klass->generic_class) {
10672 MonoClass *gklass = klass->generic_class->container_class;
10674 mono_class_setup_interfaces (gklass, error);
10675 if (!mono_error_ok (error)) {
10676 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10680 interface_count = gklass->interface_count;
10681 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10682 for (i = 0; i < interface_count; i++) {
10683 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10684 if (!mono_error_ok (error)) {
10685 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10690 interface_count = 0;
10694 mono_image_lock (klass->image);
10696 if (!klass->interfaces_inited) {
10697 klass->interface_count = interface_count;
10698 klass->interfaces = interfaces;
10700 mono_memory_barrier ();
10702 klass->interfaces_inited = TRUE;
10705 mono_image_unlock (klass->image);
10709 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10711 MonoClass *klass = field->parent;
10712 MonoImage *image = klass->image;
10713 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10714 int field_idx = field - klass->fields;
10716 mono_error_init (error);
10719 MonoClassField *gfield = >d->fields [field_idx];
10720 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10721 if (!mono_error_ok (error)) {
10722 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10723 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10726 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10727 if (!mono_error_ok (error)) {
10728 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10729 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10733 guint32 cols [MONO_FIELD_SIZE];
10734 MonoGenericContainer *container = NULL;
10735 int idx = klass->field.first + field_idx;
10737 /*FIXME, in theory we do not lazy load SRE fields*/
10738 g_assert (!image_is_dynamic (image));
10740 if (klass->generic_container) {
10741 container = klass->generic_container;
10743 container = gtd->generic_container;
10744 g_assert (container);
10747 /* klass->field.first and idx points into the fieldptr table */
10748 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10750 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10751 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10752 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10756 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10758 mono_metadata_decode_value (sig, &sig);
10759 /* FIELD signature == 0x06 */
10760 g_assert (*sig == 0x06);
10762 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10763 if (!field->type) {
10764 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10765 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10771 mono_field_resolve_flags (MonoClassField *field)
10773 MonoClass *klass = field->parent;
10774 MonoImage *image = klass->image;
10775 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10776 int field_idx = field - klass->fields;
10780 MonoClassField *gfield = >d->fields [field_idx];
10781 return mono_field_get_flags (gfield);
10783 int idx = klass->field.first + field_idx;
10785 /*FIXME, in theory we do not lazy load SRE fields*/
10786 g_assert (!image_is_dynamic (image));
10788 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10793 * mono_class_setup_basic_field_info:
10794 * @class: The class to initialize
10796 * Initializes the klass->fields array of fields.
10797 * Aquires the loader lock.
10800 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10802 mono_loader_lock ();
10803 mono_class_setup_basic_field_info (klass);
10804 mono_loader_unlock ();
10808 * mono_class_get_fields_lazy:
10809 * @klass: the MonoClass to act on
10811 * This routine is an iterator routine for retrieving the fields in a class.
10812 * Only minimal information about fields are loaded. Accessors must be used
10813 * for all MonoClassField returned.
10815 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10816 * iterate over all of the elements. When no more values are
10817 * available, the return value is NULL.
10819 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10822 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10824 MonoClassField* field;
10828 mono_class_setup_basic_field_info_locking (klass);
10829 if (!klass->fields)
10831 /* start from the first */
10832 if (klass->field.count) {
10833 *iter = &klass->fields [0];
10834 return (MonoClassField *)*iter;
10840 field = (MonoClassField *)*iter;
10842 if (field < &klass->fields [klass->field.count]) {
10844 return (MonoClassField *)*iter;
10850 mono_class_full_name (MonoClass *klass)
10852 return mono_type_full_name (&klass->byval_arg);
10855 /* Declare all shared lazy type lookup functions */
10856 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)