2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include <mono/metadata/image.h>
21 #include <mono/metadata/image-internals.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/assembly-internals.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/profiler-private.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/metadata/security-core-clr.h>
38 #include <mono/metadata/attrdefs.h>
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/verify-internals.h>
41 #include <mono/metadata/mono-debug.h>
42 #include <mono/utils/mono-counters.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45 #include <mono/utils/mono-logger-internals.h>
46 #include <mono/utils/mono-memory-model.h>
47 #include <mono/utils/atomic.h>
48 #include <mono/utils/bsearch.h>
49 #include <mono/utils/checked-build.h>
53 gboolean mono_print_vtable = FALSE;
54 gboolean mono_align_small_structs = FALSE;
57 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
58 guint32 classes_size, class_ext_size;
60 /* Low level lock which protects data structures in this module */
61 static mono_mutex_t classes_mutex;
63 /* Function supplied by the runtime to find classes by name using information from the AOT file */
64 static MonoGetClassFromName get_class_from_name = NULL;
66 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
67 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
68 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
69 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
70 static int generic_array_methods (MonoClass *klass);
71 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
73 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
74 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
75 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
76 static guint32 mono_field_resolve_flags (MonoClassField *field);
77 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
78 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
81 We use gclass recording to allow recursive system f types to be referenced by a parent.
83 Given the following type hierarchy:
85 class TextBox : TextBoxBase<TextBox> {}
86 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
87 class TextInput<T> : Input<T> where T: TextInput<T> {}
90 The runtime tries to load TextBoxBase<>.
91 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
92 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
93 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
95 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
96 at this point, iow, both are registered in the type map and both and a NULL parent. This means
97 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
99 To fix that what we do is to record all generic instantes created while resolving the parent of
100 any generic type definition and, after resolved, correct the parent field if needed.
103 static int record_gclass_instantiation;
104 static GSList *gclass_recorded_list;
105 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
110 mono_locks_os_acquire (&classes_mutex, ClassesLock);
114 classes_unlock (void)
116 mono_locks_os_release (&classes_mutex, ClassesLock);
120 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
123 enable_gclass_recording (void)
125 ++record_gclass_instantiation;
129 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
132 disable_gclass_recording (gclass_record_func func, void *user_data)
134 GSList **head = &gclass_recorded_list;
136 g_assert (record_gclass_instantiation > 0);
137 --record_gclass_instantiation;
140 GSList *node = *head;
141 if (func ((MonoClass*)node->data, user_data)) {
143 g_slist_free_1 (node);
149 /* We automatically discard all recorded gclasses when disabled. */
150 if (!record_gclass_instantiation && gclass_recorded_list) {
151 g_slist_free (gclass_recorded_list);
152 gclass_recorded_list = NULL;
157 * mono_class_from_typeref:
158 * @image: a MonoImage
159 * @type_token: a TypeRef token
161 * Creates the MonoClass* structure representing the type defined by
162 * the typeref token valid inside @image.
163 * Returns: The MonoClass* representing the typeref token, NULL ifcould
167 mono_class_from_typeref (MonoImage *image, guint32 type_token)
170 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
171 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
176 * mono_class_from_typeref_checked:
177 * @image: a MonoImage
178 * @type_token: a TypeRef token
179 * @error: error return code, if any.
181 * Creates the MonoClass* structure representing the type defined by
182 * the typeref token valid inside @image.
184 * Returns: The MonoClass* representing the typeref token, NULL if it could
185 * not be loaded with the @error value filled with the information about the
189 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
191 guint32 cols [MONO_TYPEREF_SIZE];
192 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
194 const char *name, *nspace;
195 MonoClass *res = NULL;
198 mono_error_init (error);
200 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
203 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
205 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
206 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
208 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
209 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
210 case MONO_RESOLUTION_SCOPE_MODULE:
212 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
213 This is not the observed behavior of existing implementations.
214 The defacto behavior is that it's just a typedef in disguise.
216 /* a typedef in disguise */
217 res = mono_class_from_name_checked (image, nspace, name, error);
220 case MONO_RESOLUTION_SCOPE_MODULEREF:
221 module = mono_image_load_module_checked (image, idx, error);
223 res = mono_class_from_name_checked (module, nspace, name, error);
226 case MONO_RESOLUTION_SCOPE_TYPEREF: {
227 MonoClass *enclosing;
230 if (idx == mono_metadata_token_index (type_token)) {
231 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
235 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
236 return_val_if_nok (error, NULL);
238 if (enclosing->nested_classes_inited && enclosing->ext) {
239 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
240 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
241 res = (MonoClass *)tmp->data;
242 if (strcmp (res->name, name) == 0)
246 /* Don't call mono_class_init as we might've been called by it recursively */
247 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
249 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
250 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
251 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
253 if (strcmp (nname, name) == 0)
254 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
256 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
259 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
262 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
266 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
267 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
271 if (!image->references || !image->references [idx - 1])
272 mono_assembly_load_reference (image, idx - 1);
273 g_assert (image->references [idx - 1]);
275 /* If the assembly did not load, register this as a type load exception */
276 if (image->references [idx - 1] == REFERENCE_MISSING){
277 MonoAssemblyName aname;
280 mono_assembly_get_assemblyref (image, idx - 1, &aname);
281 human_name = mono_stringify_assembly_name (&aname);
282 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
286 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
289 /* Generic case, should be avoided for when a better error is possible. */
290 if (!res && mono_error_ok (error)) {
291 char *name = mono_class_name_from_token (image, type_token);
292 char *assembly = mono_assembly_name_from_token (image, type_token);
293 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
300 mono_image_memdup (MonoImage *image, void *data, guint size)
302 void *res = mono_image_alloc (image, size);
303 memcpy (res, data, size);
307 /* Copy everything mono_metadata_free_array free. */
309 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
312 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
314 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
316 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
318 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
320 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
322 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
327 /* Copy everything mono_metadata_free_method_signature free. */
329 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
333 sig = mono_metadata_signature_dup_full (image, sig);
335 sig->ret = mono_metadata_type_dup (image, sig->ret);
336 for (i = 0; i < sig->param_count; ++i)
337 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
343 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
345 MonoAssembly *ta = klass->image->assembly;
348 name = mono_stringify_assembly_name (&ta->aname);
349 g_string_append_printf (str, ", %s", name);
354 mono_type_name_check_byref (MonoType *type, GString *str)
357 g_string_append_c (str, '&');
361 * mono_identifier_escape_type_name_chars:
362 * @str: a destination string
363 * @identifier: an IDENTIFIER in internal form
367 * The displayed form of the identifier is appended to str.
369 * The displayed form of an identifier has the characters ,+&*[]\
370 * that have special meaning in type names escaped with a preceeding
371 * backslash (\) character.
374 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
380 // reserve space for common case: there will be no escaped characters.
381 g_string_set_size(str, n + strlen(identifier));
382 g_string_set_size(str, n);
384 for (const char* s = identifier; *s != 0 ; s++) {
393 g_string_append_c (str, '\\');
394 g_string_append_c (str, *s);
397 g_string_append_c (str, *s);
405 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
406 MonoTypeNameFormat format)
410 switch (type->type) {
411 case MONO_TYPE_ARRAY: {
412 int i, rank = type->data.array->rank;
413 MonoTypeNameFormat nested_format;
415 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
416 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
418 mono_type_get_name_recurse (
419 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
420 g_string_append_c (str, '[');
422 g_string_append_c (str, '*');
423 for (i = 1; i < rank; i++)
424 g_string_append_c (str, ',');
425 g_string_append_c (str, ']');
427 mono_type_name_check_byref (type, str);
429 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
430 _mono_type_get_assembly_name (type->data.array->eklass, str);
433 case MONO_TYPE_SZARRAY: {
434 MonoTypeNameFormat nested_format;
436 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
437 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
439 mono_type_get_name_recurse (
440 &type->data.klass->byval_arg, str, FALSE, nested_format);
441 g_string_append (str, "[]");
443 mono_type_name_check_byref (type, str);
445 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
446 _mono_type_get_assembly_name (type->data.klass, str);
449 case MONO_TYPE_PTR: {
450 MonoTypeNameFormat nested_format;
452 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
453 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
455 mono_type_get_name_recurse (
456 type->data.type, str, FALSE, nested_format);
457 g_string_append_c (str, '*');
459 mono_type_name_check_byref (type, str);
461 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
462 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
467 if (!mono_generic_param_info (type->data.generic_param))
468 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
470 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
472 mono_type_name_check_byref (type, str);
476 klass = mono_class_from_mono_type (type);
477 if (klass->nested_in) {
478 mono_type_get_name_recurse (
479 &klass->nested_in->byval_arg, str, TRUE, format);
480 if (format == MONO_TYPE_NAME_FORMAT_IL)
481 g_string_append_c (str, '.');
483 g_string_append_c (str, '+');
484 } else if (*klass->name_space) {
485 if (format == MONO_TYPE_NAME_FORMAT_IL)
486 g_string_append (str, klass->name_space);
488 mono_identifier_escape_type_name_chars (str, klass->name_space);
489 g_string_append_c (str, '.');
491 if (format == MONO_TYPE_NAME_FORMAT_IL) {
492 char *s = strchr (klass->name, '`');
493 int len = s ? s - klass->name : strlen (klass->name);
494 g_string_append_len (str, klass->name, len);
496 mono_identifier_escape_type_name_chars (str, klass->name);
500 if (klass->generic_class) {
501 MonoGenericClass *gclass = klass->generic_class;
502 MonoGenericInst *inst = gclass->context.class_inst;
503 MonoTypeNameFormat nested_format;
506 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
507 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
509 if (format == MONO_TYPE_NAME_FORMAT_IL)
510 g_string_append_c (str, '<');
512 g_string_append_c (str, '[');
513 for (i = 0; i < inst->type_argc; i++) {
514 MonoType *t = inst->type_argv [i];
517 g_string_append_c (str, ',');
518 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
519 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
520 g_string_append_c (str, '[');
521 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
522 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
523 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
524 g_string_append_c (str, ']');
526 if (format == MONO_TYPE_NAME_FORMAT_IL)
527 g_string_append_c (str, '>');
529 g_string_append_c (str, ']');
530 } else if (klass->generic_container &&
531 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
532 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
535 if (format == MONO_TYPE_NAME_FORMAT_IL)
536 g_string_append_c (str, '<');
538 g_string_append_c (str, '[');
539 for (i = 0; i < klass->generic_container->type_argc; i++) {
541 g_string_append_c (str, ',');
542 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
544 if (format == MONO_TYPE_NAME_FORMAT_IL)
545 g_string_append_c (str, '>');
547 g_string_append_c (str, ']');
550 mono_type_name_check_byref (type, str);
552 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
553 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
554 _mono_type_get_assembly_name (klass, str);
560 * mono_type_get_name_full:
562 * @format: the format for the return string.
565 * Returns: The string representation in a number of formats:
567 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
568 * returned in the formatrequired by System.Reflection, this is the
569 * inverse of mono_reflection_parse_type ().
571 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
572 * be used by the IL assembler.
574 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
576 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
579 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
583 result = g_string_new ("");
585 mono_type_get_name_recurse (type, result, FALSE, format);
587 return g_string_free (result, FALSE);
591 * mono_type_get_full_name:
594 * Returns: The string representation for type as required by System.Reflection.
595 * The inverse of mono_reflection_parse_type ().
598 mono_type_get_full_name (MonoClass *klass)
600 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
604 * mono_type_get_name:
607 * Returns: The string representation for type as it would be represented in IL code.
610 mono_type_get_name (MonoType *type)
612 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
616 * mono_type_get_underlying_type:
619 * Returns: The MonoType for the underlying integer type if @type
620 * is an enum and byref is false, otherwise the type itself.
623 mono_type_get_underlying_type (MonoType *type)
625 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
626 return mono_class_enum_basetype (type->data.klass);
627 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
628 return mono_class_enum_basetype (type->data.generic_class->container_class);
633 * mono_class_is_open_constructed_type:
636 * Returns: TRUE if type represents a generics open constructed type.
637 * IOW, not all type parameters required for the instantiation have
638 * been provided or it's a generic type definition.
640 * An open constructed type means it's a non realizable type. Not to
641 * be mixed up with an abstract type - we can't cast or dispatch to
642 * an open type, for example.
645 mono_class_is_open_constructed_type (MonoType *t)
651 case MONO_TYPE_SZARRAY:
652 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
653 case MONO_TYPE_ARRAY:
654 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
656 return mono_class_is_open_constructed_type (t->data.type);
657 case MONO_TYPE_GENERICINST:
658 return t->data.generic_class->context.class_inst->is_open;
659 case MONO_TYPE_CLASS:
660 case MONO_TYPE_VALUETYPE:
661 return t->data.klass->generic_container != NULL;
668 This is a simple function to catch the most common bad instances of generic types.
669 Specially those that might lead to further failures in the runtime.
672 is_valid_generic_argument (MonoType *type)
674 switch (type->type) {
676 //case MONO_TYPE_TYPEDBYREF:
684 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
686 mono_error_init (error);
688 switch (type->type) {
689 case MONO_TYPE_MVAR: {
691 int num = mono_type_get_generic_param_num (type);
692 MonoGenericInst *inst = context->method_inst;
695 if (num >= inst->type_argc) {
696 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
697 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
698 num, info ? info->name : "", inst->type_argc);
702 if (!is_valid_generic_argument (inst->type_argv [num])) {
703 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
704 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
705 num, info ? info->name : "", inst->type_argv [num]->type);
709 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
710 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
711 * ->byref and ->attrs from @type are propagated to the returned type.
713 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
714 nt->byref = type->byref;
715 nt->attrs = type->attrs;
718 case MONO_TYPE_VAR: {
720 int num = mono_type_get_generic_param_num (type);
721 MonoGenericInst *inst = context->class_inst;
724 if (num >= inst->type_argc) {
725 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
726 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
727 num, info ? info->name : "", inst->type_argc);
730 if (!is_valid_generic_argument (inst->type_argv [num])) {
731 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
732 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
733 num, info ? info->name : "", inst->type_argv [num]->type);
736 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
737 nt->byref = type->byref;
738 nt->attrs = type->attrs;
741 case MONO_TYPE_SZARRAY: {
742 MonoClass *eclass = type->data.klass;
743 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
744 if (!inflated || !mono_error_ok (error))
746 nt = mono_metadata_type_dup (image, type);
747 nt->data.klass = mono_class_from_mono_type (inflated);
748 mono_metadata_free_type (inflated);
751 case MONO_TYPE_ARRAY: {
752 MonoClass *eclass = type->data.array->eklass;
753 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
754 if (!inflated || !mono_error_ok (error))
756 nt = mono_metadata_type_dup (image, type);
757 nt->data.array->eklass = mono_class_from_mono_type (inflated);
758 mono_metadata_free_type (inflated);
761 case MONO_TYPE_GENERICINST: {
762 MonoGenericClass *gclass = type->data.generic_class;
763 MonoGenericInst *inst;
765 if (!gclass->context.class_inst->is_open)
768 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
769 return_val_if_nok (error, NULL);
771 if (inst != gclass->context.class_inst)
772 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
774 if (gclass == type->data.generic_class)
777 nt = mono_metadata_type_dup (image, type);
778 nt->data.generic_class = gclass;
781 case MONO_TYPE_CLASS:
782 case MONO_TYPE_VALUETYPE: {
783 MonoClass *klass = type->data.klass;
784 MonoGenericContainer *container = klass->generic_container;
785 MonoGenericInst *inst;
786 MonoGenericClass *gclass = NULL;
792 /* We can't use context->class_inst directly, since it can have more elements */
793 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
794 return_val_if_nok (error, NULL);
796 if (inst == container->context.class_inst)
799 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
801 nt = mono_metadata_type_dup (image, type);
802 nt->type = MONO_TYPE_GENERICINST;
803 nt->data.generic_class = gclass;
813 mono_generic_class_get_context (MonoGenericClass *gclass)
815 return &gclass->context;
819 mono_class_get_context (MonoClass *klass)
821 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
825 * mono_class_get_generic_container:
827 * Return the generic container of KLASS which should be a generic type definition.
829 MonoGenericContainer*
830 mono_class_get_generic_container (MonoClass *klass)
832 g_assert (klass->is_generic);
834 return klass->generic_container;
838 * mono_class_get_generic_class:
840 * Return the MonoGenericClass of KLASS, which should be a generic instance.
843 mono_class_get_generic_class (MonoClass *klass)
845 g_assert (klass->is_inflated);
847 return klass->generic_class;
851 * mono_class_inflate_generic_type_with_mempool:
852 * @mempool: a mempool
854 * @context: a generics context
855 * @error: error context
857 * The same as mono_class_inflate_generic_type, but allocates the MonoType
858 * from mempool if it is non-NULL. If it is NULL, the MonoType is
859 * allocated on the heap and is owned by the caller.
860 * The returned type can potentially be the same as TYPE, so it should not be
861 * modified by the caller, and it should be freed using mono_metadata_free_type ().
864 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
866 MonoType *inflated = NULL;
867 mono_error_init (error);
870 inflated = inflate_generic_type (image, type, context, error);
871 return_val_if_nok (error, NULL);
874 MonoType *shared = mono_metadata_get_shared_type (type);
879 return mono_metadata_type_dup (image, type);
883 mono_stats.inflated_type_count++;
888 * mono_class_inflate_generic_type:
890 * @context: a generics context
892 * If @type is a generic type and @context is not NULL, instantiate it using the
893 * generics context @context.
895 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
896 * on the heap and is owned by the caller. Returns NULL on error.
898 * @deprecated Please use mono_class_inflate_generic_type_checked instead
901 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
905 result = mono_class_inflate_generic_type_checked (type, context, &error);
906 mono_error_cleanup (&error);
911 * mono_class_inflate_generic_type:
913 * @context: a generics context
914 * @error: error context to use
916 * If @type is a generic type and @context is not NULL, instantiate it using the
917 * generics context @context.
919 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
920 * on the heap and is owned by the caller.
923 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
925 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
929 * mono_class_inflate_generic_type_no_copy:
931 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
935 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
937 MonoType *inflated = NULL;
939 mono_error_init (error);
941 inflated = inflate_generic_type (image, type, context, error);
942 return_val_if_nok (error, NULL);
948 mono_stats.inflated_type_count++;
953 * mono_class_inflate_generic_class:
955 * Inflate the class @gklass with @context. Set @error on failure.
958 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
963 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
964 return_val_if_nok (error, NULL);
966 res = mono_class_from_mono_type (inflated);
967 mono_metadata_free_type (inflated);
972 static MonoGenericContext
973 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
975 MonoGenericInst *class_inst = NULL;
976 MonoGenericInst *method_inst = NULL;
977 MonoGenericContext res = { NULL, NULL };
979 mono_error_init (error);
981 if (context->class_inst) {
982 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
983 if (!mono_error_ok (error))
987 if (context->method_inst) {
988 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
989 if (!mono_error_ok (error))
993 res.class_inst = class_inst;
994 res.method_inst = method_inst;
1000 * mono_class_inflate_generic_method:
1001 * @method: a generic method
1002 * @context: a generics context
1004 * Instantiate the generic method @method using the generics context @context.
1006 * Returns: The new instantiated method
1009 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1011 return mono_class_inflate_generic_method_full (method, NULL, context);
1015 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1017 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1021 * mono_class_inflate_generic_method_full:
1023 * Instantiate method @method with the generic context @context.
1024 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1025 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1028 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1031 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1032 if (!mono_error_ok (&error))
1033 /*FIXME do proper error handling - on this case, kill this function. */
1034 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1040 * mono_class_inflate_generic_method_full_checked:
1041 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1044 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1047 MonoMethodInflated *iresult, *cached;
1048 MonoMethodSignature *sig;
1049 MonoGenericContext tmp_context;
1051 mono_error_init (error);
1053 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1054 while (method->is_inflated) {
1055 MonoGenericContext *method_context = mono_method_get_context (method);
1056 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1058 tmp_context = inflate_generic_context (method_context, context, error);
1059 return_val_if_nok (error, NULL);
1061 context = &tmp_context;
1063 if (mono_metadata_generic_context_equal (method_context, context))
1066 method = imethod->declaring;
1070 * A method only needs to be inflated if the context has argument for which it is
1073 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1074 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1077 if (!((method->is_generic && context->method_inst) ||
1078 (method->klass->generic_container && context->class_inst)))
1081 iresult = g_new0 (MonoMethodInflated, 1);
1082 iresult->context = *context;
1083 iresult->declaring = method;
1085 if (!context->method_inst && method->is_generic)
1086 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1088 if (!context->class_inst) {
1089 g_assert (!iresult->declaring->klass->generic_class);
1090 if (iresult->declaring->klass->generic_container)
1091 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1092 else if (iresult->declaring->klass->generic_class)
1093 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1095 /* This can happen with some callers like mono_object_get_virtual_method () */
1096 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1097 iresult->context.class_inst = NULL;
1099 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1102 mono_image_set_lock (set);
1103 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1104 mono_image_set_unlock (set);
1108 return (MonoMethod*)cached;
1111 mono_stats.inflated_method_count++;
1113 inflated_methods_size += sizeof (MonoMethodInflated);
1115 sig = mono_method_signature (method);
1117 char *name = mono_type_get_full_name (method->klass);
1118 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1124 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1126 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1129 result = (MonoMethod *) iresult;
1130 result->is_inflated = TRUE;
1131 result->is_generic = FALSE;
1132 result->sre_method = FALSE;
1133 result->signature = NULL;
1135 if (method->wrapper_type) {
1136 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1137 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1138 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1140 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1141 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1144 if (iresult->context.method_inst) {
1145 /* Set the generic_container of the result to the generic_container of method */
1146 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1148 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1149 result->is_generic = 1;
1150 mono_method_set_generic_container (result, generic_container);
1154 if (!klass_hint || !klass_hint->generic_class ||
1155 klass_hint->generic_class->container_class != method->klass ||
1156 klass_hint->generic_class->context.class_inst != context->class_inst)
1159 if (method->klass->generic_container)
1160 result->klass = klass_hint;
1162 if (!result->klass) {
1163 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1164 if (!mono_error_ok (error))
1167 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1169 mono_metadata_free_type (inflated);
1173 * FIXME: This should hold, but it doesn't:
1175 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1176 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1177 * g_assert (result->is_generic);
1180 * Fixing this here causes other things to break, hence a very
1181 * ugly hack in mini-trampolines.c - see
1182 * is_generic_method_definition().
1186 mono_image_set_lock (set);
1187 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1189 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1190 iresult->owner = set;
1193 mono_image_set_unlock (set);
1195 return (MonoMethod*)cached;
1203 * mono_get_inflated_method:
1205 * Obsolete. We keep it around since it's mentioned in the public API.
1208 mono_get_inflated_method (MonoMethod *method)
1214 * mono_method_get_context_general:
1216 * @uninflated: handle uninflated methods?
1218 * Returns the generic context of a method or NULL if it doesn't have
1219 * one. For an inflated method that's the context stored in the
1220 * method. Otherwise it's in the method's generic container or in the
1221 * generic container of the method's class.
1224 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1226 if (method->is_inflated) {
1227 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1228 return &imethod->context;
1232 if (method->is_generic)
1233 return &(mono_method_get_generic_container (method)->context);
1234 if (method->klass->generic_container)
1235 return &method->klass->generic_container->context;
1240 * mono_method_get_context:
1243 * Returns the generic context for method if it's inflated, otherwise
1247 mono_method_get_context (MonoMethod *method)
1249 return mono_method_get_context_general (method, FALSE);
1253 * mono_method_get_generic_container:
1255 * Returns the generic container of METHOD, which should be a generic method definition.
1256 * Returns NULL if METHOD is not a generic method definition.
1257 * LOCKING: Acquires the loader lock.
1259 MonoGenericContainer*
1260 mono_method_get_generic_container (MonoMethod *method)
1262 MonoGenericContainer *container;
1264 if (!method->is_generic)
1267 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1268 g_assert (container);
1274 * mono_method_set_generic_container:
1276 * Sets the generic container of METHOD to CONTAINER.
1277 * LOCKING: Acquires the image lock.
1280 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1282 g_assert (method->is_generic);
1284 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1288 * mono_class_find_enum_basetype:
1289 * @class: The enum class
1291 * Determine the basetype of an enum by iterating through its fields. We do this
1292 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1295 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1297 MonoGenericContainer *container = NULL;
1298 MonoImage *m = klass->image;
1299 const int top = klass->field.count;
1302 g_assert (klass->enumtype);
1304 mono_error_init (error);
1306 if (klass->generic_container)
1307 container = klass->generic_container;
1308 else if (klass->generic_class) {
1309 MonoClass *gklass = klass->generic_class->container_class;
1311 container = gklass->generic_container;
1312 g_assert (container);
1316 * Fetch all the field information.
1318 for (i = 0; i < top; i++){
1320 guint32 cols [MONO_FIELD_SIZE];
1321 int idx = klass->field.first + i;
1324 /* klass->field.first and idx points into the fieldptr table */
1325 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1327 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1330 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1331 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1335 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1336 mono_metadata_decode_value (sig, &sig);
1337 /* FIELD signature == 0x06 */
1339 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1343 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1347 if (klass->generic_class) {
1348 //FIXME do we leak here?
1349 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1350 if (!mono_error_ok (error))
1352 ftype->attrs = cols [MONO_FIELD_FLAGS];
1357 mono_error_set_type_load_class (error, klass, "Could not find base type");
1364 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1367 mono_type_has_exceptions (MonoType *type)
1369 switch (type->type) {
1370 case MONO_TYPE_CLASS:
1371 case MONO_TYPE_VALUETYPE:
1372 case MONO_TYPE_SZARRAY:
1373 return mono_class_has_failure (type->data.klass);
1374 case MONO_TYPE_ARRAY:
1375 return mono_class_has_failure (type->data.array->eklass);
1376 case MONO_TYPE_GENERICINST:
1377 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1384 mono_error_set_for_class_failure (MonoError *oerror, MonoClass *klass)
1386 gpointer exception_data = mono_class_get_exception_data (klass);
1388 switch (mono_class_get_failure(klass)) {
1389 case MONO_EXCEPTION_TYPE_LOAD: {
1390 mono_error_set_type_load_class (oerror, klass, "Error Loading class");
1393 case MONO_EXCEPTION_INVALID_PROGRAM: {
1394 mono_error_set_invalid_program (oerror, (const char *)exception_data);
1397 case MONO_EXCEPTION_MISSING_METHOD:
1398 case MONO_EXCEPTION_MISSING_FIELD:
1399 case MONO_EXCEPTION_FILE_NOT_FOUND:
1400 case MONO_EXCEPTION_BAD_IMAGE:
1402 g_assert_not_reached ();
1410 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1414 mono_class_alloc (MonoClass *klass, int size)
1416 if (klass->generic_class)
1417 return mono_image_set_alloc (klass->generic_class->owner, size);
1419 return mono_image_alloc (klass->image, size);
1423 mono_class_alloc0 (MonoClass *klass, int size)
1427 res = mono_class_alloc (klass, size);
1428 memset (res, 0, size);
1432 #define mono_class_new0(klass,struct_type, n_structs) \
1433 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1436 * mono_class_setup_basic_field_info:
1437 * @class: The class to initialize
1439 * Initializes the klass->fields.
1440 * LOCKING: Assumes the loader lock is held.
1443 mono_class_setup_basic_field_info (MonoClass *klass)
1445 MonoClassField *field;
1453 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1454 image = klass->image;
1455 top = klass->field.count;
1457 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1459 * This happens when a generic instance of an unfinished generic typebuilder
1460 * is used as an element type for creating an array type. We can't initialize
1461 * the fields of this class using the fields of gklass, since gklass is not
1462 * finished yet, fields could be added to it later.
1468 mono_class_setup_basic_field_info (gtd);
1470 top = gtd->field.count;
1471 klass->field.first = gtd->field.first;
1472 klass->field.count = gtd->field.count;
1475 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1478 * Fetch all the field information.
1480 for (i = 0; i < top; i++){
1481 field = &klass->fields [i];
1482 field->parent = klass;
1485 field->name = mono_field_get_name (>d->fields [i]);
1487 int idx = klass->field.first + i;
1488 /* klass->field.first and idx points into the fieldptr table */
1489 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1490 /* The name is needed for fieldrefs */
1491 field->name = mono_metadata_string_heap (image, name_idx);
1497 * mono_class_setup_fields:
1498 * @class: The class to initialize
1500 * Initializes the klass->fields.
1501 * LOCKING: Assumes the loader lock is held.
1504 mono_class_setup_fields (MonoClass *klass)
1507 MonoImage *m = klass->image;
1509 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1510 int i, blittable = TRUE;
1511 guint32 real_size = 0;
1512 guint32 packing_size = 0;
1514 gboolean explicit_size;
1515 MonoClassField *field;
1516 MonoGenericContainer *container = NULL;
1517 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1520 * FIXME: We have a race condition here. It's possible that this function returns
1521 * to its caller with `instance_size` set to `0` instead of the actual size. This
1522 * is not a problem when the function is called recursively on the same class,
1523 * because the size will be initialized by the outer invocation. What follows is a
1524 * description of how it can occur in other cases, too. There it is a problem,
1525 * because it can lead to the GC being asked to allocate an object of size `0`,
1526 * which SGen chokes on. The race condition is triggered infrequently by
1527 * `tests/sgen-suspend.cs`.
1529 * This function is called for a class whenever one of its subclasses is inited.
1530 * For example, it's called for every subclass of Object. What it does is this:
1532 * if (klass->setup_fields_called)
1535 * klass->instance_size = 0;
1537 * klass->setup_fields_called = 1;
1538 * ... critical point
1539 * klass->instance_size = actual_instance_size;
1541 * The last two steps are sometimes reversed, but that only changes the way in which
1542 * the race condition works.
1544 * Assume thread A goes through this function and makes it to the critical point.
1545 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1546 * immediately, but `instance_size` is incorrect.
1548 * The other case looks like this:
1550 * if (klass->setup_fields_called)
1552 * ... critical point X
1553 * klass->instance_size = 0;
1554 * ... critical point Y
1555 * klass->instance_size = actual_instance_size;
1557 * klass->setup_fields_called = 1;
1559 * Assume thread A goes through the function and makes it to critical point X. Now
1560 * thread B runs through the whole of the function, returning, assuming
1561 * `instance_size` is set. At that point thread A gets to run and makes it to
1562 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1565 if (klass->setup_fields_called)
1568 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1570 * This happens when a generic instance of an unfinished generic typebuilder
1571 * is used as an element type for creating an array type. We can't initialize
1572 * the fields of this class using the fields of gklass, since gklass is not
1573 * finished yet, fields could be added to it later.
1578 mono_class_setup_basic_field_info (klass);
1579 top = klass->field.count;
1582 mono_class_setup_fields (gtd);
1583 if (mono_class_has_failure (gtd)) {
1584 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1591 klass->sizes.class_size = 0;
1593 if (klass->parent) {
1594 /* For generic instances, klass->parent might not have been initialized */
1595 mono_class_init (klass->parent);
1596 if (!klass->parent->size_inited) {
1597 mono_class_setup_fields (klass->parent);
1598 if (mono_class_has_failure (klass->parent)) {
1599 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1603 instance_size += klass->parent->instance_size;
1604 klass->min_align = klass->parent->min_align;
1605 /* we use |= since it may have been set already */
1606 klass->has_references |= klass->parent->has_references;
1607 blittable = klass->parent->blittable;
1609 instance_size = sizeof (MonoObject);
1610 klass->min_align = 1;
1613 /* We can't really enable 16 bytes alignment until the GC supports it.
1614 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1615 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1616 Bug #506144 is an example of this issue.
1618 if (klass->simd_type)
1619 klass->min_align = 16;
1621 /* Get the real size */
1622 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1624 if (explicit_size) {
1625 if ((packing_size & 0xffffff00) != 0) {
1626 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1627 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1630 klass->packing_size = packing_size;
1631 real_size += instance_size;
1635 if (explicit_size && real_size) {
1636 instance_size = MAX (real_size, instance_size);
1638 klass->blittable = blittable;
1639 if (!klass->instance_size)
1640 klass->instance_size = instance_size;
1641 mono_memory_barrier ();
1642 klass->size_inited = 1;
1643 klass->fields_inited = 1;
1644 klass->setup_fields_called = 1;
1648 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1651 /* Prevent infinite loops if the class references itself */
1652 klass->setup_fields_called = 1;
1654 if (klass->generic_container) {
1655 container = klass->generic_container;
1657 container = gtd->generic_container;
1658 g_assert (container);
1662 * Fetch all the field information.
1664 for (i = 0; i < top; i++){
1665 int idx = klass->field.first + i;
1666 field = &klass->fields [i];
1668 field->parent = klass;
1671 mono_field_resolve_type (field, &error);
1672 if (!mono_error_ok (&error)) {
1673 /*mono_field_resolve_type already failed class*/
1674 mono_error_cleanup (&error);
1678 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1679 g_assert (field->type);
1682 if (mono_field_is_deleted (field))
1685 MonoClassField *gfield = >d->fields [i];
1686 field->offset = gfield->offset;
1688 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1690 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1691 field->offset = offset;
1693 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1694 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Missing field layout info for %s", field->name));
1697 if (field->offset < -1) { /*-1 is used to encode special static fields */
1698 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Invalid negative field offset %d for %s", field->offset, field->name));
1701 if (klass->generic_container) {
1702 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Generic class cannot have explicit layout."));
1708 /* Only do these checks if we still think this type is blittable */
1709 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1710 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1713 MonoClass *field_class = mono_class_from_mono_type (field->type);
1715 mono_class_setup_fields (field_class);
1716 if (mono_class_has_failure (field_class)) {
1717 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1721 if (!field_class || !field_class->blittable)
1726 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1727 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1728 blittable = klass->element_class->blittable;
1731 if (mono_type_has_exceptions (field->type)) {
1732 char *class_name = mono_type_get_full_name (klass);
1733 char *type_name = mono_type_full_name (field->type);
1735 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1736 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1737 g_free (class_name);
1741 /* The def_value of fields is compute lazily during vtable creation */
1744 if (klass == mono_defaults.string_class)
1747 klass->blittable = blittable;
1749 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1750 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1753 if (explicit_size && real_size) {
1754 instance_size = MAX (real_size, instance_size);
1757 if (mono_class_has_failure (klass))
1759 mono_class_layout_fields (klass, instance_size);
1761 /*valuetypes can't be neither bigger than 1Mb or empty. */
1762 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1763 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1765 mono_memory_barrier ();
1766 klass->fields_inited = 1;
1770 * mono_class_setup_fields_locking:
1771 * @class: The class to initialize
1773 * Initializes the klass->fields array of fields.
1774 * Aquires the loader lock.
1777 mono_class_setup_fields_locking (MonoClass *klass)
1779 /* This can be checked without locks */
1780 if (klass->fields_inited)
1782 mono_loader_lock ();
1783 mono_class_setup_fields (klass);
1784 mono_loader_unlock ();
1788 * mono_class_has_references:
1790 * Returns whenever @klass->has_references is set, initializing it if needed.
1791 * Aquires the loader lock.
1794 mono_class_has_references (MonoClass *klass)
1796 if (klass->init_pending) {
1797 /* Be conservative */
1800 mono_class_init (klass);
1802 return klass->has_references;
1807 * mono_type_get_basic_type_from_generic:
1810 * Returns a closed type corresponding to the possibly open type
1814 mono_type_get_basic_type_from_generic (MonoType *type)
1816 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1817 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1818 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1819 return &mono_defaults.object_class->byval_arg;
1824 type_has_references (MonoClass *klass, MonoType *ftype)
1826 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)))))
1828 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1829 MonoGenericParam *gparam = ftype->data.generic_param;
1831 if (gparam->gshared_constraint)
1832 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1838 * mono_class_layout_fields:
1840 * @instance_size: base instance size
1842 * Compute the placement of fields inside an object or struct, according to
1843 * the layout rules and set the following fields in @class:
1844 * - has_references (if the class contains instance references firled or structs that contain references)
1845 * - has_static_refs (same, but for static fields)
1846 * - instance_size (size of the object in memory)
1847 * - class_size (size needed for the static fields)
1848 * - size_inited (flag set when the instance_size is set)
1850 * LOCKING: this is supposed to be called with the loader lock held.
1853 mono_class_layout_fields (MonoClass *klass, int instance_size)
1856 const int top = klass->field.count;
1857 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1858 guint32 pass, passes, real_size;
1859 gboolean gc_aware_layout = FALSE;
1860 gboolean has_static_fields = FALSE;
1861 MonoClassField *field;
1864 * When we do generic sharing we need to have layout
1865 * information for open generic classes (either with a generic
1866 * context containing type variables or with a generic
1867 * container), so we don't return in that case anymore.
1871 * Enable GC aware auto layout: in this mode, reference
1872 * fields are grouped together inside objects, increasing collector
1874 * Requires that all classes whose layout is known to native code be annotated
1875 * with [StructLayout (LayoutKind.Sequential)]
1876 * Value types have gc_aware_layout disabled by default, as per
1877 * what the default is for other runtimes.
1879 /* corlib is missing [StructLayout] directives in many places */
1880 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1881 if (!klass->valuetype)
1882 gc_aware_layout = TRUE;
1885 /* Compute klass->has_references */
1887 * Process non-static fields first, since static fields might recursively
1888 * refer to the class itself.
1890 for (i = 0; i < top; i++) {
1893 field = &klass->fields [i];
1895 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1896 ftype = mono_type_get_underlying_type (field->type);
1897 ftype = mono_type_get_basic_type_from_generic (ftype);
1898 if (type_has_references (klass, ftype))
1899 klass->has_references = TRUE;
1903 for (i = 0; i < top; i++) {
1906 field = &klass->fields [i];
1908 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1909 ftype = mono_type_get_underlying_type (field->type);
1910 ftype = mono_type_get_basic_type_from_generic (ftype);
1911 if (type_has_references (klass, ftype))
1912 klass->has_static_refs = TRUE;
1916 for (i = 0; i < top; i++) {
1919 field = &klass->fields [i];
1921 ftype = mono_type_get_underlying_type (field->type);
1922 ftype = mono_type_get_basic_type_from_generic (ftype);
1923 if (type_has_references (klass, ftype)) {
1924 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1925 klass->has_static_refs = TRUE;
1927 klass->has_references = TRUE;
1932 * Compute field layout and total size (not considering static fields)
1935 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1936 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1938 if (gc_aware_layout)
1943 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1946 if (klass->parent) {
1947 mono_class_setup_fields (klass->parent);
1948 if (mono_class_has_failure (klass->parent)) {
1949 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1952 real_size = klass->parent->instance_size;
1954 real_size = sizeof (MonoObject);
1957 for (pass = 0; pass < passes; ++pass) {
1958 for (i = 0; i < top; i++){
1963 field = &klass->fields [i];
1965 if (mono_field_is_deleted (field))
1967 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1970 ftype = mono_type_get_underlying_type (field->type);
1971 ftype = mono_type_get_basic_type_from_generic (ftype);
1972 if (gc_aware_layout) {
1973 if (type_has_references (klass, ftype)) {
1982 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1983 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1984 /* This field is a hack inserted by MCS to empty structures */
1988 size = mono_type_size (field->type, &align);
1990 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1991 align = klass->packing_size ? MIN (klass->packing_size, align): align;
1992 /* if the field has managed references, we need to force-align it
1995 if (type_has_references (klass, ftype))
1996 align = MAX (align, sizeof (gpointer));
1998 klass->min_align = MAX (align, klass->min_align);
1999 field->offset = real_size;
2001 field->offset += align - 1;
2002 field->offset &= ~(align - 1);
2004 /*TypeBuilders produce all sort of weird things*/
2005 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
2006 real_size = field->offset + size;
2009 instance_size = MAX (real_size, instance_size);
2011 if (instance_size & (klass->min_align - 1)) {
2012 instance_size += klass->min_align - 1;
2013 instance_size &= ~(klass->min_align - 1);
2017 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
2021 for (i = 0; i < top; i++) {
2026 field = &klass->fields [i];
2029 * There must be info about all the fields in a type if it
2030 * uses explicit layout.
2032 if (mono_field_is_deleted (field))
2034 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2037 size = mono_type_size (field->type, &align);
2038 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2039 klass->min_align = MAX (align, klass->min_align);
2042 * When we get here, field->offset is already set by the
2043 * loader (for either runtime fields or fields loaded from metadata).
2044 * The offset is from the start of the object: this works for both
2045 * classes and valuetypes.
2047 field->offset += sizeof (MonoObject);
2048 ftype = mono_type_get_underlying_type (field->type);
2049 ftype = mono_type_get_basic_type_from_generic (ftype);
2050 if (type_has_references (klass, ftype)) {
2051 if (field->offset % sizeof (gpointer)) {
2052 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2059 real_size = MAX (real_size, size + field->offset);
2062 if (klass->has_references) {
2063 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2065 /* Check for overlapping reference and non-reference fields */
2066 for (i = 0; i < top; i++) {
2069 field = &klass->fields [i];
2071 if (mono_field_is_deleted (field))
2073 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2075 ftype = mono_type_get_underlying_type (field->type);
2076 if (MONO_TYPE_IS_REFERENCE (ftype))
2077 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2079 for (i = 0; i < top; i++) {
2080 field = &klass->fields [i];
2082 if (mono_field_is_deleted (field))
2084 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2087 // FIXME: Too much code does this
2089 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2090 char *err_msg = mono_image_strdup_printf (klass->image, "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);
2091 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2095 g_free (ref_bitmap);
2098 instance_size = MAX (real_size, instance_size);
2099 if (instance_size & (klass->min_align - 1)) {
2100 instance_size += klass->min_align - 1;
2101 instance_size &= ~(klass->min_align - 1);
2107 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2109 * This leads to all kinds of problems with nested structs, so only
2110 * enable it when a MONO_DEBUG property is set.
2112 * For small structs, set min_align to at least the struct size to improve
2113 * performance, and since the JIT memset/memcpy code assumes this and generates
2114 * unaligned accesses otherwise. See #78990 for a testcase.
2116 if (mono_align_small_structs) {
2117 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2118 klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
2122 if (klass->instance_size && !klass->image->dynamic) {
2123 /* Might be already set using cached info */
2124 g_assert (klass->instance_size == instance_size);
2126 klass->instance_size = instance_size;
2128 mono_memory_barrier ();
2129 klass->size_inited = 1;
2132 * Compute static field layout and size
2134 for (i = 0; i < top; i++){
2138 field = &klass->fields [i];
2140 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2142 if (mono_field_is_deleted (field))
2145 if (mono_type_has_exceptions (field->type)) {
2146 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2150 has_static_fields = TRUE;
2152 size = mono_type_size (field->type, &align);
2153 field->offset = klass->sizes.class_size;
2154 /*align is always non-zero here*/
2155 field->offset += align - 1;
2156 field->offset &= ~(align - 1);
2157 klass->sizes.class_size = field->offset + size;
2160 if (has_static_fields && klass->sizes.class_size == 0)
2161 /* Simplify code which depends on class_size != 0 if the class has static fields */
2162 klass->sizes.class_size = 8;
2166 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2170 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2171 method->klass = klass;
2172 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2173 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2174 method->signature = sig;
2175 method->name = name;
2178 if (name [0] == '.') {
2179 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2181 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2187 * mono_class_setup_methods:
2190 * Initializes the 'methods' array in CLASS.
2191 * Calling this method should be avoided if possible since it allocates a lot
2192 * of long-living MonoMethod structures.
2193 * Methods belonging to an interface are assigned a sequential slot starting
2196 * On failure this function sets klass->exception_type
2199 mono_class_setup_methods (MonoClass *klass)
2202 MonoMethod **methods;
2207 if (klass->generic_class) {
2209 MonoClass *gklass = klass->generic_class->container_class;
2211 mono_class_init (gklass);
2212 if (!mono_class_has_failure (gklass))
2213 mono_class_setup_methods (gklass);
2214 if (mono_class_has_failure (gklass)) {
2215 /* FIXME make exception_data less opaque so it's possible to dup it here */
2216 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Generic type definition failed to load"));
2220 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2221 count = gklass->method.count;
2222 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2224 for (i = 0; i < count; i++) {
2225 methods [i] = mono_class_inflate_generic_method_full_checked (
2226 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2227 if (!mono_error_ok (&error)) {
2228 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2229 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Could not inflate method %s due to %s", method, mono_error_get_message (&error)));
2232 mono_error_cleanup (&error);
2236 } else if (klass->rank) {
2238 MonoMethod *amethod;
2239 MonoMethodSignature *sig;
2240 int count_generic = 0, first_generic = 0;
2242 gboolean jagged_ctor = FALSE;
2244 count = 3 + (klass->rank > 1? 2: 1);
2246 mono_class_setup_interfaces (klass, &error);
2247 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2249 if (klass->rank == 1 && klass->element_class->rank) {
2251 klass->method.count ++;
2254 if (klass->interface_count) {
2255 count_generic = generic_array_methods (klass);
2256 first_generic = count;
2257 count += klass->interface_count * count_generic;
2260 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2262 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2263 sig->ret = &mono_defaults.void_class->byval_arg;
2264 sig->pinvoke = TRUE;
2265 sig->hasthis = TRUE;
2266 for (i = 0; i < klass->rank; ++i)
2267 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2269 amethod = create_array_method (klass, ".ctor", sig);
2270 methods [method_num++] = amethod;
2271 if (klass->rank > 1) {
2272 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2273 sig->ret = &mono_defaults.void_class->byval_arg;
2274 sig->pinvoke = TRUE;
2275 sig->hasthis = TRUE;
2276 for (i = 0; i < klass->rank * 2; ++i)
2277 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2279 amethod = create_array_method (klass, ".ctor", sig);
2280 methods [method_num++] = amethod;
2284 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2285 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2286 sig->ret = &mono_defaults.void_class->byval_arg;
2287 sig->pinvoke = TRUE;
2288 sig->hasthis = TRUE;
2289 for (i = 0; i < klass->rank + 1; ++i)
2290 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2291 amethod = create_array_method (klass, ".ctor", sig);
2292 methods [method_num++] = amethod;
2295 /* element Get (idx11, [idx2, ...]) */
2296 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2297 sig->ret = &klass->element_class->byval_arg;
2298 sig->pinvoke = TRUE;
2299 sig->hasthis = TRUE;
2300 for (i = 0; i < klass->rank; ++i)
2301 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2302 amethod = create_array_method (klass, "Get", sig);
2303 methods [method_num++] = amethod;
2304 /* element& Address (idx11, [idx2, ...]) */
2305 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2306 sig->ret = &klass->element_class->this_arg;
2307 sig->pinvoke = TRUE;
2308 sig->hasthis = TRUE;
2309 for (i = 0; i < klass->rank; ++i)
2310 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2311 amethod = create_array_method (klass, "Address", sig);
2312 methods [method_num++] = amethod;
2313 /* void Set (idx11, [idx2, ...], element) */
2314 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2315 sig->ret = &mono_defaults.void_class->byval_arg;
2316 sig->pinvoke = TRUE;
2317 sig->hasthis = TRUE;
2318 for (i = 0; i < klass->rank; ++i)
2319 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2320 sig->params [i] = &klass->element_class->byval_arg;
2321 amethod = create_array_method (klass, "Set", sig);
2322 methods [method_num++] = amethod;
2324 for (i = 0; i < klass->interface_count; i++)
2325 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2329 count = klass->method.count;
2330 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2331 for (i = 0; i < count; ++i) {
2332 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2333 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2335 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Could not load method %d due to %s", i, mono_error_get_message (&error)));
2336 mono_error_cleanup (&error);
2341 if (MONO_CLASS_IS_INTERFACE (klass)) {
2343 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2344 for (i = 0; i < count; ++i) {
2345 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2346 methods [i]->slot = slot++;
2350 mono_image_lock (klass->image);
2352 if (!klass->methods) {
2353 klass->method.count = count;
2355 /* Needed because of the double-checking locking pattern */
2356 mono_memory_barrier ();
2358 klass->methods = methods;
2361 mono_image_unlock (klass->image);
2365 * mono_class_get_method_by_index:
2367 * Returns klass->methods [index], initializing klass->methods if neccesary.
2369 * LOCKING: Acquires the loader lock.
2372 mono_class_get_method_by_index (MonoClass *klass, int index)
2375 /* Avoid calling setup_methods () if possible */
2376 if (klass->generic_class && !klass->methods) {
2377 MonoClass *gklass = klass->generic_class->container_class;
2380 m = mono_class_inflate_generic_method_full_checked (
2381 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2382 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2384 * If setup_methods () is called later for this class, no duplicates are created,
2385 * since inflate_generic_method guarantees that only one instance of a method
2386 * is created for each context.
2389 mono_class_setup_methods (klass);
2390 g_assert (m == klass->methods [index]);
2394 mono_class_setup_methods (klass);
2395 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2397 g_assert (index >= 0 && index < klass->method.count);
2398 return klass->methods [index];
2403 * mono_class_get_inflated_method:
2405 * Given an inflated class CLASS and a method METHOD which should be a method of
2406 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2409 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2411 MonoClass *gklass = klass->generic_class->container_class;
2414 g_assert (method->klass == gklass);
2416 mono_class_setup_methods (gklass);
2417 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2419 for (i = 0; i < gklass->method.count; ++i) {
2420 if (gklass->methods [i] == method) {
2421 if (klass->methods) {
2422 return klass->methods [i];
2425 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2426 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2436 * mono_class_get_vtable_entry:
2438 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2439 * LOCKING: Acquires the loader lock.
2442 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2446 if (klass->rank == 1) {
2448 * szarrays do not overwrite any methods of Array, so we can avoid
2449 * initializing their vtables in some cases.
2451 mono_class_setup_vtable (klass->parent);
2452 if (offset < klass->parent->vtable_size)
2453 return klass->parent->vtable [offset];
2456 if (klass->generic_class) {
2458 MonoClass *gklass = klass->generic_class->container_class;
2459 mono_class_setup_vtable (gklass);
2460 m = gklass->vtable [offset];
2462 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2463 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2465 mono_class_setup_vtable (klass);
2466 if (mono_class_has_failure (klass))
2468 m = klass->vtable [offset];
2475 * mono_class_get_vtable_size:
2477 * Return the vtable size for KLASS.
2480 mono_class_get_vtable_size (MonoClass *klass)
2482 mono_class_setup_vtable (klass);
2484 return klass->vtable_size;
2488 * mono_class_setup_properties:
2490 * Initialize klass->ext.property and klass->ext.properties.
2492 * This method can fail the class.
2495 mono_class_setup_properties (MonoClass *klass)
2497 guint startm, endm, i, j;
2498 guint32 cols [MONO_PROPERTY_SIZE];
2499 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2500 MonoProperty *properties;
2504 if (klass->ext && klass->ext->properties)
2507 if (klass->generic_class) {
2508 MonoClass *gklass = klass->generic_class->container_class;
2510 mono_class_init (gklass);
2511 mono_class_setup_properties (gklass);
2512 if (mono_class_has_failure (gklass)) {
2513 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Generic type definition failed to load"));
2517 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2519 for (i = 0; i < gklass->ext->property.count; i++) {
2521 MonoProperty *prop = &properties [i];
2523 *prop = gklass->ext->properties [i];
2526 prop->get = mono_class_inflate_generic_method_full_checked (
2527 prop->get, klass, mono_class_get_context (klass), &error);
2529 prop->set = mono_class_inflate_generic_method_full_checked (
2530 prop->set, klass, mono_class_get_context (klass), &error);
2532 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2533 prop->parent = klass;
2536 first = gklass->ext->property.first;
2537 count = gklass->ext->property.count;
2539 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2540 count = last - first;
2543 mono_class_setup_methods (klass);
2544 if (mono_class_has_failure (klass))
2548 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2549 for (i = first; i < last; ++i) {
2550 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2551 properties [i - first].parent = klass;
2552 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2553 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2555 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2556 for (j = startm; j < endm; ++j) {
2559 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2561 if (klass->image->uncompressed_metadata) {
2563 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2564 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2565 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2567 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2570 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2571 case METHOD_SEMANTIC_SETTER:
2572 properties [i - first].set = method;
2574 case METHOD_SEMANTIC_GETTER:
2575 properties [i - first].get = method;
2584 mono_class_alloc_ext (klass);
2586 mono_image_lock (klass->image);
2588 if (klass->ext->properties) {
2589 /* We leak 'properties' which was allocated from the image mempool */
2590 mono_image_unlock (klass->image);
2594 klass->ext->property.first = first;
2595 klass->ext->property.count = count;
2597 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2598 mono_memory_barrier ();
2600 /* Leave this assignment as the last op in the function */
2601 klass->ext->properties = properties;
2603 mono_image_unlock (klass->image);
2607 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2609 MonoMethod **om, **retval;
2612 for (om = methods, count = 0; *om; ++om, ++count)
2615 retval = g_new0 (MonoMethod*, count + 1);
2617 for (om = methods, count = 0; *om; ++om, ++count) {
2619 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2620 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2626 /*This method can fail the class.*/
2628 mono_class_setup_events (MonoClass *klass)
2631 guint startm, endm, i, j;
2632 guint32 cols [MONO_EVENT_SIZE];
2633 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2637 if (klass->ext && klass->ext->events)
2640 if (klass->generic_class) {
2641 MonoClass *gklass = klass->generic_class->container_class;
2642 MonoGenericContext *context = NULL;
2644 mono_class_setup_events (gklass);
2645 if (mono_class_has_failure (gklass)) {
2646 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Generic type definition failed to load"));
2650 first = gklass->ext->event.first;
2651 count = gklass->ext->event.count;
2653 events = mono_class_new0 (klass, MonoEvent, count);
2656 context = mono_class_get_context (klass);
2658 for (i = 0; i < count; i++) {
2660 MonoEvent *event = &events [i];
2661 MonoEvent *gevent = &gklass->ext->events [i];
2663 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2665 event->parent = klass;
2666 event->name = gevent->name;
2667 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2668 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2669 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2670 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2671 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2672 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2674 #ifndef MONO_SMALL_CONFIG
2675 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2677 event->attrs = gevent->attrs;
2680 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2681 count = last - first;
2684 mono_class_setup_methods (klass);
2685 if (mono_class_has_failure (klass)) {
2686 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Generic type definition failed to load"));
2691 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2692 for (i = first; i < last; ++i) {
2693 MonoEvent *event = &events [i - first];
2695 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2696 event->parent = klass;
2697 event->attrs = cols [MONO_EVENT_FLAGS];
2698 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2700 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2701 for (j = startm; j < endm; ++j) {
2704 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2706 if (klass->image->uncompressed_metadata) {
2708 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2709 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2710 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2712 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2715 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2716 case METHOD_SEMANTIC_ADD_ON:
2717 event->add = method;
2719 case METHOD_SEMANTIC_REMOVE_ON:
2720 event->remove = method;
2722 case METHOD_SEMANTIC_FIRE:
2723 event->raise = method;
2725 case METHOD_SEMANTIC_OTHER: {
2726 #ifndef MONO_SMALL_CONFIG
2729 if (event->other == NULL) {
2730 event->other = g_new0 (MonoMethod*, 2);
2732 while (event->other [n])
2734 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2736 event->other [n] = method;
2737 /* NULL terminated */
2738 event->other [n + 1] = NULL;
2749 mono_class_alloc_ext (klass);
2751 mono_image_lock (klass->image);
2753 if (klass->ext->events) {
2754 mono_image_unlock (klass->image);
2758 klass->ext->event.first = first;
2759 klass->ext->event.count = count;
2761 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2762 mono_memory_barrier ();
2764 /* Leave this assignment as the last op in the function */
2765 klass->ext->events = events;
2767 mono_image_unlock (klass->image);
2771 * Global pool of interface IDs, represented as a bitset.
2772 * LOCKING: Protected by the classes lock.
2774 static MonoBitSet *global_interface_bitset = NULL;
2777 * mono_unload_interface_ids:
2778 * @bitset: bit set of interface IDs
2780 * When an image is unloaded, the interface IDs associated with
2781 * the image are put back in the global pool of IDs so the numbers
2785 mono_unload_interface_ids (MonoBitSet *bitset)
2788 mono_bitset_sub (global_interface_bitset, bitset);
2793 mono_unload_interface_id (MonoClass *klass)
2795 if (global_interface_bitset && klass->interface_id) {
2797 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2803 * mono_get_unique_iid:
2806 * Assign a unique integer ID to the interface represented by @class.
2807 * The ID will positive and as small as possible.
2808 * LOCKING: Acquires the classes lock.
2809 * Returns: The new ID.
2812 mono_get_unique_iid (MonoClass *klass)
2816 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2820 if (!global_interface_bitset) {
2821 global_interface_bitset = mono_bitset_new (128, 0);
2824 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2826 int old_size = mono_bitset_size (global_interface_bitset);
2827 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2828 mono_bitset_free (global_interface_bitset);
2829 global_interface_bitset = new_set;
2832 mono_bitset_set (global_interface_bitset, iid);
2833 /* set the bit also in the per-image set */
2834 if (!klass->generic_class) {
2835 if (klass->image->interface_bitset) {
2836 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2837 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2838 mono_bitset_free (klass->image->interface_bitset);
2839 klass->image->interface_bitset = new_set;
2842 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2844 mono_bitset_set (klass->image->interface_bitset, iid);
2849 #ifndef MONO_SMALL_CONFIG
2850 if (mono_print_vtable) {
2852 char *type_name = mono_type_full_name (&klass->byval_arg);
2853 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2854 generic_id = klass->generic_class->context.class_inst->id;
2855 g_assert (generic_id != 0);
2859 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2864 g_assert (iid <= 65535);
2869 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2874 mono_class_setup_interfaces (klass, error);
2875 return_if_nok (error);
2877 for (i = 0; i < klass->interface_count; i++) {
2878 ic = klass->interfaces [i];
2881 *res = g_ptr_array_new ();
2882 g_ptr_array_add (*res, ic);
2883 mono_class_init (ic);
2884 if (mono_class_has_failure (ic)) {
2885 mono_error_set_type_load_class (error, ic, "Error Loading class");
2889 collect_implemented_interfaces_aux (ic, res, error);
2890 return_if_nok (error);
2895 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2897 GPtrArray *res = NULL;
2899 collect_implemented_interfaces_aux (klass, &res, error);
2900 if (!mono_error_ok (error)) {
2902 g_ptr_array_free (res, TRUE);
2909 compare_interface_ids (const void *p_key, const void *p_element) {
2910 const MonoClass *key = (const MonoClass *)p_key;
2911 const MonoClass *element = *(const MonoClass **)p_element;
2913 return (key->interface_id - element->interface_id);
2916 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2918 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2919 MonoClass **result = (MonoClass **)mono_binary_search (
2921 klass->interfaces_packed,
2922 klass->interface_offsets_count,
2923 sizeof (MonoClass *),
2924 compare_interface_ids);
2926 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2933 * mono_class_interface_offset_with_variance:
2935 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2936 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2938 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2940 * FIXME figure out MS disambiguation rules and fix this function.
2943 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2944 int i = mono_class_interface_offset (klass, itf);
2945 *non_exact_match = FALSE;
2949 if (!mono_class_has_variant_generic_params (itf))
2952 for (i = 0; i < klass->interface_offsets_count; i++) {
2953 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2954 *non_exact_match = TRUE;
2955 return klass->interface_offsets_packed [i];
2963 print_implemented_interfaces (MonoClass *klass) {
2966 GPtrArray *ifaces = NULL;
2968 int ancestor_level = 0;
2970 name = mono_type_get_full_name (klass);
2971 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2974 for (i = 0; i < klass->interface_offsets_count; i++)
2975 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2976 klass->interfaces_packed [i]->interface_id,
2977 klass->interface_offsets_packed [i],
2978 klass->interfaces_packed [i]->method.count,
2979 klass->interfaces_packed [i]->name_space,
2980 klass->interfaces_packed [i]->name );
2981 printf ("Interface flags: ");
2982 for (i = 0; i <= klass->max_interface_id; i++)
2983 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2984 printf ("(%d,T)", i);
2986 printf ("(%d,F)", i);
2988 printf ("Dump interface flags:");
2989 #ifdef COMPRESSED_INTERFACE_BITMAP
2991 const uint8_t* p = klass->interface_bitmap;
2992 i = klass->max_interface_id;
2994 printf (" %d x 00 %02X", p [0], p [1]);
3000 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3001 printf (" %02X", klass->interface_bitmap [i]);
3004 while (klass != NULL) {
3005 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3006 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3007 if (!mono_error_ok (&error)) {
3008 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3009 mono_error_cleanup (&error);
3010 } else if (ifaces) {
3011 for (i = 0; i < ifaces->len; i++) {
3012 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3013 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3014 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3016 mono_class_interface_offset (klass, ic),
3021 g_ptr_array_free (ifaces, TRUE);
3024 klass = klass->parent;
3029 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3032 args [0] = &arg0->byval_arg;
3034 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3038 array_class_get_if_rank (MonoClass *klass, guint rank)
3040 return rank ? mono_array_class_get (klass, rank) : klass;
3044 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3046 valuetype_types [0] = eclass;
3047 if (eclass == mono_defaults.int16_class)
3048 valuetype_types [1] = mono_defaults.uint16_class;
3049 else if (eclass == mono_defaults.uint16_class)
3050 valuetype_types [1] = mono_defaults.int16_class;
3051 else if (eclass == mono_defaults.int32_class)
3052 valuetype_types [1] = mono_defaults.uint32_class;
3053 else if (eclass == mono_defaults.uint32_class)
3054 valuetype_types [1] = mono_defaults.int32_class;
3055 else if (eclass == mono_defaults.int64_class)
3056 valuetype_types [1] = mono_defaults.uint64_class;
3057 else if (eclass == mono_defaults.uint64_class)
3058 valuetype_types [1] = mono_defaults.int64_class;
3059 else if (eclass == mono_defaults.byte_class)
3060 valuetype_types [1] = mono_defaults.sbyte_class;
3061 else if (eclass == mono_defaults.sbyte_class)
3062 valuetype_types [1] = mono_defaults.byte_class;
3063 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3064 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3067 /* this won't be needed once bug #325495 is completely fixed
3068 * though we'll need something similar to know which interfaces to allow
3069 * in arrays when they'll be lazyly created
3071 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3072 * MS returns diferrent types based on which instance is called. For example:
3073 * object obj = new byte[10][];
3074 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3075 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3078 * Fixing this should kill quite some code, save some bits and improve compatibility.
3081 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3083 MonoClass *eclass = klass->element_class;
3084 static MonoClass* generic_icollection_class = NULL;
3085 static MonoClass* generic_ienumerable_class = NULL;
3086 static MonoClass* generic_ienumerator_class = NULL;
3087 static MonoClass* generic_ireadonlylist_class = NULL;
3088 static MonoClass* generic_ireadonlycollection_class = NULL;
3089 MonoClass *valuetype_types[2] = { NULL, NULL };
3090 MonoClass **interfaces = NULL;
3091 int i, nifaces, interface_count, real_count, original_rank;
3093 gboolean internal_enumerator;
3094 gboolean eclass_is_valuetype;
3096 if (!mono_defaults.generic_ilist_class) {
3100 internal_enumerator = FALSE;
3101 eclass_is_valuetype = FALSE;
3102 original_rank = eclass->rank;
3103 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3104 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3106 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3108 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3109 original_rank = eclass->rank;
3111 eclass = eclass->element_class;
3112 internal_enumerator = TRUE;
3113 *is_enumerator = TRUE;
3121 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3122 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3124 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3126 if (!generic_icollection_class) {
3127 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3128 "System.Collections.Generic", "ICollection`1");
3129 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3130 "System.Collections.Generic", "IEnumerable`1");
3131 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3132 "System.Collections.Generic", "IEnumerator`1");
3133 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3134 "System.Collections.Generic", "IReadOnlyList`1");
3135 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3136 "System.Collections.Generic", "IReadOnlyCollection`1");
3139 mono_class_init (eclass);
3142 * Arrays in 2.0 need to implement a number of generic interfaces
3143 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3144 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3145 * We collect the types needed to build the
3146 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3147 * the generic interfaces needed to implement.
3149 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3150 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3152 if (eclass->valuetype) {
3153 nifaces = generic_ireadonlylist_class ? 5 : 3;
3154 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3156 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3157 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3158 if (internal_enumerator) {
3160 if (valuetype_types [1])
3164 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3165 interfaces [0] = valuetype_types [0];
3166 if (valuetype_types [1])
3167 interfaces [nifaces] = valuetype_types [1];
3169 eclass_is_valuetype = TRUE;
3172 int idepth = eclass->idepth;
3173 if (!internal_enumerator)
3175 nifaces = generic_ireadonlylist_class ? 2 : 3;
3177 // FIXME: This doesn't seem to work/required for generic params
3178 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3179 mono_class_setup_interface_offsets (eclass);
3181 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3182 /* we add object for interfaces and the supertypes for the other
3183 * types. The last of the supertypes is the element class itself which we
3184 * already created the explicit interfaces for (so we include it for IEnumerator
3185 * and exclude it for arrays).
3187 if (MONO_CLASS_IS_INTERFACE (eclass))
3190 interface_count += idepth;
3191 if (eclass->rank && eclass->element_class->valuetype) {
3192 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3193 if (valuetype_types [1])
3196 /* IList, ICollection, IEnumerable, IReadOnlyList */
3197 interface_count *= nifaces;
3198 real_count = interface_count;
3199 if (internal_enumerator) {
3200 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3201 if (valuetype_types [1])
3204 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3205 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3206 interfaces [0] = mono_defaults.object_class;
3210 for (i = 0; i < idepth; i++) {
3211 mono_class_init (eclass->supertypes [i]);
3212 interfaces [j] = eclass->supertypes [i];
3216 if (all_interfaces) {
3217 for (i = 0; i < eclass->interface_offsets_count; i++) {
3218 interfaces [j] = eclass->interfaces_packed [i];
3222 for (i = 0; i < eclass->interface_count; i++) {
3223 interfaces [j] = eclass->interfaces [i];
3227 if (valuetype_types [1]) {
3228 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3233 /* instantiate the generic interfaces */
3234 for (i = 0; i < interface_count; i += nifaces) {
3235 MonoClass *iface = interfaces [i];
3237 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3238 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3240 if (eclass->valuetype) {
3241 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3242 if (generic_ireadonlylist_class) {
3243 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3244 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3247 if (!generic_ireadonlylist_class)
3248 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3251 if (internal_enumerator) {
3253 /* instantiate IEnumerator<iface> */
3254 for (i = 0; i < interface_count; i++) {
3255 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3257 j = interface_count;
3258 if (!eclass_is_valuetype) {
3259 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3260 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3263 for (i = 0; i < eclass->idepth; i++) {
3264 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3268 for (i = 0; i < eclass->interface_offsets_count; i++) {
3269 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3273 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3275 if (valuetype_types [1])
3276 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3280 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3281 for (i = 0; i < real_count; ++i) {
3282 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3283 g_print ("%s implements %s\n", type_name, name);
3294 find_array_interface (MonoClass *klass, const char *name)
3297 for (i = 0; i < klass->interface_count; ++i) {
3298 if (strcmp (klass->interfaces [i]->name, name) == 0)
3305 * Return the number of virtual methods.
3306 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3307 * Return -1 on failure.
3308 * FIXME It would be nice if this information could be cached somewhere.
3311 count_virtual_methods (MonoClass *klass)
3315 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3317 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3318 mono_class_setup_methods (klass);
3319 if (mono_class_has_failure (klass))
3322 for (i = 0; i < klass->method.count; ++i) {
3323 flags = klass->methods [i]->flags;
3324 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3328 for (i = 0; i < klass->method.count; ++i) {
3329 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3331 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3339 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3347 m = (l + num_ifaces) / 2;
3348 if (interfaces_full [m] == ic)
3350 if (l == num_ifaces)
3352 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3361 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3363 int i = find_interface (num_ifaces, interfaces_full, ic);
3365 return interface_offsets_full [i];
3370 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3372 int i = find_interface (num_ifaces, interfaces_full, ic);
3376 interface_offsets_full [i] = offset;
3379 for (i = 0; i < num_ifaces; ++i) {
3380 if (interfaces_full [i]) {
3382 if (interfaces_full [i]->interface_id < ic->interface_id)
3385 while (end < num_ifaces && interfaces_full [end]) end++;
3386 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3387 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3389 interfaces_full [i] = ic;
3390 interface_offsets_full [i] = offset;
3396 #ifdef COMPRESSED_INTERFACE_BITMAP
3399 * Compressed interface bitmap design.
3401 * Interface bitmaps take a large amount of memory, because their size is
3402 * linear with the maximum interface id assigned in the process (each interface
3403 * is assigned a unique id as it is loaded). The number of interface classes
3404 * is high because of the many implicit interfaces implemented by arrays (we'll
3405 * need to lazy-load them in the future).
3406 * Most classes implement a very small number of interfaces, so the bitmap is
3407 * sparse. This bitmap needs to be checked by interface casts, so access to the
3408 * needed bit must be fast and doable with few jit instructions.
3410 * The current compression format is as follows:
3411 * *) it is a sequence of one or more two-byte elements
3412 * *) the first byte in the element is the count of empty bitmap bytes
3413 * at the current bitmap position
3414 * *) the second byte in the element is an actual bitmap byte at the current
3417 * As an example, the following compressed bitmap bytes:
3418 * 0x07 0x01 0x00 0x7
3419 * correspond to the following bitmap:
3420 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3422 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3423 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3424 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3428 * mono_compress_bitmap:
3429 * @dest: destination buffer
3430 * @bitmap: bitmap buffer
3431 * @size: size of @bitmap in bytes
3433 * This is a mono internal function.
3434 * The @bitmap data is compressed into a format that is small but
3435 * still searchable in few instructions by the JIT and runtime.
3436 * The compressed data is stored in the buffer pointed to by the
3437 * @dest array. Passing a #NULL value for @dest allows to just compute
3438 * the size of the buffer.
3439 * This compression algorithm assumes the bits set in the bitmap are
3440 * few and far between, like in interface bitmaps.
3441 * Returns: The size of the compressed bitmap in bytes.
3444 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3448 const uint8_t *end = bitmap + size;
3449 while (bitmap < end) {
3450 if (*bitmap || numz == 255) {
3474 * mono_class_interface_match:
3475 * @bitmap: a compressed bitmap buffer
3476 * @id: the index to check in the bitmap
3478 * This is a mono internal function.
3479 * Checks if a bit is set in a compressed interface bitmap. @id must
3480 * be already checked for being smaller than the maximum id encoded in the
3483 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3487 mono_class_interface_match (const uint8_t *bitmap, int id)
3490 id -= bitmap [0] * 8;
3494 return bitmap [1] & (1 << id);
3503 * LOCKING: this is supposed to be called with the loader lock held.
3504 * Return -1 on failure and set exception_type
3507 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3511 int i, j, max_iid, num_ifaces;
3512 MonoClass **interfaces_full = NULL;
3513 int *interface_offsets_full = NULL;
3515 GPtrArray **ifaces_array = NULL;
3516 int interface_offsets_count;
3517 MonoClass **array_interfaces = NULL;
3518 int num_array_interfaces;
3519 int is_enumerator = FALSE;
3521 mono_class_setup_supertypes (klass);
3523 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3524 * implicit interfaces have the property that they are assigned the same slot in the
3525 * vtables for compatible interfaces
3527 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3529 /* compute maximum number of slots and maximum interface id */
3531 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3532 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3533 for (j = 0; j < klass->idepth; j++) {
3534 k = klass->supertypes [j];
3535 num_ifaces += k->interface_count;
3536 for (i = 0; i < k->interface_count; i++) {
3537 ic = k->interfaces [i];
3540 mono_class_init (ic);
3542 if (max_iid < ic->interface_id)
3543 max_iid = ic->interface_id;
3545 ifaces = mono_class_get_implemented_interfaces (k, &error);
3546 if (!mono_error_ok (&error)) {
3547 char *name = mono_type_get_full_name (k);
3548 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error)));
3550 mono_error_cleanup (&error);
3555 num_ifaces += ifaces->len;
3556 for (i = 0; i < ifaces->len; ++i) {
3557 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3558 if (max_iid < ic->interface_id)
3559 max_iid = ic->interface_id;
3561 ifaces_array [j] = ifaces;
3565 for (i = 0; i < num_array_interfaces; ++i) {
3566 ic = array_interfaces [i];
3567 mono_class_init (ic);
3568 if (max_iid < ic->interface_id)
3569 max_iid = ic->interface_id;
3572 if (MONO_CLASS_IS_INTERFACE (klass)) {
3574 if (max_iid < klass->interface_id)
3575 max_iid = klass->interface_id;
3577 klass->max_interface_id = max_iid;
3578 /* compute vtable offset for interfaces */
3579 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3580 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3582 for (i = 0; i < num_ifaces; i++) {
3583 interface_offsets_full [i] = -1;
3586 /* skip the current class */
3587 for (j = 0; j < klass->idepth - 1; j++) {
3588 k = klass->supertypes [j];
3589 ifaces = ifaces_array [j];
3592 for (i = 0; i < ifaces->len; ++i) {
3594 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3596 /*Force the sharing of interface offsets between parent and subtypes.*/
3597 io = mono_class_interface_offset (k, ic);
3599 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3604 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3605 ifaces = ifaces_array [klass->idepth - 1];
3607 for (i = 0; i < ifaces->len; ++i) {
3609 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3610 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3612 count = count_virtual_methods (ic);
3614 char *name = mono_type_get_full_name (ic);
3615 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Error calculating interface offset of %s", name));
3624 if (MONO_CLASS_IS_INTERFACE (klass))
3625 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3627 if (num_array_interfaces) {
3628 if (is_enumerator) {
3629 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3630 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3631 g_assert (ienumerator_offset >= 0);
3632 for (i = 0; i < num_array_interfaces; ++i) {
3633 ic = array_interfaces [i];
3634 if (strcmp (ic->name, "IEnumerator`1") == 0)
3635 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3637 g_assert_not_reached ();
3638 /*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);*/
3641 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3642 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3643 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3644 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3645 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3646 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3647 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3648 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3649 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3650 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3651 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3652 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3653 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3654 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3655 for (i = 0; i < num_array_interfaces; ++i) {
3657 ic = array_interfaces [i];
3658 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3659 offset = ilist_offset;
3660 else if (strcmp (ic->name, "ICollection`1") == 0)
3661 offset = icollection_offset;
3662 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3663 offset = ienumerable_offset;
3664 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3665 offset = ireadonlylist_offset;
3666 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3667 offset = ireadonlycollection_offset;
3669 g_assert_not_reached ();
3670 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3671 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3676 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3677 if (interface_offsets_full [i] != -1) {
3678 interface_offsets_count ++;
3683 * We might get called multiple times:
3684 * - mono_class_init ()
3685 * - mono_class_setup_vtable ().
3686 * - mono_class_setup_interface_offsets ().
3687 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3688 * means we have to overwrite those when called from other places (#4440).
3690 if (klass->interfaces_packed) {
3692 g_assert (klass->interface_offsets_count == interface_offsets_count);
3696 klass->interface_offsets_count = interface_offsets_count;
3697 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3698 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3699 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3700 #ifdef COMPRESSED_INTERFACE_BITMAP
3701 bitmap = g_malloc0 (bsize);
3703 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3705 for (i = 0; i < interface_offsets_count; i++) {
3706 int id = interfaces_full [i]->interface_id;
3707 bitmap [id >> 3] |= (1 << (id & 7));
3708 klass->interfaces_packed [i] = interfaces_full [i];
3709 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3710 /*if (num_array_interfaces)
3711 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]);*/
3713 #ifdef COMPRESSED_INTERFACE_BITMAP
3714 i = mono_compress_bitmap (NULL, bitmap, bsize);
3715 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3716 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3719 klass->interface_bitmap = bitmap;
3724 g_free (interfaces_full);
3725 g_free (interface_offsets_full);
3726 g_free (array_interfaces);
3727 for (i = 0; i < klass->idepth; i++) {
3728 ifaces = ifaces_array [i];
3730 g_ptr_array_free (ifaces, TRUE);
3732 g_free (ifaces_array);
3734 //printf ("JUST DONE: ");
3735 //print_implemented_interfaces (klass);
3741 * Setup interface offsets for interfaces.
3743 * - klass->max_interface_id
3744 * - klass->interface_offsets_count
3745 * - klass->interfaces_packed
3746 * - klass->interface_offsets_packed
3747 * - klass->interface_bitmap
3749 * This function can fail @class.
3752 mono_class_setup_interface_offsets (MonoClass *klass)
3754 mono_loader_lock ();
3756 setup_interface_offsets (klass, 0, FALSE);
3758 mono_loader_unlock ();
3761 /*Checks if @klass has @parent as one of it's parents type gtd
3765 * Bar<T> : Foo<Bar<Bar<T>>>
3769 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3771 klass = mono_class_get_generic_type_definition (klass);
3772 parent = mono_class_get_generic_type_definition (parent);
3773 mono_class_setup_supertypes (klass);
3774 mono_class_setup_supertypes (parent);
3776 return klass->idepth >= parent->idepth &&
3777 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3781 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3783 MonoGenericInst *ginst;
3785 if (!klass->generic_class) {
3786 mono_class_setup_vtable_full (klass, in_setup);
3787 return !mono_class_has_failure (klass);
3790 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3791 if (mono_class_has_failure (klass->generic_class->container_class)) {
3792 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Failed to load generic definition vtable"));
3796 ginst = klass->generic_class->context.class_inst;
3797 for (i = 0; i < ginst->type_argc; ++i) {
3799 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3801 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3802 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3803 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3805 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3806 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Failed to load generic parameter %d", i));
3814 * mono_class_setup_vtable:
3816 * Creates the generic vtable of CLASS.
3817 * Initializes the following fields in MonoClass:
3820 * Plus all the fields initialized by setup_interface_offsets ().
3821 * If there is an error during vtable construction, klass->exception_type is set.
3823 * LOCKING: Acquires the loader lock.
3826 mono_class_setup_vtable (MonoClass *klass)
3828 mono_class_setup_vtable_full (klass, NULL);
3832 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3835 MonoMethod **overrides;
3836 MonoGenericContext *context;
3844 if (MONO_CLASS_IS_INTERFACE (klass)) {
3845 /* This sets method->slot for all methods if this is an interface */
3846 mono_class_setup_methods (klass);
3850 if (mono_class_has_failure (klass))
3853 if (g_list_find (in_setup, klass))
3856 mono_loader_lock ();
3858 if (klass->vtable) {
3859 mono_loader_unlock ();
3863 mono_stats.generic_vtable_count ++;
3864 in_setup = g_list_prepend (in_setup, klass);
3866 if (klass->generic_class) {
3867 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3868 mono_loader_unlock ();
3869 g_list_remove (in_setup, klass);
3873 context = mono_class_get_context (klass);
3874 type_token = klass->generic_class->container_class->type_token;
3876 context = (MonoGenericContext *) klass->generic_container;
3877 type_token = klass->type_token;
3880 if (image_is_dynamic (klass->image)) {
3881 /* Generic instances can have zero method overrides without causing any harm.
3882 * This is true since we don't do layout all over again for them, we simply inflate
3883 * the layout of the parent.
3885 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3886 if (!is_ok (&error)) {
3887 mono_loader_unlock ();
3888 g_list_remove (in_setup, klass);
3889 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf(klass->image, "Could not load list of method overrides due to %s", mono_error_get_message (&error)));
3890 mono_error_cleanup (&error);
3894 /* The following call fails if there are missing methods in the type */
3895 /* FIXME it's probably a good idea to avoid this for generic instances. */
3896 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3900 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3902 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Could not load list of method overrides"));
3906 mono_loader_unlock ();
3907 g_list_remove (in_setup, klass);
3912 #define DEBUG_INTERFACE_VTABLE_CODE 0
3913 #define TRACE_INTERFACE_VTABLE_CODE 0
3914 #define VERIFY_INTERFACE_VTABLE_CODE 0
3915 #define VTABLE_SELECTOR (1)
3917 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3918 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3919 if (!(VTABLE_SELECTOR)) break; \
3923 #define DEBUG_INTERFACE_VTABLE(stmt)
3926 #if TRACE_INTERFACE_VTABLE_CODE
3927 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3928 if (!(VTABLE_SELECTOR)) break; \
3932 #define TRACE_INTERFACE_VTABLE(stmt)
3935 #if VERIFY_INTERFACE_VTABLE_CODE
3936 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3937 if (!(VTABLE_SELECTOR)) break; \
3941 #define VERIFY_INTERFACE_VTABLE(stmt)
3945 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3947 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3951 GString *res = g_string_new ("");
3953 g_string_append_c (res, '(');
3954 for (i = 0; i < sig->param_count; ++i) {
3956 g_string_append_c (res, ',');
3957 mono_type_get_desc (res, sig->params [i], include_namespace);
3959 g_string_append (res, ")=>");
3960 if (sig->ret != NULL) {
3961 mono_type_get_desc (res, sig->ret, include_namespace);
3963 g_string_append (res, "NULL");
3966 g_string_free (res, FALSE);
3970 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3971 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3972 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3973 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3981 is_wcf_hack_disabled (void)
3983 static gboolean disabled;
3984 static gboolean inited = FALSE;
3986 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3993 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3995 MonoMethodSignature *cmsig, *imsig;
3996 if (strcmp (im->name, cm->name) == 0) {
3997 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3998 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4001 if (! slot_is_empty) {
4002 if (require_newslot) {
4003 if (! interface_is_explicitly_implemented_by_class) {
4004 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4007 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4008 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4012 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4015 cmsig = mono_method_signature (cm);
4016 imsig = mono_method_signature (im);
4017 if (!cmsig || !imsig) {
4018 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Could not resolve the signature of a virtual method"));
4022 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4023 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4024 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4025 TRACE_INTERFACE_VTABLE (printf ("]"));
4028 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4029 if (mono_security_core_clr_enabled ())
4030 mono_security_core_clr_check_override (klass, cm, im);
4032 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4033 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4034 char *body_name = mono_method_full_name (cm, TRUE);
4035 char *decl_name = mono_method_full_name (im, TRUE);
4036 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4044 MonoClass *ic = im->klass;
4045 const char *ic_name_space = ic->name_space;
4046 const char *ic_name = ic->name;
4049 if (! require_newslot) {
4050 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4053 if (cm->klass->rank == 0) {
4054 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4057 cmsig = mono_method_signature (cm);
4058 imsig = mono_method_signature (im);
4059 if (!cmsig || !imsig) {
4060 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Could not resolve the signature of a virtual method"));
4064 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4065 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4066 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4067 TRACE_INTERFACE_VTABLE (printf ("]"));
4070 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4071 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4074 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4075 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4078 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))) {
4079 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4083 subname = strstr (cm->name, ic_name_space);
4084 if (subname != cm->name) {
4085 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4088 subname += strlen (ic_name_space);
4089 if (subname [0] != '.') {
4090 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4094 if (strstr (subname, ic_name) != subname) {
4095 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4098 subname += strlen (ic_name);
4099 if (subname [0] != '.') {
4100 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4104 if (strcmp (subname, im->name) != 0) {
4105 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4109 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4110 if (mono_security_core_clr_enabled ())
4111 mono_security_core_clr_check_override (klass, cm, im);
4113 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4114 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4115 char *body_name = mono_method_full_name (cm, TRUE);
4116 char *decl_name = mono_method_full_name (im, TRUE);
4117 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4127 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4129 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4130 MonoMethod *method = key;
4131 MonoMethod *override = value;
4132 MonoClass *method_class = mono_method_get_class (method);
4133 MonoClass *override_class = mono_method_get_class (override);
4135 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4136 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4137 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4140 print_overrides (GHashTable *override_map, const char *message) {
4142 printf ("Override map \"%s\" START:\n", message);
4143 g_hash_table_foreach (override_map, foreach_override, NULL);
4144 printf ("Override map \"%s\" END.\n", message);
4146 printf ("Override map \"%s\" EMPTY.\n", message);
4150 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4151 char *full_name = mono_type_full_name (&klass->byval_arg);
4155 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4157 if (print_interfaces) {
4158 print_implemented_interfaces (klass);
4159 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4162 if (klass->parent) {
4163 parent_size = klass->parent->vtable_size;
4167 for (i = 0; i < size; ++i) {
4168 MonoMethod *cm = vtable [i];
4169 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4170 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4172 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4180 #if VERIFY_INTERFACE_VTABLE_CODE
4182 mono_method_try_get_vtable_index (MonoMethod *method)
4184 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4185 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4186 if (imethod->declaring->is_generic)
4187 return imethod->declaring->slot;
4189 return method->slot;
4193 mono_class_verify_vtable (MonoClass *klass)
4196 char *full_name = mono_type_full_name (&klass->byval_arg);
4198 printf ("*** Verifying VTable of class '%s' \n", full_name);
4202 if (!klass->methods)
4205 for (i = 0; i < klass->method.count; ++i) {
4206 MonoMethod *cm = klass->methods [i];
4209 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4213 full_name = mono_method_full_name (cm, TRUE);
4215 slot = mono_method_try_get_vtable_index (cm);
4217 if (slot >= klass->vtable_size) {
4218 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4222 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4223 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4224 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4225 g_free (other_name);
4228 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4235 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4237 char *method_signature;
4240 for (index = 0; index < onum; ++index) {
4241 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4242 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4244 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4245 type_name = mono_type_full_name (&klass->byval_arg);
4246 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4247 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4248 g_free (method_signature);
4250 mono_class_setup_methods (klass);
4251 if (mono_class_has_failure (klass)) {
4252 char *name = mono_type_get_full_name (klass);
4253 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4257 for (index = 0; index < klass->method.count; ++index) {
4258 MonoMethod *cm = klass->methods [index];
4259 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4261 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4262 g_free (method_signature);
4267 mono_method_get_method_definition (MonoMethod *method)
4269 while (method->is_inflated)
4270 method = ((MonoMethodInflated*)method)->declaring;
4275 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4279 for (i = 0; i < onum; ++i) {
4280 MonoMethod *decl = overrides [i * 2];
4281 MonoMethod *body = overrides [i * 2 + 1];
4283 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4284 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Method belongs to a different class than the declared one"));
4288 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4289 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4290 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Method must not be static to override a base type"));
4292 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Method must be virtual to override a base type"));
4296 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4297 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4298 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Cannot override a static method in a base type"));
4300 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Cannot override a non virtual method in a base type"));
4304 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4305 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Method overrides a class or interface that is not extended or implemented by this type"));
4309 body = mono_method_get_method_definition (body);
4310 decl = mono_method_get_method_definition (decl);
4312 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4313 char *body_name = mono_method_full_name (body, TRUE);
4314 char *decl_name = mono_method_full_name (decl, TRUE);
4315 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4325 mono_class_need_stelemref_method (MonoClass *klass)
4327 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4331 * LOCKING: this is supposed to be called with the loader lock held.
4334 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4338 MonoMethod **vtable;
4339 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4340 GPtrArray *ifaces = NULL;
4341 GHashTable *override_map = NULL;
4343 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4344 int first_non_interface_slot;
4346 GSList *virt_methods = NULL, *l;
4347 int stelemref_slot = 0;
4352 if (overrides && !verify_class_overrides (klass, overrides, onum))
4355 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4356 if (!mono_error_ok (&error)) {
4357 char *name = mono_type_get_full_name (klass);
4358 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error)));
4360 mono_error_cleanup (&error);
4362 } else if (ifaces) {
4363 for (i = 0; i < ifaces->len; i++) {
4364 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4365 max_vtsize += ic->method.count;
4367 g_ptr_array_free (ifaces, TRUE);
4371 if (klass->parent) {
4372 mono_class_init (klass->parent);
4373 mono_class_setup_vtable_full (klass->parent, in_setup);
4375 if (mono_class_has_failure (klass->parent)) {
4376 char *name = mono_type_get_full_name (klass->parent);
4377 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Parent %s failed to load", name));
4382 max_vtsize += klass->parent->vtable_size;
4383 cur_slot = klass->parent->vtable_size;
4386 max_vtsize += klass->method.count;
4388 /*Array have a slot for stelemref*/
4389 if (mono_class_need_stelemref_method (klass)) {
4390 stelemref_slot = cur_slot;
4395 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4396 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4398 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4400 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4401 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4404 max_iid = klass->max_interface_id;
4405 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4407 /* Optimized version for generic instances */
4408 if (klass->generic_class) {
4410 MonoClass *gklass = klass->generic_class->container_class;
4413 mono_class_setup_vtable_full (gklass, in_setup);
4414 if (mono_class_has_failure (gklass)) {
4415 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4419 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4420 klass->vtable_size = gklass->vtable_size;
4421 for (i = 0; i < gklass->vtable_size; ++i)
4422 if (gklass->vtable [i]) {
4423 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4424 if (!mono_error_ok (&error)) {
4425 char *err_msg = mono_image_strdup_printf (klass->image, "Could not inflate method due to %s", mono_error_get_message (&error));
4426 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4427 mono_error_cleanup (&error);
4431 tmp [i]->slot = gklass->vtable [i]->slot;
4433 mono_memory_barrier ();
4434 klass->vtable = tmp;
4436 /* Have to set method->slot for abstract virtual methods */
4437 if (klass->methods && gklass->methods) {
4438 for (i = 0; i < klass->method.count; ++i)
4439 if (klass->methods [i]->slot == -1)
4440 klass->methods [i]->slot = gklass->methods [i]->slot;
4446 if (klass->parent && klass->parent->vtable_size) {
4447 MonoClass *parent = klass->parent;
4450 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4452 // Also inherit parent interface vtables, just as a starting point.
4453 // This is needed otherwise bug-77127.exe fails when the property methods
4454 // have different names in the iterface and the class, because for child
4455 // classes the ".override" information is not used anymore.
4456 for (i = 0; i < parent->interface_offsets_count; i++) {
4457 MonoClass *parent_interface = parent->interfaces_packed [i];
4458 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4459 /*FIXME this is now dead code as this condition will never hold true.
4460 Since interface offsets are inherited then the offset of an interface implemented
4461 by a parent will never be the out of it's vtable boundary.
4463 if (interface_offset >= parent->vtable_size) {
4464 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4467 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4468 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4469 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4470 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4471 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4472 parent_interface_offset + j, parent_interface_offset, j,
4473 interface_offset + j, interface_offset, j));
4480 /*Array have a slot for stelemref*/
4481 if (mono_class_need_stelemref_method (klass)) {
4482 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4484 method->slot = stelemref_slot;
4486 g_assert (method->slot == stelemref_slot);
4488 vtable [stelemref_slot] = method;
4491 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4492 /* override interface methods */
4493 for (i = 0; i < onum; i++) {
4494 MonoMethod *decl = overrides [i*2];
4495 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4497 dslot = mono_method_get_vtable_slot (decl);
4499 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4503 dslot += mono_class_interface_offset (klass, decl->klass);
4504 vtable [dslot] = overrides [i*2 + 1];
4505 vtable [dslot]->slot = dslot;
4507 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4509 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4511 if (mono_security_core_clr_enabled ())
4512 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4515 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4516 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4519 * Create a list of virtual methods to avoid calling
4520 * mono_class_get_virtual_methods () which is slow because of the metadata
4524 gpointer iter = NULL;
4527 virt_methods = NULL;
4528 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4529 virt_methods = g_slist_prepend (virt_methods, cm);
4531 if (mono_class_has_failure (klass))
4535 // Loop on all implemented interfaces...
4536 for (i = 0; i < klass->interface_offsets_count; i++) {
4537 MonoClass *parent = klass->parent;
4539 gboolean interface_is_explicitly_implemented_by_class;
4542 ic = klass->interfaces_packed [i];
4543 ic_offset = mono_class_interface_offset (klass, ic);
4545 mono_class_setup_methods (ic);
4546 if (mono_class_has_failure (ic))
4549 // Check if this interface is explicitly implemented (instead of just inherited)
4550 if (parent != NULL) {
4551 int implemented_interfaces_index;
4552 interface_is_explicitly_implemented_by_class = FALSE;
4553 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4554 if (ic == klass->interfaces [implemented_interfaces_index]) {
4555 interface_is_explicitly_implemented_by_class = TRUE;
4560 interface_is_explicitly_implemented_by_class = TRUE;
4563 // Loop on all interface methods...
4564 for (im_index = 0; im_index < ic->method.count; im_index++) {
4565 MonoMethod *im = ic->methods [im_index];
4566 int im_slot = ic_offset + im->slot;
4567 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4569 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4572 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4574 // If there is an explicit implementation, just use it right away,
4575 // otherwise look for a matching method
4576 if (override_im == NULL) {
4580 // First look for a suitable method among the class methods
4581 for (l = virt_methods; l; l = l->next) {
4582 cm = (MonoMethod *)l->data;
4583 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)));
4584 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4585 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4586 vtable [im_slot] = cm;
4587 /* Why do we need this? */
4592 TRACE_INTERFACE_VTABLE (printf ("\n"));
4593 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4597 // If the slot is still empty, look in all the inherited virtual methods...
4598 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4599 MonoClass *parent = klass->parent;
4600 // Reverse order, so that last added methods are preferred
4601 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4602 MonoMethod *cm = parent->vtable [cm_index];
4604 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));
4605 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4606 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4607 vtable [im_slot] = cm;
4608 /* Why do we need this? */
4614 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4616 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4620 g_assert (vtable [im_slot] == override_im);
4625 // If the class is not abstract, check that all its interface slots are full.
4626 // The check is done here and not directly at the end of the loop above because
4627 // it can happen (for injected generic array interfaces) that the same slot is
4628 // processed multiple times (those interfaces have overlapping slots), and it
4629 // will not always be the first pass the one that fills the slot.
4630 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4631 for (i = 0; i < klass->interface_offsets_count; i++) {
4635 ic = klass->interfaces_packed [i];
4636 ic_offset = mono_class_interface_offset (klass, ic);
4638 for (im_index = 0; im_index < ic->method.count; im_index++) {
4639 MonoMethod *im = ic->methods [im_index];
4640 int im_slot = ic_offset + im->slot;
4642 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4645 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4646 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4647 if (vtable [im_slot] == NULL) {
4648 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4655 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4656 for (l = virt_methods; l; l = l->next) {
4657 cm = (MonoMethod *)l->data;
4659 * If the method is REUSE_SLOT, we must check in the
4660 * base class for a method to override.
4662 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4664 for (k = klass->parent; k ; k = k->parent) {
4669 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4670 MonoMethodSignature *cmsig, *m1sig;
4672 cmsig = mono_method_signature (cm);
4673 m1sig = mono_method_signature (m1);
4675 if (!cmsig || !m1sig) {
4676 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4680 if (!strcmp(cm->name, m1->name) &&
4681 mono_metadata_signature_equal (cmsig, m1sig)) {
4683 if (mono_security_core_clr_enabled ())
4684 mono_security_core_clr_check_override (klass, cm, m1);
4686 slot = mono_method_get_vtable_slot (m1);
4690 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4691 char *body_name = mono_method_full_name (cm, TRUE);
4692 char *decl_name = mono_method_full_name (m1, TRUE);
4693 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4699 g_assert (cm->slot < max_vtsize);
4701 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4702 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4703 mono_method_full_name (m1, 1), m1,
4704 mono_method_full_name (cm, 1), cm));
4705 g_hash_table_insert (override_map, m1, cm);
4709 if (mono_class_has_failure (k))
4719 /*Non final newslot methods must be given a non-interface vtable slot*/
4720 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4724 cm->slot = cur_slot++;
4726 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4727 vtable [cm->slot] = cm;
4730 /* override non interface methods */
4731 for (i = 0; i < onum; i++) {
4732 MonoMethod *decl = overrides [i*2];
4733 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4734 g_assert (decl->slot != -1);
4735 vtable [decl->slot] = overrides [i*2 + 1];
4736 overrides [i * 2 + 1]->slot = decl->slot;
4738 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4739 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4740 mono_method_full_name (decl, 1), decl,
4741 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4742 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4744 if (mono_security_core_clr_enabled ())
4745 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4750 * If a method occupies more than one place in the vtable, and it is
4751 * overriden, then change the other occurances too.
4756 for (i = 0; i < max_vtsize; ++i)
4758 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4760 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4765 g_hash_table_destroy (override_map);
4766 override_map = NULL;
4769 g_slist_free (virt_methods);
4770 virt_methods = NULL;
4772 /* Ensure that all vtable slots are filled with concrete instance methods */
4773 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4774 for (i = 0; i < cur_slot; ++i) {
4775 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4776 char *type_name = mono_type_get_full_name (klass);
4777 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4778 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name));
4780 g_free (method_name);
4786 if (klass->generic_class) {
4787 MonoClass *gklass = klass->generic_class->container_class;
4789 mono_class_init (gklass);
4791 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4793 /* Check that the vtable_size value computed in mono_class_init () is correct */
4794 if (klass->vtable_size)
4795 g_assert (cur_slot == klass->vtable_size);
4796 klass->vtable_size = cur_slot;
4799 /* Try to share the vtable with our parent. */
4800 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4801 mono_memory_barrier ();
4802 klass->vtable = klass->parent->vtable;
4804 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4805 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4806 mono_memory_barrier ();
4807 klass->vtable = tmp;
4810 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4811 if (mono_print_vtable) {
4814 print_implemented_interfaces (klass);
4816 for (i = 0; i <= max_iid; i++)
4817 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4820 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4821 klass->vtable_size, icount);
4823 for (i = 0; i < cur_slot; ++i) {
4828 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4829 mono_method_full_name (cm, TRUE));
4835 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4836 klass->name, max_iid);
4838 for (i = 0; i < klass->interface_count; i++) {
4839 ic = klass->interfaces [i];
4840 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4841 mono_class_interface_offset (klass, ic),
4842 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4845 for (k = klass->parent; k ; k = k->parent) {
4846 for (i = 0; i < k->interface_count; i++) {
4847 ic = k->interfaces [i];
4848 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4849 mono_class_interface_offset (klass, ic),
4850 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4856 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4861 char *name = mono_type_get_full_name (klass);
4862 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "VTable setup of type %s failed", name));
4865 g_hash_table_destroy (override_map);
4867 g_slist_free (virt_methods);
4872 * mono_method_get_vtable_slot:
4874 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4875 * LOCKING: Acquires the loader lock.
4877 * FIXME Use proper MonoError machinery here.
4880 mono_method_get_vtable_slot (MonoMethod *method)
4882 if (method->slot == -1) {
4883 mono_class_setup_vtable (method->klass);
4884 if (mono_class_has_failure (method->klass))
4886 if (method->slot == -1) {
4890 if (!method->klass->generic_class) {
4891 g_assert (method->is_inflated);
4892 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4895 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4896 g_assert (method->klass->generic_class);
4897 gklass = method->klass->generic_class->container_class;
4898 mono_class_setup_methods (method->klass);
4899 g_assert (method->klass->methods);
4900 for (i = 0; i < method->klass->method.count; ++i) {
4901 if (method->klass->methods [i] == method)
4904 g_assert (i < method->klass->method.count);
4905 g_assert (gklass->methods);
4906 method->slot = gklass->methods [i]->slot;
4908 g_assert (method->slot != -1);
4910 return method->slot;
4914 * mono_method_get_vtable_index:
4917 * Returns the index into the runtime vtable to access the method or,
4918 * in the case of a virtual generic method, the virtual generic method
4919 * thunk. Returns -1 on failure.
4921 * FIXME Use proper MonoError machinery here.
4924 mono_method_get_vtable_index (MonoMethod *method)
4926 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4927 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4928 if (imethod->declaring->is_generic)
4929 return mono_method_get_vtable_slot (imethod->declaring);
4931 return mono_method_get_vtable_slot (method);
4934 static MonoMethod *default_ghc = NULL;
4935 static MonoMethod *default_finalize = NULL;
4936 static int finalize_slot = -1;
4937 static int ghc_slot = -1;
4940 initialize_object_slots (MonoClass *klass)
4945 if (klass == mono_defaults.object_class) {
4946 mono_class_setup_vtable (klass);
4947 for (i = 0; i < klass->vtable_size; ++i) {
4948 MonoMethod *cm = klass->vtable [i];
4950 if (!strcmp (cm->name, "GetHashCode"))
4952 else if (!strcmp (cm->name, "Finalize"))
4956 g_assert (ghc_slot > 0);
4957 default_ghc = klass->vtable [ghc_slot];
4959 g_assert (finalize_slot > 0);
4960 default_finalize = klass->vtable [finalize_slot];
4965 MonoMethod *array_method;
4967 } GenericArrayMethodInfo;
4969 static int generic_array_method_num = 0;
4970 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4973 generic_array_methods (MonoClass *klass)
4975 int i, count_generic = 0;
4976 GList *list = NULL, *tmp;
4977 if (generic_array_method_num)
4978 return generic_array_method_num;
4979 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4980 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4981 for (i = 0; i < klass->parent->method.count; i++) {
4982 MonoMethod *m = klass->parent->methods [i];
4983 if (!strncmp (m->name, "InternalArray__", 15)) {
4985 list = g_list_prepend (list, m);
4988 list = g_list_reverse (list);
4989 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4991 for (tmp = list; tmp; tmp = tmp->next) {
4992 const char *mname, *iname;
4994 MonoMethod *m = (MonoMethod *)tmp->data;
4995 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4996 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4998 generic_array_method_info [i].array_method = m;
4999 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5000 iname = "System.Collections.Generic.ICollection`1.";
5001 mname = m->name + 27;
5002 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5003 iname = "System.Collections.Generic.IEnumerable`1.";
5004 mname = m->name + 27;
5005 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5006 iname = "System.Collections.Generic.IReadOnlyList`1.";
5007 mname = m->name + strlen (ireadonlylist_prefix);
5008 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5009 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5010 mname = m->name + strlen (ireadonlycollection_prefix);
5011 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5012 iname = "System.Collections.Generic.IList`1.";
5013 mname = m->name + 15;
5015 g_assert_not_reached ();
5018 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5019 strcpy (name, iname);
5020 strcpy (name + strlen (iname), mname);
5021 generic_array_method_info [i].name = name;
5024 /*g_print ("array generic methods: %d\n", count_generic);*/
5026 generic_array_method_num = count_generic;
5028 return generic_array_method_num;
5032 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5034 MonoGenericContext tmp_context;
5037 tmp_context.class_inst = NULL;
5038 tmp_context.method_inst = iface->generic_class->context.class_inst;
5039 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5041 for (i = 0; i < generic_array_method_num; i++) {
5043 MonoMethod *m = generic_array_method_info [i].array_method;
5044 MonoMethod *inflated;
5046 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5047 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5048 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5053 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5055 int null_length = strlen ("(null)");
5056 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5057 char *s = (char *)mono_image_alloc (image, len);
5060 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5061 g_assert (result == len - 1);
5068 * @class: the class to initialize
5070 * Compute the instance_size, class_size and other infos that cannot be
5071 * computed at mono_class_get() time. Also compute vtable_size if possible.
5072 * Returns TRUE on success or FALSE if there was a problem in loading
5073 * the type (incorrect assemblies, missing assemblies, methods, etc).
5075 * LOCKING: Acquires the loader lock.
5078 mono_class_init (MonoClass *klass)
5081 MonoCachedClassInfo cached_info;
5082 gboolean has_cached_info;
5086 /* Double-checking locking pattern */
5087 if (klass->inited || mono_class_has_failure (klass))
5088 return !mono_class_has_failure (klass);
5090 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5092 /* We do everything inside the lock to prevent races */
5093 mono_loader_lock ();
5095 if (klass->inited || mono_class_has_failure (klass)) {
5096 mono_loader_unlock ();
5097 /* Somebody might have gotten in before us */
5098 return !mono_class_has_failure (klass);
5101 if (klass->init_pending) {
5102 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Recursive type definition detected"));
5106 klass->init_pending = 1;
5108 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5109 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5114 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5115 MonoClass *element_class = klass->element_class;
5116 if (!element_class->inited)
5117 mono_class_init (element_class);
5118 if (mono_class_has_failure (element_class)) {
5119 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5124 mono_stats.initialized_class_count++;
5126 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5127 MonoClass *gklass = klass->generic_class->container_class;
5129 mono_stats.generic_class_count++;
5131 klass->method = gklass->method;
5132 klass->field = gklass->field;
5134 mono_class_init (gklass);
5135 // FIXME: Why is this needed ?
5136 if (!mono_class_has_failure (gklass))
5137 mono_class_setup_methods (gklass);
5138 if (mono_class_has_failure (gklass)) {
5139 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Generic Type Defintion failed to init"));
5143 if (MONO_CLASS_IS_INTERFACE (klass))
5144 klass->interface_id = mono_get_unique_iid (klass);
5147 if (klass->parent && !klass->parent->inited)
5148 mono_class_init (klass->parent);
5150 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5152 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5153 klass->nested_classes_inited = TRUE;
5156 * Computes the size used by the fields, and their locations
5158 if (has_cached_info) {
5159 klass->instance_size = cached_info.instance_size;
5160 klass->sizes.class_size = cached_info.class_size;
5161 klass->packing_size = cached_info.packing_size;
5162 klass->min_align = cached_info.min_align;
5163 klass->blittable = cached_info.blittable;
5164 klass->has_references = cached_info.has_references;
5165 klass->has_static_refs = cached_info.has_static_refs;
5166 klass->no_special_static_fields = cached_info.no_special_static_fields;
5169 if (!klass->size_inited){
5170 mono_class_setup_fields (klass);
5171 if (mono_class_has_failure (klass))
5175 /* Initialize arrays */
5177 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5179 if (klass->interface_count) {
5180 int count_generic = generic_array_methods (klass);
5181 klass->method.count += klass->interface_count * count_generic;
5185 mono_class_setup_supertypes (klass);
5188 initialize_object_slots (klass);
5191 * Initialize the rest of the data without creating a generic vtable if possible.
5192 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5193 * also avoid computing a generic vtable.
5195 if (has_cached_info) {
5197 klass->vtable_size = cached_info.vtable_size;
5198 klass->has_finalize = cached_info.has_finalize;
5199 klass->has_finalize_inited = TRUE;
5200 klass->ghcimpl = cached_info.ghcimpl;
5201 klass->has_cctor = cached_info.has_cctor;
5202 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5203 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5204 * The first slot if for array with.
5206 static int szarray_vtable_size[2] = { 0 };
5208 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5211 if (!szarray_vtable_size [slot]) {
5212 mono_class_setup_vtable (klass);
5213 szarray_vtable_size [slot] = klass->vtable_size;
5215 klass->vtable_size = szarray_vtable_size[slot];
5217 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5218 MonoClass *gklass = klass->generic_class->container_class;
5220 /* Generic instance case */
5221 klass->ghcimpl = gklass->ghcimpl;
5222 klass->has_cctor = gklass->has_cctor;
5224 mono_class_setup_vtable (gklass);
5225 if (mono_class_has_failure (gklass)) {
5226 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5230 klass->vtable_size = gklass->vtable_size;
5234 /* ghcimpl is not currently used
5236 if (klass->parent) {
5237 MonoMethod *cmethod = klass->vtable [ghc_slot];
5238 if (cmethod->is_inflated)
5239 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5240 if (cmethod == default_ghc) {
5246 /* C# doesn't allow interfaces to have cctors */
5247 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5248 MonoMethod *cmethod = NULL;
5250 if (klass->type_token && !image_is_dynamic(klass->image)) {
5251 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5252 /* The find_method function ignores the 'flags' argument */
5253 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5254 klass->has_cctor = 1;
5256 mono_class_setup_methods (klass);
5257 if (mono_class_has_failure (klass))
5260 for (i = 0; i < klass->method.count; ++i) {
5261 MonoMethod *method = klass->methods [i];
5262 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5263 (strcmp (".cctor", method->name) == 0)) {
5264 klass->has_cctor = 1;
5272 if (klass->parent) {
5273 int first_iface_slot;
5274 /* This will compute klass->parent->vtable_size for some classes */
5275 mono_class_init (klass->parent);
5276 if (mono_class_has_failure (klass->parent)) {
5277 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5280 if (!klass->parent->vtable_size) {
5281 /* FIXME: Get rid of this somehow */
5282 mono_class_setup_vtable (klass->parent);
5283 if (mono_class_has_failure (klass->parent)) {
5284 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5288 first_iface_slot = klass->parent->vtable_size;
5289 if (mono_class_need_stelemref_method (klass))
5291 setup_interface_offsets (klass, first_iface_slot, TRUE);
5293 setup_interface_offsets (klass, 0, TRUE);
5296 if (mono_security_core_clr_enabled ())
5297 mono_security_core_clr_check_inheritance (klass);
5299 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5300 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Invalid generic instantiation"));
5305 /* Because of the double-checking locking pattern */
5306 mono_memory_barrier ();
5308 klass->init_pending = 0;
5310 mono_loader_unlock ();
5312 return !mono_class_has_failure (klass);
5316 * mono_class_has_finalizer:
5318 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5322 mono_class_has_finalizer (MonoClass *klass)
5324 gboolean has_finalize = FALSE;
5326 if (klass->has_finalize_inited)
5327 return klass->has_finalize;
5329 /* Interfaces and valuetypes are not supposed to have finalizers */
5330 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5331 MonoMethod *cmethod = NULL;
5333 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5334 } else if (klass->generic_class) {
5335 MonoClass *gklass = klass->generic_class->container_class;
5337 has_finalize = mono_class_has_finalizer (gklass);
5338 } else if (klass->parent && klass->parent->has_finalize) {
5339 has_finalize = TRUE;
5341 if (klass->parent) {
5343 * Can't search in metadata for a method named Finalize, because that
5344 * ignores overrides.
5346 mono_class_setup_vtable (klass);
5347 if (mono_class_has_failure (klass))
5350 cmethod = klass->vtable [finalize_slot];
5354 g_assert (klass->vtable_size > finalize_slot);
5356 if (klass->parent) {
5357 if (cmethod->is_inflated)
5358 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5359 if (cmethod != default_finalize)
5360 has_finalize = TRUE;
5366 mono_image_lock (klass->image);
5368 if (!klass->has_finalize_inited) {
5369 klass->has_finalize = has_finalize ? 1 : 0;
5371 mono_memory_barrier ();
5372 klass->has_finalize_inited = TRUE;
5375 mono_image_unlock (klass->image);
5377 return klass->has_finalize;
5381 mono_is_corlib_image (MonoImage *image)
5383 /* FIXME: allow the dynamic case for our compilers and with full trust */
5384 if (image_is_dynamic (image))
5385 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5387 return image == mono_defaults.corlib;
5391 * LOCKING: this assumes the loader lock is held
5394 mono_class_setup_mono_type (MonoClass *klass)
5396 const char *name = klass->name;
5397 const char *nspace = klass->name_space;
5398 gboolean is_corlib = mono_is_corlib_image (klass->image);
5400 klass->this_arg.byref = 1;
5401 klass->this_arg.data.klass = klass;
5402 klass->this_arg.type = MONO_TYPE_CLASS;
5403 klass->byval_arg.data.klass = klass;
5404 klass->byval_arg.type = MONO_TYPE_CLASS;
5406 if (is_corlib && !strcmp (nspace, "System")) {
5407 if (!strcmp (name, "ValueType")) {
5409 * do not set the valuetype bit for System.ValueType.
5410 * klass->valuetype = 1;
5412 klass->blittable = TRUE;
5413 } else if (!strcmp (name, "Enum")) {
5415 * do not set the valuetype bit for System.Enum.
5416 * klass->valuetype = 1;
5418 klass->valuetype = 0;
5419 klass->enumtype = 0;
5420 } else if (!strcmp (name, "Object")) {
5421 klass->byval_arg.type = MONO_TYPE_OBJECT;
5422 klass->this_arg.type = MONO_TYPE_OBJECT;
5423 } else if (!strcmp (name, "String")) {
5424 klass->byval_arg.type = MONO_TYPE_STRING;
5425 klass->this_arg.type = MONO_TYPE_STRING;
5426 } else if (!strcmp (name, "TypedReference")) {
5427 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5428 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5432 if (klass->valuetype) {
5433 int t = MONO_TYPE_VALUETYPE;
5435 if (is_corlib && !strcmp (nspace, "System")) {
5438 if (!strcmp (name, "Boolean")) {
5439 t = MONO_TYPE_BOOLEAN;
5440 } else if (!strcmp(name, "Byte")) {
5442 klass->blittable = TRUE;
5446 if (!strcmp (name, "Char")) {
5451 if (!strcmp (name, "Double")) {
5453 klass->blittable = TRUE;
5457 if (!strcmp (name, "Int32")) {
5459 klass->blittable = TRUE;
5460 } else if (!strcmp(name, "Int16")) {
5462 klass->blittable = TRUE;
5463 } else if (!strcmp(name, "Int64")) {
5465 klass->blittable = TRUE;
5466 } else if (!strcmp(name, "IntPtr")) {
5468 klass->blittable = TRUE;
5472 if (!strcmp (name, "Single")) {
5474 klass->blittable = TRUE;
5475 } else if (!strcmp(name, "SByte")) {
5477 klass->blittable = TRUE;
5481 if (!strcmp (name, "UInt32")) {
5483 klass->blittable = TRUE;
5484 } else if (!strcmp(name, "UInt16")) {
5486 klass->blittable = TRUE;
5487 } else if (!strcmp(name, "UInt64")) {
5489 klass->blittable = TRUE;
5490 } else if (!strcmp(name, "UIntPtr")) {
5492 klass->blittable = TRUE;
5496 if (!strcmp (name, "TypedReference")) {
5497 t = MONO_TYPE_TYPEDBYREF;
5498 klass->blittable = TRUE;
5502 if (!strcmp (name, "Void")) {
5510 klass->byval_arg.type = (MonoTypeEnum)t;
5511 klass->this_arg.type = (MonoTypeEnum)t;
5514 if (MONO_CLASS_IS_INTERFACE (klass))
5515 klass->interface_id = mono_get_unique_iid (klass);
5521 * COM initialization is delayed until needed.
5522 * However when a [ComImport] attribute is present on a type it will trigger
5523 * the initialization. This is not a problem unless the BCL being executed
5524 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5527 init_com_from_comimport (MonoClass *klass)
5529 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5530 if (mono_security_core_clr_enabled ()) {
5531 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5532 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5533 /* but it can not be made available for application (i.e. user code) since all COM calls
5534 * are considered native calls. In this case we fail with a TypeLoadException (just like
5535 * Silverlight 2 does */
5536 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5541 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5543 #endif /*DISABLE_COM*/
5546 * LOCKING: this assumes the loader lock is held
5549 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5551 gboolean system_namespace;
5552 gboolean is_corlib = mono_is_corlib_image (klass->image);
5554 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5556 /* if root of the hierarchy */
5557 if (system_namespace && !strcmp (klass->name, "Object")) {
5558 klass->parent = NULL;
5559 klass->instance_size = sizeof (MonoObject);
5562 if (!strcmp (klass->name, "<Module>")) {
5563 klass->parent = NULL;
5564 klass->instance_size = 0;
5568 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5569 /* Imported COM Objects always derive from __ComObject. */
5571 if (MONO_CLASS_IS_IMPORT (klass)) {
5572 init_com_from_comimport (klass);
5573 if (parent == mono_defaults.object_class)
5574 parent = mono_class_get_com_object_class ();
5578 /* set the parent to something useful and safe, but mark the type as broken */
5579 parent = mono_defaults.object_class;
5580 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5583 klass->parent = parent;
5585 if (parent->generic_class && !parent->name) {
5587 * If the parent is a generic instance, we may get
5588 * called before it is fully initialized, especially
5589 * before it has its name.
5594 #ifndef DISABLE_REMOTING
5595 klass->marshalbyref = parent->marshalbyref;
5596 klass->contextbound = parent->contextbound;
5599 klass->delegate = parent->delegate;
5601 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5602 mono_class_set_is_com_object (klass);
5604 if (system_namespace) {
5605 #ifndef DISABLE_REMOTING
5606 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5607 klass->marshalbyref = 1;
5609 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5610 klass->contextbound = 1;
5612 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5613 klass->delegate = 1;
5616 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5617 (strcmp (klass->parent->name_space, "System") == 0)))
5618 klass->valuetype = 1;
5619 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5620 klass->valuetype = klass->enumtype = 1;
5622 /*klass->enumtype = klass->parent->enumtype; */
5624 /* initialize com types if COM interfaces are present */
5626 if (MONO_CLASS_IS_IMPORT (klass))
5627 init_com_from_comimport (klass);
5629 klass->parent = NULL;
5635 * mono_class_setup_supertypes:
5638 * Build the data structure needed to make fast type checks work.
5639 * This currently sets two fields in @class:
5640 * - idepth: distance between @class and System.Object in the type
5642 * - supertypes: array of classes: each element has a class in the hierarchy
5643 * starting from @class up to System.Object
5645 * LOCKING: This function is atomic, in case of contention we waste memory.
5648 mono_class_setup_supertypes (MonoClass *klass)
5651 MonoClass **supertypes;
5653 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5657 if (klass->parent && !klass->parent->supertypes)
5658 mono_class_setup_supertypes (klass->parent);
5660 klass->idepth = klass->parent->idepth + 1;
5664 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5665 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5667 if (klass->parent) {
5668 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5671 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5672 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5674 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5677 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5681 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5683 MonoClass *gtd = (MonoClass*)user_data;
5684 /* Only try to fix generic instances of @gtd */
5685 if (gclass->generic_class->container_class != gtd)
5688 /* Check if the generic instance has no parent. */
5689 if (gtd->parent && !gclass->parent)
5690 mono_generic_class_setup_parent (gclass, gtd);
5696 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5698 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, msg));
5699 mono_error_set_type_load_class (error, klass, msg);
5703 * mono_class_create_from_typedef:
5704 * @image: image where the token is valid
5705 * @type_token: typedef token
5706 * @error: used to return any error found while creating the type
5708 * Create the MonoClass* representing the specified type token.
5709 * @type_token must be a TypeDef token.
5711 * FIXME: don't return NULL on failure, just the the caller figure it out.
5714 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5716 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5717 MonoClass *klass, *parent = NULL;
5718 guint32 cols [MONO_TYPEDEF_SIZE];
5719 guint32 cols_next [MONO_TYPEDEF_SIZE];
5720 guint tidx = mono_metadata_token_index (type_token);
5721 MonoGenericContext *context = NULL;
5722 const char *name, *nspace;
5724 MonoClass **interfaces;
5725 guint32 field_last, method_last;
5726 guint32 nesting_tokeen;
5728 mono_error_init (error);
5730 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5731 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5735 mono_loader_lock ();
5737 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5738 mono_loader_unlock ();
5742 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5744 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5745 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5747 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5750 klass->name_space = nspace;
5752 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5754 klass->image = image;
5755 klass->type_token = type_token;
5756 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5758 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5760 classes_size += sizeof (MonoClass);
5763 * Check whether we're a generic type definition.
5765 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5766 if (klass->generic_container) {
5767 klass->is_generic = 1;
5768 klass->generic_container->owner.klass = klass;
5769 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5770 context = &klass->generic_container->context;
5773 if (klass->generic_container)
5774 enable_gclass_recording ();
5776 if (cols [MONO_TYPEDEF_EXTENDS]) {
5778 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5780 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5781 /*WARNING: this must satisfy mono_metadata_type_hash*/
5782 klass->this_arg.byref = 1;
5783 klass->this_arg.data.klass = klass;
5784 klass->this_arg.type = MONO_TYPE_CLASS;
5785 klass->byval_arg.data.klass = klass;
5786 klass->byval_arg.type = MONO_TYPE_CLASS;
5788 parent = mono_class_get_checked (image, parent_token, error);
5789 if (parent && context) /* Always inflate */
5790 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5792 if (parent == NULL) {
5793 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, mono_error_get_message (error)));
5794 goto parent_failure;
5797 for (tmp = parent; tmp; tmp = tmp->parent) {
5799 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5800 goto parent_failure;
5802 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5803 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5804 goto parent_failure;
5809 mono_class_setup_parent (klass, parent);
5811 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5812 mono_class_setup_mono_type (klass);
5814 if (klass->generic_container)
5815 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5818 * This might access klass->byval_arg for recursion generated by generic constraints,
5819 * so it has to come after setup_mono_type ().
5821 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5822 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5823 if (!mono_error_ok (error)) {
5824 /*FIXME implement a mono_class_set_failure_from_mono_error */
5825 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, mono_error_get_message (error)));
5826 mono_loader_unlock ();
5827 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5832 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5836 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5840 klass->cast_class = klass->element_class = klass;
5842 if (!klass->enumtype) {
5843 if (!mono_metadata_interfaces_from_typedef_full (
5844 image, type_token, &interfaces, &icount, FALSE, context, error)){
5846 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, mono_error_get_message (error)));
5847 mono_loader_unlock ();
5848 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5852 klass->interfaces = interfaces;
5853 klass->interface_count = icount;
5854 klass->interfaces_inited = 1;
5857 /*g_print ("Load class %s\n", name);*/
5860 * Compute the field and method lists
5862 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5863 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5865 if (tt->rows > tidx){
5866 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5867 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5868 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5870 field_last = image->tables [MONO_TABLE_FIELD].rows;
5871 method_last = image->tables [MONO_TABLE_METHOD].rows;
5874 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5875 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5876 klass->field.count = field_last - klass->field.first;
5878 klass->field.count = 0;
5880 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5881 klass->method.count = method_last - klass->method.first;
5883 klass->method.count = 0;
5885 /* reserve space to store vector pointer in arrays */
5886 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5887 klass->instance_size += 2 * sizeof (gpointer);
5888 g_assert (klass->field.count == 0);
5891 if (klass->enumtype) {
5892 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5893 if (!enum_basetype) {
5894 /*set it to a default value as the whole runtime can't handle this to be null*/
5895 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5896 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, mono_error_get_message (error)));
5897 mono_loader_unlock ();
5898 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5901 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5905 * If we're a generic type definition, load the constraints.
5906 * We must do this after the class has been constructed to make certain recursive scenarios
5909 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5910 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup_printf (klass->image, "Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
5911 mono_loader_unlock ();
5912 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5916 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5917 if (!strncmp (name, "Vector", 6))
5918 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");
5921 mono_loader_unlock ();
5923 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5928 mono_class_setup_mono_type (klass);
5929 mono_loader_unlock ();
5930 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5934 /** Is klass a Nullable<T> ginst? */
5936 mono_class_is_nullable (MonoClass *klass)
5938 return klass->generic_class != NULL &&
5939 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5943 /** if klass is T? return T */
5945 mono_class_get_nullable_param (MonoClass *klass)
5947 g_assert (mono_class_is_nullable (klass));
5948 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5952 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5956 MonoGenericClass *gclass = klass->generic_class;
5958 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5959 if (!mono_error_ok (&error)) {
5960 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5961 klass->parent = mono_defaults.object_class;
5962 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5963 mono_error_cleanup (&error);
5967 mono_class_setup_parent (klass, klass->parent);
5969 if (klass->enumtype) {
5970 klass->cast_class = gtd->cast_class;
5971 klass->element_class = gtd->element_class;
5977 * Create the `MonoClass' for an instantiation of a generic type.
5978 * We only do this if we actually need it.
5981 mono_generic_class_get_class (MonoGenericClass *gclass)
5983 MonoClass *klass, *gklass;
5985 if (gclass->cached_class)
5986 return gclass->cached_class;
5988 mono_loader_lock ();
5989 if (gclass->cached_class) {
5990 mono_loader_unlock ();
5991 return gclass->cached_class;
5994 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5996 gklass = gclass->container_class;
5998 if (record_gclass_instantiation > 0)
5999 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6001 if (gklass->nested_in) {
6002 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6003 klass->nested_in = gklass->nested_in;
6006 klass->name = gklass->name;
6007 klass->name_space = gklass->name_space;
6009 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6011 klass->image = gklass->image;
6012 klass->flags = gklass->flags;
6013 klass->type_token = gklass->type_token;
6014 klass->field.count = gklass->field.count;
6016 klass->is_inflated = 1;
6017 klass->generic_class = gclass;
6019 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6020 klass->this_arg.type = klass->byval_arg.type;
6021 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6022 klass->this_arg.byref = TRUE;
6023 klass->enumtype = gklass->enumtype;
6024 klass->valuetype = gklass->valuetype;
6026 klass->cast_class = klass->element_class = klass;
6028 if (mono_class_is_nullable (klass))
6029 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6032 * We're not interested in the nested classes of a generic instance.
6033 * We use the generic type definition to look for nested classes.
6036 mono_generic_class_setup_parent (klass, gklass);
6038 if (gclass->is_dynamic) {
6040 * 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.
6041 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6042 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6044 if (!gklass->wastypebuilder)
6047 mono_class_setup_supertypes (klass);
6049 if (klass->enumtype) {
6051 * For enums, gklass->fields might not been set, but instance_size etc. is
6052 * already set in mono_reflection_create_internal_class (). For non-enums,
6053 * these will be computed normally in mono_class_layout_fields ().
6055 klass->instance_size = gklass->instance_size;
6056 klass->sizes.class_size = gklass->sizes.class_size;
6057 mono_memory_barrier ();
6058 klass->size_inited = 1;
6062 mono_memory_barrier ();
6063 gclass->cached_class = klass;
6065 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6067 inflated_classes ++;
6068 inflated_classes_size += sizeof (MonoClass);
6070 mono_loader_unlock ();
6076 get_image_for_container (MonoGenericContainer *container)
6079 if (container->is_anonymous) {
6080 result = container->owner.image;
6083 if (container->is_method) {
6084 MonoMethod *method = container->owner.method;
6085 g_assert_checked (method);
6086 klass = method->klass;
6088 klass = container->owner.klass;
6090 g_assert_checked (klass);
6091 result = klass->image;
6098 get_image_for_generic_param (MonoGenericParam *param)
6100 MonoGenericContainer *container = mono_generic_param_owner (param);
6101 g_assert_checked (container);
6102 return get_image_for_container (container);
6105 // Make a string in the designated image consisting of a single integer.
6106 #define INT_STRING_SIZE 16
6108 make_generic_name_string (MonoImage *image, int num)
6110 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6111 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6115 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6116 // pinfo is derived from param by the caller for us.
6118 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6120 MonoClass *klass, **ptr;
6122 MonoGenericContainer *container = mono_generic_param_owner (param);
6123 g_assert_checked (container);
6125 MonoImage *image = get_image_for_container (container);
6126 gboolean is_mvar = container->is_method;
6127 gboolean is_anonymous = container->is_anonymous;
6129 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6130 classes_size += sizeof (MonoClass);
6133 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6135 int n = mono_generic_param_num (param);
6136 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6140 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6141 } else if (is_mvar) {
6142 MonoMethod *omethod = container->owner.method;
6143 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6145 MonoClass *oklass = container->owner.klass;
6146 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6149 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6151 // Count non-NULL items in pinfo->constraints
6154 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6158 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6159 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6161 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6162 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6164 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6167 if (count - pos > 0) {
6168 klass->interface_count = count - pos;
6169 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6170 klass->interfaces_inited = TRUE;
6171 for (i = pos; i < count; i++)
6172 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6175 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6177 klass->inited = TRUE;
6178 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6179 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6180 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6182 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6183 klass->this_arg.type = klass->byval_arg.type;
6184 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6185 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6186 klass->this_arg.byref = TRUE;
6188 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6189 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6191 /*Init these fields to sane values*/
6192 klass->min_align = 1;
6194 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6195 * constrained to, the JIT depends on this.
6197 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6198 mono_memory_barrier ();
6199 klass->size_inited = 1;
6200 klass->setup_fields_called = 1;
6202 mono_class_setup_supertypes (klass);
6204 if (count - pos > 0) {
6205 mono_class_setup_vtable (klass->parent);
6206 if (mono_class_has_failure (klass->parent))
6207 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Failed to setup parent interfaces"));
6209 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6215 #define FAST_CACHE_SIZE 16
6218 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6219 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6220 * we cache the MonoClasses.
6221 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6222 * LOCKING: Takes the image lock depending on @take_lock.
6225 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6227 int n = mono_generic_param_num (param);
6228 MonoImage *image = get_image_for_generic_param (param);
6229 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6230 MonoClass *klass = NULL;
6235 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6236 // For high numbers or constraints we have to use pointer hashes.
6237 if (param->gshared_constraint) {
6238 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6241 mono_image_lock (image);
6242 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6244 mono_image_unlock (image);
6249 if (n < FAST_CACHE_SIZE) {
6251 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6253 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6255 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6258 mono_image_lock (image);
6259 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6261 mono_image_unlock (image);
6268 * LOCKING: Image lock (param->image) must be held
6271 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6273 int n = mono_generic_param_num (param);
6274 MonoImage *image = get_image_for_generic_param (param);
6275 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6279 if (param->gshared_constraint) {
6280 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6282 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6283 mono_memory_barrier ();
6285 image->mvar_cache_constrained = ht;
6287 image->var_cache_constrained = ht;
6289 g_hash_table_insert (ht, param, klass);
6290 } else if (n < FAST_CACHE_SIZE) {
6292 /* Requires locking to avoid droping an already published class */
6293 if (!image->mvar_cache_fast)
6294 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6295 image->mvar_cache_fast [n] = klass;
6297 if (!image->var_cache_fast)
6298 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6299 image->var_cache_fast [n] = klass;
6302 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6304 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6306 ht = g_hash_table_new (NULL, NULL);
6307 mono_memory_barrier ();
6309 image->mvar_cache_slow = ht;
6311 image->var_cache_slow = ht;
6314 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6319 * LOCKING: Acquires the image lock (@image).
6322 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6324 MonoImage *image = get_image_for_generic_param (param);
6325 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6326 MonoClass *klass, *klass2;
6328 // If a klass already exists for this object and is cached, return it.
6329 if (pinfo) // Non-anonymous
6330 klass = pinfo->pklass;
6332 klass = get_anon_gparam_class (param, TRUE);
6337 // Create a new klass
6338 klass = make_generic_param_class (param, pinfo);
6340 // Now we need to cache the klass we created.
6341 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6342 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6343 // and allow our newly-created klass object to just leak.
6344 mono_memory_barrier ();
6346 mono_image_lock (image);
6348 // Here "klass2" refers to the klass potentially created by the other thread.
6349 if (pinfo) // Repeat check from above
6350 klass2 = pinfo->pklass;
6352 klass2 = get_anon_gparam_class (param, FALSE);
6359 pinfo->pklass = klass;
6361 set_anon_gparam_class (param, klass);
6363 mono_image_unlock (image);
6365 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6367 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6369 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6375 * mono_class_from_generic_parameter:
6376 * @param: Parameter to find/construct a class for.
6377 * @arg2: Is ignored.
6378 * @arg3: Is ignored.
6381 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6383 return mono_class_from_generic_parameter_internal (param);
6388 mono_ptr_class_get (MonoType *type)
6391 MonoClass *el_class;
6395 el_class = mono_class_from_mono_type (type);
6396 image = el_class->image;
6398 mono_image_lock (image);
6399 if (image->ptr_cache) {
6400 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6401 mono_image_unlock (image);
6405 mono_image_unlock (image);
6407 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6409 classes_size += sizeof (MonoClass);
6411 result->parent = NULL; /* no parent for PTR types */
6412 result->name_space = el_class->name_space;
6413 name = g_strdup_printf ("%s*", el_class->name);
6414 result->name = mono_image_strdup (image, name);
6417 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6419 result->image = el_class->image;
6420 result->inited = TRUE;
6421 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6422 /* Can pointers get boxed? */
6423 result->instance_size = sizeof (gpointer);
6424 result->cast_class = result->element_class = el_class;
6425 result->blittable = TRUE;
6427 result->byval_arg.type = MONO_TYPE_PTR;
6428 result->this_arg.type = result->byval_arg.type;
6429 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6430 result->this_arg.byref = TRUE;
6432 mono_class_setup_supertypes (result);
6434 mono_image_lock (image);
6435 if (image->ptr_cache) {
6437 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6438 mono_image_unlock (image);
6439 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6443 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6445 g_hash_table_insert (image->ptr_cache, el_class, result);
6446 mono_image_unlock (image);
6448 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6454 mono_fnptr_class_get (MonoMethodSignature *sig)
6457 static GHashTable *ptr_hash = NULL;
6459 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6461 mono_loader_lock ();
6464 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6466 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6467 mono_loader_unlock ();
6470 result = g_new0 (MonoClass, 1);
6472 result->parent = NULL; /* no parent for PTR types */
6473 result->name_space = "System";
6474 result->name = "MonoFNPtrFakeClass";
6476 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6478 result->image = mono_defaults.corlib; /* need to fix... */
6479 result->inited = TRUE;
6480 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6481 /* Can pointers get boxed? */
6482 result->instance_size = sizeof (gpointer);
6483 result->cast_class = result->element_class = result;
6484 result->blittable = TRUE;
6486 result->byval_arg.type = MONO_TYPE_FNPTR;
6487 result->this_arg.type = result->byval_arg.type;
6488 result->this_arg.data.method = result->byval_arg.data.method = sig;
6489 result->this_arg.byref = TRUE;
6490 result->blittable = TRUE;
6492 mono_class_setup_supertypes (result);
6494 g_hash_table_insert (ptr_hash, sig, result);
6496 mono_loader_unlock ();
6498 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6504 * mono_class_from_mono_type:
6505 * @type: describes the type to return
6507 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6510 mono_class_from_mono_type (MonoType *type)
6512 switch (type->type) {
6513 case MONO_TYPE_OBJECT:
6514 return type->data.klass? type->data.klass: mono_defaults.object_class;
6515 case MONO_TYPE_VOID:
6516 return type->data.klass? type->data.klass: mono_defaults.void_class;
6517 case MONO_TYPE_BOOLEAN:
6518 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6519 case MONO_TYPE_CHAR:
6520 return type->data.klass? type->data.klass: mono_defaults.char_class;
6522 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6524 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6526 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6528 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6530 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6532 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6534 return type->data.klass? type->data.klass: mono_defaults.int_class;
6536 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6538 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6540 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6542 return type->data.klass? type->data.klass: mono_defaults.single_class;
6544 return type->data.klass? type->data.klass: mono_defaults.double_class;
6545 case MONO_TYPE_STRING:
6546 return type->data.klass? type->data.klass: mono_defaults.string_class;
6547 case MONO_TYPE_TYPEDBYREF:
6548 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6549 case MONO_TYPE_ARRAY:
6550 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6552 return mono_ptr_class_get (type->data.type);
6553 case MONO_TYPE_FNPTR:
6554 return mono_fnptr_class_get (type->data.method);
6555 case MONO_TYPE_SZARRAY:
6556 return mono_array_class_get (type->data.klass, 1);
6557 case MONO_TYPE_CLASS:
6558 case MONO_TYPE_VALUETYPE:
6559 return type->data.klass;
6560 case MONO_TYPE_GENERICINST:
6561 return mono_generic_class_get_class (type->data.generic_class);
6562 case MONO_TYPE_MVAR:
6564 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6566 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6567 g_assert_not_reached ();
6570 // Yes, this returns NULL, even if it is documented as not doing so, but there
6571 // is no way for the code to make it this far, due to the assert above.
6576 * mono_type_retrieve_from_typespec
6577 * @image: context where the image is created
6578 * @type_spec: typespec token
6579 * @context: the generic context used to evaluate generic instantiations in
6582 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6584 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6586 *did_inflate = FALSE;
6591 if (context && (context->class_inst || context->method_inst)) {
6592 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6594 if (!mono_error_ok (error)) {
6600 *did_inflate = TRUE;
6607 * mono_class_create_from_typespec
6608 * @image: context where the image is created
6609 * @type_spec: typespec token
6610 * @context: the generic context used to evaluate generic instantiations in
6613 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6616 gboolean inflated = FALSE;
6617 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6618 return_val_if_nok (error, NULL);
6619 ret = mono_class_from_mono_type (t);
6621 mono_metadata_free_type (t);
6626 * mono_bounded_array_class_get:
6627 * @element_class: element class
6628 * @rank: the dimension of the array class
6629 * @bounded: whenever the array has non-zero bounds
6631 * Returns: A class object describing the array with element type @element_type and
6635 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6639 MonoClass *parent = NULL;
6640 GSList *list, *rootlist = NULL;
6643 gboolean corlib_type = FALSE;
6645 g_assert (rank <= 255);
6648 /* bounded only matters for one-dimensional arrays */
6651 image = eclass->image;
6653 if (rank == 1 && !bounded) {
6655 * This case is very frequent not just during compilation because of calls
6656 * from mono_class_from_mono_type (), mono_array_new (),
6657 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6659 mono_os_mutex_lock (&image->szarray_cache_lock);
6660 if (!image->szarray_cache)
6661 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6662 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6663 mono_os_mutex_unlock (&image->szarray_cache_lock);
6667 mono_loader_lock ();
6669 mono_loader_lock ();
6671 if (!image->array_cache)
6672 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6674 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6675 for (; list; list = list->next) {
6676 klass = (MonoClass *)list->data;
6677 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6678 mono_loader_unlock ();
6685 /* for the building corlib use System.Array from it */
6686 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6687 parent = mono_class_load_from_name (image, "System", "Array");
6690 parent = mono_defaults.array_class;
6691 if (!parent->inited)
6692 mono_class_init (parent);
6695 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6697 klass->image = image;
6698 klass->name_space = eclass->name_space;
6699 nsize = strlen (eclass->name);
6700 name = (char *)g_malloc (nsize + 2 + rank + 1);
6701 memcpy (name, eclass->name, nsize);
6704 memset (name + nsize + 1, ',', rank - 1);
6706 name [nsize + rank] = '*';
6707 name [nsize + rank + bounded] = ']';
6708 name [nsize + rank + bounded + 1] = 0;
6709 klass->name = mono_image_strdup (image, name);
6712 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6714 classes_size += sizeof (MonoClass);
6716 klass->type_token = 0;
6717 /* all arrays are marked serializable and sealed, bug #42779 */
6718 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6719 klass->parent = parent;
6720 klass->instance_size = mono_class_instance_size (klass->parent);
6722 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6723 /*Arrays of those two types are invalid.*/
6724 mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL);
6725 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6726 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6727 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6728 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6730 /* element_size -1 is ok as this is not an instantitable type*/
6731 klass->sizes.element_size = -1;
6733 klass->sizes.element_size = mono_class_array_element_size (eclass);
6735 mono_class_setup_supertypes (klass);
6737 if (eclass->generic_class)
6738 mono_class_init (eclass);
6739 if (!eclass->size_inited)
6740 mono_class_setup_fields (eclass);
6741 if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6742 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6744 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6748 if (eclass->enumtype)
6749 klass->cast_class = eclass->element_class;
6751 klass->cast_class = eclass;
6753 switch (klass->cast_class->byval_arg.type) {
6755 klass->cast_class = mono_defaults.byte_class;
6758 klass->cast_class = mono_defaults.int16_class;
6761 #if SIZEOF_VOID_P == 4
6765 klass->cast_class = mono_defaults.int32_class;
6768 #if SIZEOF_VOID_P == 8
6772 klass->cast_class = mono_defaults.int64_class;
6778 klass->element_class = eclass;
6780 if ((rank > 1) || bounded) {
6781 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6782 klass->byval_arg.type = MONO_TYPE_ARRAY;
6783 klass->byval_arg.data.array = at;
6784 at->eklass = eclass;
6786 /* FIXME: complete.... */
6788 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6789 klass->byval_arg.data.klass = eclass;
6791 klass->this_arg = klass->byval_arg;
6792 klass->this_arg.byref = 1;
6797 klass->generic_container = eclass->generic_container;
6799 if (rank == 1 && !bounded) {
6800 MonoClass *prev_class;
6802 mono_os_mutex_lock (&image->szarray_cache_lock);
6803 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6805 /* Someone got in before us */
6808 g_hash_table_insert (image->szarray_cache, eclass, klass);
6809 mono_os_mutex_unlock (&image->szarray_cache_lock);
6811 list = g_slist_append (rootlist, klass);
6812 g_hash_table_insert (image->array_cache, eclass, list);
6815 mono_loader_unlock ();
6817 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6823 * mono_array_class_get:
6824 * @element_class: element class
6825 * @rank: the dimension of the array class
6827 * Returns: A class object describing the array with element type @element_type and
6831 mono_array_class_get (MonoClass *eclass, guint32 rank)
6833 return mono_bounded_array_class_get (eclass, rank, FALSE);
6837 * mono_class_instance_size:
6840 * Use to get the size of a class in bytes.
6842 * Returns: The size of an object instance
6845 mono_class_instance_size (MonoClass *klass)
6847 if (!klass->size_inited)
6848 mono_class_init (klass);
6850 return klass->instance_size;
6854 * mono_class_min_align:
6857 * Use to get the computed minimum alignment requirements for the specified class.
6859 * Returns: minimm alignment requirements
6862 mono_class_min_align (MonoClass *klass)
6864 if (!klass->size_inited)
6865 mono_class_init (klass);
6867 return klass->min_align;
6871 * mono_class_value_size:
6874 * This function is used for value types, and return the
6875 * space and the alignment to store that kind of value object.
6877 * Returns: the size of a value of kind @klass
6880 mono_class_value_size (MonoClass *klass, guint32 *align)
6884 /* fixme: check disable, because we still have external revereces to
6885 * mscorlib and Dummy Objects
6887 /*g_assert (klass->valuetype);*/
6889 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6892 *align = klass->min_align;
6898 * mono_class_data_size:
6901 * Returns: The size of the static class data
6904 mono_class_data_size (MonoClass *klass)
6907 mono_class_init (klass);
6908 /* This can happen with dynamically created types */
6909 if (!klass->fields_inited)
6910 mono_class_setup_fields_locking (klass);
6912 /* in arrays, sizes.class_size is unioned with element_size
6913 * and arrays have no static fields
6917 return klass->sizes.class_size;
6921 * Auxiliary routine to mono_class_get_field
6923 * Takes a field index instead of a field token.
6925 static MonoClassField *
6926 mono_class_get_field_idx (MonoClass *klass, int idx)
6928 mono_class_setup_fields_locking (klass);
6929 if (mono_class_has_failure (klass))
6933 if (klass->image->uncompressed_metadata) {
6935 * klass->field.first points to the FieldPtr table, while idx points into the
6936 * Field table, so we have to do a search.
6938 /*FIXME this is broken for types with multiple fields with the same name.*/
6939 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6942 for (i = 0; i < klass->field.count; ++i)
6943 if (mono_field_get_name (&klass->fields [i]) == name)
6944 return &klass->fields [i];
6945 g_assert_not_reached ();
6947 if (klass->field.count) {
6948 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6949 return &klass->fields [idx - klass->field.first];
6953 klass = klass->parent;
6959 * mono_class_get_field:
6960 * @class: the class to lookup the field.
6961 * @field_token: the field token
6963 * Returns: A MonoClassField representing the type and offset of
6964 * the field, or a NULL value if the field does not belong to this
6968 mono_class_get_field (MonoClass *klass, guint32 field_token)
6970 int idx = mono_metadata_token_index (field_token);
6972 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6974 return mono_class_get_field_idx (klass, idx - 1);
6978 * mono_class_get_field_from_name:
6979 * @klass: the class to lookup the field.
6980 * @name: the field name
6982 * Search the class @klass and it's parents for a field with the name @name.
6984 * Returns: The MonoClassField pointer of the named field or NULL
6987 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6989 return mono_class_get_field_from_name_full (klass, name, NULL);
6993 * mono_class_get_field_from_name_full:
6994 * @klass: the class to lookup the field.
6995 * @name: the field name
6996 * @type: the type of the fields. This optional.
6998 * Search the class @klass and it's parents for a field with the name @name and type @type.
7000 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7001 * of its generic type definition.
7003 * Returns: The MonoClassField pointer of the named field or NULL
7006 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7010 mono_class_setup_fields_locking (klass);
7011 if (mono_class_has_failure (klass))
7015 for (i = 0; i < klass->field.count; ++i) {
7016 MonoClassField *field = &klass->fields [i];
7018 if (strcmp (name, mono_field_get_name (field)) != 0)
7022 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7023 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7028 klass = klass->parent;
7034 * mono_class_get_field_token:
7035 * @field: the field we need the token of
7037 * Get the token of a field. Note that the tokesn is only valid for the image
7038 * the field was loaded from. Don't use this function for fields in dynamic types.
7040 * Returns: The token representing the field in the image it was loaded from.
7043 mono_class_get_field_token (MonoClassField *field)
7045 MonoClass *klass = field->parent;
7048 mono_class_setup_fields_locking (klass);
7053 for (i = 0; i < klass->field.count; ++i) {
7054 if (&klass->fields [i] == field) {
7055 int idx = klass->field.first + i + 1;
7057 if (klass->image->uncompressed_metadata)
7058 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7059 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7062 klass = klass->parent;
7065 g_assert_not_reached ();
7070 mono_field_get_index (MonoClassField *field)
7072 int index = field - field->parent->fields;
7074 g_assert (index >= 0 && index < field->parent->field.count);
7080 * mono_class_get_field_default_value:
7082 * Return the default value of the field as a pointer into the metadata blob.
7085 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7088 guint32 constant_cols [MONO_CONSTANT_SIZE];
7090 MonoClass *klass = field->parent;
7092 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7094 if (!klass->ext || !klass->ext->field_def_values) {
7095 MonoFieldDefaultValue *def_values;
7097 mono_class_alloc_ext (klass);
7099 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7101 mono_image_lock (klass->image);
7102 mono_memory_barrier ();
7103 if (!klass->ext->field_def_values)
7104 klass->ext->field_def_values = def_values;
7105 mono_image_unlock (klass->image);
7108 field_index = mono_field_get_index (field);
7110 if (!klass->ext->field_def_values [field_index].data) {
7111 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7115 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7117 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7118 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7119 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7122 *def_type = klass->ext->field_def_values [field_index].def_type;
7123 return klass->ext->field_def_values [field_index].data;
7127 mono_property_get_index (MonoProperty *prop)
7129 int index = prop - prop->parent->ext->properties;
7131 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7137 * mono_class_get_property_default_value:
7139 * Return the default value of the field as a pointer into the metadata blob.
7142 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7145 guint32 constant_cols [MONO_CONSTANT_SIZE];
7146 MonoClass *klass = property->parent;
7148 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7150 * We don't cache here because it is not used by C# so it's quite rare, but
7151 * we still do the lookup in klass->ext because that is where the data
7152 * is stored for dynamic assemblies.
7155 if (image_is_dynamic (klass->image)) {
7156 int prop_index = mono_property_get_index (property);
7157 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7158 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7159 return klass->ext->prop_def_values [prop_index].data;
7163 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7167 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7168 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7169 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7173 mono_class_get_event_token (MonoEvent *event)
7175 MonoClass *klass = event->parent;
7180 for (i = 0; i < klass->ext->event.count; ++i) {
7181 if (&klass->ext->events [i] == event)
7182 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7185 klass = klass->parent;
7188 g_assert_not_reached ();
7193 * mono_class_get_property_from_name:
7195 * @name: name of the property to lookup in the specified class
7197 * Use this method to lookup a property in a class
7198 * Returns: the MonoProperty with the given name, or NULL if the property
7199 * does not exist on the @klass.
7202 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7206 gpointer iter = NULL;
7207 while ((p = mono_class_get_properties (klass, &iter))) {
7208 if (! strcmp (name, p->name))
7211 klass = klass->parent;
7217 * mono_class_get_property_token:
7218 * @prop: MonoProperty to query
7220 * Returns: The ECMA token for the specified property.
7223 mono_class_get_property_token (MonoProperty *prop)
7225 MonoClass *klass = prop->parent;
7229 gpointer iter = NULL;
7230 while ((p = mono_class_get_properties (klass, &iter))) {
7231 if (&klass->ext->properties [i] == prop)
7232 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7236 klass = klass->parent;
7239 g_assert_not_reached ();
7244 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7246 const char *name, *nspace;
7247 if (image_is_dynamic (image))
7248 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7250 switch (type_token & 0xff000000){
7251 case MONO_TOKEN_TYPE_DEF: {
7252 guint32 cols [MONO_TYPEDEF_SIZE];
7253 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7254 guint tidx = mono_metadata_token_index (type_token);
7256 if (tidx > tt->rows)
7257 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7259 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7260 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7261 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7262 if (strlen (nspace) == 0)
7263 return g_strdup_printf ("%s", name);
7265 return g_strdup_printf ("%s.%s", nspace, name);
7268 case MONO_TOKEN_TYPE_REF: {
7270 guint32 cols [MONO_TYPEREF_SIZE];
7271 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7272 guint tidx = mono_metadata_token_index (type_token);
7275 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7277 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7278 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7279 mono_error_cleanup (&error);
7283 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7284 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7285 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7286 if (strlen (nspace) == 0)
7287 return g_strdup_printf ("%s", name);
7289 return g_strdup_printf ("%s.%s", nspace, name);
7292 case MONO_TOKEN_TYPE_SPEC:
7293 return g_strdup_printf ("Typespec 0x%08x", type_token);
7295 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7300 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7302 if (image_is_dynamic (image))
7303 return g_strdup_printf ("DynamicAssembly %s", image->name);
7305 switch (type_token & 0xff000000){
7306 case MONO_TOKEN_TYPE_DEF:
7307 if (image->assembly)
7308 return mono_stringify_assembly_name (&image->assembly->aname);
7309 else if (image->assembly_name)
7310 return g_strdup (image->assembly_name);
7311 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7312 case MONO_TOKEN_TYPE_REF: {
7314 MonoAssemblyName aname;
7315 guint32 cols [MONO_TYPEREF_SIZE];
7316 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7317 guint32 idx = mono_metadata_token_index (type_token);
7320 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7322 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7323 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7324 mono_error_cleanup (&error);
7327 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7329 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7330 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7331 case MONO_RESOLUTION_SCOPE_MODULE:
7333 return g_strdup ("");
7334 case MONO_RESOLUTION_SCOPE_MODULEREF:
7336 return g_strdup ("");
7337 case MONO_RESOLUTION_SCOPE_TYPEREF:
7339 return g_strdup ("");
7340 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7341 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7342 return mono_stringify_assembly_name (&aname);
7344 g_assert_not_reached ();
7348 case MONO_TOKEN_TYPE_SPEC:
7350 return g_strdup ("");
7352 g_assert_not_reached ();
7359 * mono_class_get_full:
7360 * @image: the image where the class resides
7361 * @type_token: the token for the class
7362 * @context: the generic context used to evaluate generic instantiations in
7363 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7365 * Returns: The MonoClass that represents @type_token in @image
7368 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7372 klass = mono_class_get_checked (image, type_token, &error);
7374 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7375 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7377 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7383 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7387 mono_error_init (error);
7388 klass = mono_class_get_checked (image, type_token, error);
7390 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7391 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7396 * mono_class_get_checked:
7397 * @image: the image where the class resides
7398 * @type_token: the token for the class
7399 * @error: error object to return any error
7401 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7404 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7406 MonoClass *klass = NULL;
7408 mono_error_init (error);
7410 if (image_is_dynamic (image)) {
7411 int table = mono_metadata_token_table (type_token);
7413 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7414 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7417 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7421 switch (type_token & 0xff000000){
7422 case MONO_TOKEN_TYPE_DEF:
7423 klass = mono_class_create_from_typedef (image, type_token, error);
7425 case MONO_TOKEN_TYPE_REF:
7426 klass = mono_class_from_typeref_checked (image, type_token, error);
7428 case MONO_TOKEN_TYPE_SPEC:
7429 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7432 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7436 /* Generic case, should be avoided for when a better error is possible. */
7437 if (!klass && mono_error_ok (error)) {
7438 char *name = mono_class_name_from_token (image, type_token);
7439 char *assembly = mono_assembly_name_from_token (image, type_token);
7440 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7448 * mono_type_get_checked:
7449 * @image: the image where the type resides
7450 * @type_token: the token for the type
7451 * @context: the generic context used to evaluate generic instantiations in
7452 * @error: Error handling context
7454 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7456 * Returns: The MonoType that represents @type_token in @image
7459 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7461 MonoType *type = NULL;
7462 gboolean inflated = FALSE;
7464 mono_error_init (error);
7466 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7467 if (image_is_dynamic (image)) {
7468 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7469 return_val_if_nok (error, NULL);
7470 return mono_class_get_type (klass);
7473 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7474 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7481 return mono_class_get_type (klass);
7484 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7491 MonoType *tmp = type;
7492 type = mono_class_get_type (mono_class_from_mono_type (type));
7493 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7494 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7495 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7497 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7499 if (type->type != tmp->type)
7502 mono_metadata_free_type (tmp);
7509 * @image: image where the class token will be looked up.
7510 * @type_token: a type token from the image
7512 * Returns the MonoClass with the given @type_token on the @image
7515 mono_class_get (MonoImage *image, guint32 type_token)
7517 return mono_class_get_full (image, type_token, NULL);
7521 * mono_image_init_name_cache:
7523 * Initializes the class name cache stored in image->name_cache.
7525 * LOCKING: Acquires the corresponding image lock.
7528 mono_image_init_name_cache (MonoImage *image)
7530 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7531 guint32 cols [MONO_TYPEDEF_SIZE];
7534 guint32 i, visib, nspace_index;
7535 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7537 if (image->name_cache)
7540 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7542 if (image_is_dynamic (image)) {
7543 mono_image_lock (image);
7544 if (image->name_cache) {
7545 /* Somebody initialized it before us */
7546 g_hash_table_destroy (the_name_cache);
7548 mono_atomic_store_release (&image->name_cache, the_name_cache);
7550 mono_image_unlock (image);
7554 /* Temporary hash table to avoid lookups in the nspace_table */
7555 name_cache2 = g_hash_table_new (NULL, NULL);
7557 for (i = 1; i <= t->rows; ++i) {
7558 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7559 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7561 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7562 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7564 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7566 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7567 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7569 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7570 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7571 if (!nspace_table) {
7572 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7573 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7574 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7577 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7580 /* Load type names from EXPORTEDTYPES table */
7582 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7583 guint32 cols [MONO_EXP_TYPE_SIZE];
7586 for (i = 0; i < t->rows; ++i) {
7587 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7589 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7590 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7594 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7595 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7597 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7598 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7599 if (!nspace_table) {
7600 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7601 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7602 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7605 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7609 g_hash_table_destroy (name_cache2);
7611 mono_image_lock (image);
7612 if (image->name_cache) {
7613 /* Somebody initialized it before us */
7614 g_hash_table_destroy (the_name_cache);
7616 mono_atomic_store_release (&image->name_cache, the_name_cache);
7618 mono_image_unlock (image);
7621 /*FIXME Only dynamic assemblies should allow this operation.*/
7623 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7624 const char *name, guint32 index)
7626 GHashTable *nspace_table;
7627 GHashTable *name_cache;
7630 mono_image_init_name_cache (image);
7631 mono_image_lock (image);
7633 name_cache = image->name_cache;
7634 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7635 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7636 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7639 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7640 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7642 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7644 mono_image_unlock (image);
7653 find_nocase (gpointer key, gpointer value, gpointer user_data)
7655 char *name = (char*)key;
7656 FindUserData *data = (FindUserData*)user_data;
7658 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7659 data->value = value;
7663 * mono_class_from_name_case:
7664 * @image: The MonoImage where the type is looked up in
7665 * @name_space: the type namespace
7666 * @name: the type short name.
7667 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7669 * Obtains a MonoClass with a given namespace and a given name which
7670 * is located in the given MonoImage. The namespace and name
7671 * lookups are case insensitive.
7674 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7677 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7678 mono_error_cleanup (&error);
7684 * mono_class_from_name_case:
7685 * @image: The MonoImage where the type is looked up in
7686 * @name_space: the type namespace
7687 * @name: the type short name.
7690 * Obtains a MonoClass with a given namespace and a given name which
7691 * is located in the given MonoImage. The namespace and name
7692 * lookups are case insensitive.
7694 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7695 * was not found. The @error object will contain information about the problem
7699 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7701 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7702 guint32 cols [MONO_TYPEDEF_SIZE];
7707 mono_error_init (error);
7709 if (image_is_dynamic (image)) {
7711 FindUserData user_data;
7713 mono_image_init_name_cache (image);
7714 mono_image_lock (image);
7716 user_data.key = name_space;
7717 user_data.value = NULL;
7718 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7720 if (user_data.value) {
7721 GHashTable *nspace_table = (GHashTable*)user_data.value;
7723 user_data.key = name;
7724 user_data.value = NULL;
7726 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7728 if (user_data.value)
7729 token = GPOINTER_TO_UINT (user_data.value);
7732 mono_image_unlock (image);
7735 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7741 /* add a cache if needed */
7742 for (i = 1; i <= t->rows; ++i) {
7743 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7744 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7746 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7747 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7749 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7751 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7752 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7753 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7754 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7760 return_nested_in (MonoClass *klass, char *nested)
7763 char *s = strchr (nested, '/');
7764 gpointer iter = NULL;
7771 while ((found = mono_class_get_nested_types (klass, &iter))) {
7772 if (strcmp (found->name, nested) == 0) {
7774 return return_nested_in (found, s);
7782 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7784 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7785 MonoImage *file_image;
7789 mono_error_init (error);
7792 * The EXPORTEDTYPES table only contains public types, so have to search the
7794 * Note: image->modules contains the contents of the MODULEREF table, while
7795 * the real module list is in the FILE table.
7797 for (i = 0; i < file_table->rows; i++) {
7798 guint32 cols [MONO_FILE_SIZE];
7799 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7800 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7803 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7805 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7806 if (klass || !is_ok (error))
7815 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7817 GHashTable *nspace_table;
7818 MonoImage *loaded_image;
7825 mono_error_init (error);
7827 // Checking visited images avoids stack overflows when cyclic references exist.
7828 if (g_hash_table_lookup (visited_images, image))
7831 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7833 if ((nested = strchr (name, '/'))) {
7834 int pos = nested - name;
7835 int len = strlen (name);
7838 memcpy (buf, name, len + 1);
7840 nested = buf + pos + 1;
7844 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7845 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7846 gboolean res = get_class_from_name (image, name_space, name, &klass);
7849 klass = search_modules (image, name_space, name, error);
7854 return klass ? return_nested_in (klass, nested) : NULL;
7860 mono_image_init_name_cache (image);
7861 mono_image_lock (image);
7863 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7866 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7868 mono_image_unlock (image);
7870 if (!token && image_is_dynamic (image) && image->modules) {
7871 /* Search modules as well */
7872 for (i = 0; i < image->module_count; ++i) {
7873 MonoImage *module = image->modules [i];
7875 klass = mono_class_from_name_checked (module, name_space, name, error);
7876 if (klass || !is_ok (error))
7882 klass = search_modules (image, name_space, name, error);
7883 if (klass || !is_ok (error))
7888 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7889 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7890 guint32 cols [MONO_EXP_TYPE_SIZE];
7893 idx = mono_metadata_token_index (token);
7895 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7897 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7898 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7899 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7902 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7904 return klass ? return_nested_in (klass, nested) : NULL;
7906 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7907 guint32 assembly_idx;
7909 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7911 mono_assembly_load_reference (image, assembly_idx - 1);
7912 g_assert (image->references [assembly_idx - 1]);
7913 if (image->references [assembly_idx - 1] == (gpointer)-1)
7915 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7917 return klass ? return_nested_in (klass, nested) : NULL;
7920 g_assert_not_reached ();
7924 token = MONO_TOKEN_TYPE_DEF | token;
7926 klass = mono_class_get_checked (image, token, error);
7928 return return_nested_in (klass, nested);
7933 * mono_class_from_name_checked:
7934 * @image: The MonoImage where the type is looked up in
7935 * @name_space: the type namespace
7936 * @name: the type short name.
7938 * Obtains a MonoClass with a given namespace and a given name which
7939 * is located in the given MonoImage.
7941 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7942 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7945 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7948 GHashTable *visited_images;
7950 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7952 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7954 g_hash_table_destroy (visited_images);
7960 * mono_class_from_name:
7961 * @image: The MonoImage where the type is looked up in
7962 * @name_space: the type namespace
7963 * @name: the type short name.
7965 * Obtains a MonoClass with a given namespace and a given name which
7966 * is located in the given MonoImage.
7968 * To reference nested classes, use the "/" character as a separator.
7969 * For example use "Foo/Bar" to reference the class Bar that is nested
7970 * inside Foo, like this: "class Foo { class Bar {} }".
7973 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7978 klass = mono_class_from_name_checked (image, name_space, name, &error);
7979 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7985 * mono_class_load_from_name:
7986 * @image: The MonoImage where the type is looked up in
7987 * @name_space: the type namespace
7988 * @name: the type short name.
7990 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7991 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7992 * If they are missing. Thing of System.Object or System.String.
7995 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8000 klass = mono_class_from_name_checked (image, name_space, name, &error);
8002 g_error ("Runtime critical type %s.%s not found", name_space, name);
8003 if (!mono_error_ok (&error))
8004 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8009 * mono_class_try_load_from_name:
8010 * @image: The MonoImage where the type is looked up in
8011 * @name_space: the type namespace
8012 * @name: the type short name.
8014 * This function tries to load a type, returning the class was found or NULL otherwise.
8015 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8017 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8018 * a type that we would otherwise assume to be available but was not due some error.
8022 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8027 klass = mono_class_from_name_checked (image, name_space, name, &error);
8028 if (!mono_error_ok (&error))
8029 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8035 * mono_class_is_subclass_of:
8036 * @klass: class to probe if it is a subclass of another one
8037 * @klassc: the class we suspect is the base class
8038 * @check_interfaces: whether we should perform interface checks
8040 * This method determines whether @klass is a subclass of @klassc.
8042 * If the @check_interfaces flag is set, then if @klassc is an interface
8043 * this method return TRUE if the @klass implements the interface or
8044 * if @klass is an interface, if one of its base classes is @klass.
8046 * If @check_interfaces is false then, then if @klass is not an interface
8047 * then it returns TRUE if the @klass is a subclass of @klassc.
8049 * if @klass is an interface and @klassc is System.Object, then this function
8054 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8055 gboolean check_interfaces)
8057 /* FIXME test for interfaces with variant generic arguments */
8058 mono_class_init (klass);
8059 mono_class_init (klassc);
8061 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8062 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8064 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8067 for (i = 0; i < klass->interface_count; i ++) {
8068 MonoClass *ic = klass->interfaces [i];
8073 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8078 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8081 if (klassc == mono_defaults.object_class)
8088 mono_type_is_generic_argument (MonoType *type)
8090 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8094 mono_class_has_variant_generic_params (MonoClass *klass)
8097 MonoGenericContainer *container;
8099 if (!klass->generic_class)
8102 container = klass->generic_class->container_class->generic_container;
8104 for (i = 0; i < container->type_argc; ++i)
8105 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8112 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8114 if (target == candidate)
8117 if (check_for_reference_conv &&
8118 mono_type_is_generic_argument (&target->byval_arg) &&
8119 mono_type_is_generic_argument (&candidate->byval_arg)) {
8120 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8121 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8123 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8126 if (!mono_class_is_assignable_from (target, candidate))
8132 * @container the generic container from the GTD
8133 * @klass: the class to be assigned to
8134 * @oklass: the source class
8136 * Both @klass and @oklass must be instances of the same generic interface.
8138 * Returns: TRUE if @klass can be assigned to a @klass variable
8141 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8144 MonoType **klass_argv, **oklass_argv;
8145 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8146 MonoGenericContainer *container = klass_gtd->generic_container;
8148 if (klass == oklass)
8151 /*Viable candidates are instances of the same generic interface*/
8152 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8155 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8156 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8158 for (j = 0; j < container->type_argc; ++j) {
8159 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8160 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8162 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8166 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8167 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8169 if (param1_class != param2_class) {
8170 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8171 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8173 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8174 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8184 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8186 MonoGenericParam *gparam, *ogparam;
8187 MonoGenericParamInfo *tinfo, *cinfo;
8188 MonoClass **candidate_class;
8189 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8192 if (target == candidate)
8194 if (target->byval_arg.type != candidate->byval_arg.type)
8197 gparam = target->byval_arg.data.generic_param;
8198 ogparam = candidate->byval_arg.data.generic_param;
8199 tinfo = mono_generic_param_info (gparam);
8200 cinfo = mono_generic_param_info (ogparam);
8202 class_constraint_satisfied = FALSE;
8203 valuetype_constraint_satisfied = FALSE;
8205 /*candidate must have a super set of target's special constraints*/
8206 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8207 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8209 if (cinfo->constraints) {
8210 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8211 MonoClass *cc = *candidate_class;
8213 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8214 class_constraint_satisfied = TRUE;
8215 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8216 valuetype_constraint_satisfied = TRUE;
8219 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8220 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8222 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8224 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8226 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8227 valuetype_constraint_satisfied)) {
8232 /*candidate type constraints must be a superset of target's*/
8233 if (tinfo->constraints) {
8234 MonoClass **target_class;
8235 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8236 MonoClass *tc = *target_class;
8239 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8240 * check it's constraints since it satisfy the constraint by itself.
8242 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8245 if (!cinfo->constraints)
8248 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8249 MonoClass *cc = *candidate_class;
8251 if (mono_class_is_assignable_from (tc, cc))
8255 * This happens when we have the following:
8257 * Bar<K> where K : IFace
8258 * Foo<T, U> where T : U where U : IFace
8260 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8263 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8264 if (mono_gparam_is_assignable_from (target, cc))
8268 if (!*candidate_class)
8273 /*candidate itself must have a constraint that satisfy target*/
8274 if (cinfo->constraints) {
8275 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8276 MonoClass *cc = *candidate_class;
8277 if (mono_class_is_assignable_from (target, cc))
8285 * mono_class_is_assignable_from:
8286 * @klass: the class to be assigned to
8287 * @oklass: the source class
8289 * Returns: TRUE if an instance of object oklass can be assigned to an
8290 * instance of object @klass
8293 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8296 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8298 mono_class_init (klass);
8300 if (!oklass->inited)
8301 mono_class_init (oklass);
8303 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8306 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8307 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8309 return mono_gparam_is_assignable_from (klass, oklass);
8312 if (MONO_CLASS_IS_INTERFACE (klass)) {
8313 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8314 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8315 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8319 for (i = 0; constraints [i]; ++i) {
8320 if (mono_class_is_assignable_from (klass, constraints [i]))
8328 /* interface_offsets might not be set for dynamic classes */
8329 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8331 * oklass might be a generic type parameter but they have
8332 * interface_offsets set.
8334 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8335 if (!is_ok (&error)) {
8336 mono_error_cleanup (&error);
8341 if (!oklass->interface_bitmap)
8342 /* Happens with generic instances of not-yet created dynamic types */
8344 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8347 if (mono_class_has_variant_generic_params (klass)) {
8349 mono_class_setup_interfaces (oklass, &error);
8350 if (!mono_error_ok (&error)) {
8351 mono_error_cleanup (&error);
8355 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8356 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8357 MonoClass *iface = oklass->interfaces_packed [i];
8359 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8364 } else if (klass->delegate) {
8365 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8367 }else if (klass->rank) {
8368 MonoClass *eclass, *eoclass;
8370 if (oklass->rank != klass->rank)
8373 /* vectors vs. one dimensional arrays */
8374 if (oklass->byval_arg.type != klass->byval_arg.type)
8377 eclass = klass->cast_class;
8378 eoclass = oklass->cast_class;
8381 * a is b does not imply a[] is b[] when a is a valuetype, and
8382 * b is a reference type.
8385 if (eoclass->valuetype) {
8386 if ((eclass == mono_defaults.enum_class) ||
8387 (eclass == mono_defaults.enum_class->parent) ||
8388 (eclass == mono_defaults.object_class))
8392 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8393 } else if (mono_class_is_nullable (klass)) {
8394 if (mono_class_is_nullable (oklass))
8395 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8397 return mono_class_is_assignable_from (klass->cast_class, oklass);
8398 } else if (klass == mono_defaults.object_class)
8401 return mono_class_has_parent (oklass, klass);
8404 /*Check if @oklass is variant compatible with @klass.*/
8406 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8409 MonoType **klass_argv, **oklass_argv;
8410 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8411 MonoGenericContainer *container = klass_gtd->generic_container;
8413 /*Viable candidates are instances of the same generic interface*/
8414 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8417 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8418 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8420 for (j = 0; j < container->type_argc; ++j) {
8421 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8422 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8424 if (param1_class->valuetype != param2_class->valuetype)
8428 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8429 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8431 if (param1_class != param2_class) {
8432 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8433 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8435 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8436 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8444 /*Check if @candidate implements the interface @target*/
8446 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8450 gboolean is_variant = mono_class_has_variant_generic_params (target);
8452 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8453 if (mono_class_is_variant_compatible_slow (target, candidate))
8458 if (candidate == target)
8461 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8462 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8463 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8465 if (tb && tb->interfaces) {
8466 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8467 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8468 MonoClass *iface_class;
8470 /* we can't realize the type here since it can do pretty much anything. */
8473 iface_class = mono_class_from_mono_type (iface->type);
8474 if (iface_class == target)
8476 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8478 if (mono_class_implement_interface_slow (target, iface_class))
8483 /*setup_interfaces don't mono_class_init anything*/
8484 /*FIXME this doesn't handle primitive type arrays.
8485 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8486 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8488 mono_class_setup_interfaces (candidate, &error);
8489 if (!mono_error_ok (&error)) {
8490 mono_error_cleanup (&error);
8494 for (i = 0; i < candidate->interface_count; ++i) {
8495 if (candidate->interfaces [i] == target)
8498 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8501 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8505 candidate = candidate->parent;
8506 } while (candidate);
8512 * Check if @oklass can be assigned to @klass.
8513 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8516 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8518 if (candidate == target)
8520 if (target == mono_defaults.object_class)
8523 if (mono_class_has_parent (candidate, target))
8526 /*If target is not an interface there is no need to check them.*/
8527 if (MONO_CLASS_IS_INTERFACE (target))
8528 return mono_class_implement_interface_slow (target, candidate);
8530 if (target->delegate && mono_class_has_variant_generic_params (target))
8531 return mono_class_is_variant_compatible (target, candidate, FALSE);
8534 MonoClass *eclass, *eoclass;
8536 if (target->rank != candidate->rank)
8539 /* vectors vs. one dimensional arrays */
8540 if (target->byval_arg.type != candidate->byval_arg.type)
8543 eclass = target->cast_class;
8544 eoclass = candidate->cast_class;
8547 * a is b does not imply a[] is b[] when a is a valuetype, and
8548 * b is a reference type.
8551 if (eoclass->valuetype) {
8552 if ((eclass == mono_defaults.enum_class) ||
8553 (eclass == mono_defaults.enum_class->parent) ||
8554 (eclass == mono_defaults.object_class))
8558 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8560 /*FIXME properly handle nullables */
8561 /*FIXME properly handle (M)VAR */
8566 * mono_class_get_cctor:
8567 * @klass: A MonoClass pointer
8569 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8572 mono_class_get_cctor (MonoClass *klass)
8574 MonoCachedClassInfo cached_info;
8576 if (image_is_dynamic (klass->image)) {
8578 * has_cctor is not set for these classes because mono_class_init () is
8581 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8584 if (!klass->has_cctor)
8587 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8589 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8590 if (!mono_error_ok (&error))
8591 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8595 if (klass->generic_class && !klass->methods)
8596 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8598 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8602 * mono_class_get_finalizer:
8603 * @klass: The MonoClass pointer
8605 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8608 mono_class_get_finalizer (MonoClass *klass)
8610 MonoCachedClassInfo cached_info;
8613 mono_class_init (klass);
8614 if (!mono_class_has_finalizer (klass))
8617 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8619 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8620 if (!mono_error_ok (&error))
8621 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8624 mono_class_setup_vtable (klass);
8625 return klass->vtable [finalize_slot];
8630 * mono_class_needs_cctor_run:
8631 * @klass: the MonoClass pointer
8632 * @caller: a MonoMethod describing the caller
8634 * Determines whenever the class has a static constructor and whenever it
8635 * needs to be called when executing CALLER.
8638 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8642 method = mono_class_get_cctor (klass);
8644 return (method == caller) ? FALSE : TRUE;
8650 * mono_class_array_element_size:
8653 * Returns: The number of bytes an element of type @klass
8654 * uses when stored into an array.
8657 mono_class_array_element_size (MonoClass *klass)
8659 MonoType *type = &klass->byval_arg;
8662 switch (type->type) {
8665 case MONO_TYPE_BOOLEAN:
8669 case MONO_TYPE_CHAR:
8678 case MONO_TYPE_CLASS:
8679 case MONO_TYPE_STRING:
8680 case MONO_TYPE_OBJECT:
8681 case MONO_TYPE_SZARRAY:
8682 case MONO_TYPE_ARRAY:
8683 return sizeof (gpointer);
8688 case MONO_TYPE_VALUETYPE:
8689 if (type->data.klass->enumtype) {
8690 type = mono_class_enum_basetype (type->data.klass);
8691 klass = klass->element_class;
8694 return mono_class_instance_size (klass) - sizeof (MonoObject);
8695 case MONO_TYPE_GENERICINST:
8696 type = &type->data.generic_class->container_class->byval_arg;
8699 case MONO_TYPE_MVAR: {
8702 return mono_type_size (type, &align);
8704 case MONO_TYPE_VOID:
8708 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8714 * mono_array_element_size:
8715 * @ac: pointer to a #MonoArrayClass
8717 * Returns: The size of single array element.
8720 mono_array_element_size (MonoClass *ac)
8722 g_assert (ac->rank);
8723 return ac->sizes.element_size;
8727 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8728 MonoGenericContext *context)
8731 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8732 g_assert (mono_error_ok (&error));
8737 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8738 MonoGenericContext *context, MonoError *error)
8740 mono_error_init (error);
8742 if (image_is_dynamic (image)) {
8743 MonoClass *tmp_handle_class;
8744 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8746 mono_error_assert_ok (error);
8747 g_assert (tmp_handle_class);
8749 *handle_class = tmp_handle_class;
8751 if (tmp_handle_class == mono_defaults.typehandle_class)
8752 return &((MonoClass*)obj)->byval_arg;
8757 switch (token & 0xff000000) {
8758 case MONO_TOKEN_TYPE_DEF:
8759 case MONO_TOKEN_TYPE_REF:
8760 case MONO_TOKEN_TYPE_SPEC: {
8763 *handle_class = mono_defaults.typehandle_class;
8764 type = mono_type_get_checked (image, token, context, error);
8768 mono_class_init (mono_class_from_mono_type (type));
8769 /* We return a MonoType* as handle */
8772 case MONO_TOKEN_FIELD_DEF: {
8774 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8776 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8780 *handle_class = mono_defaults.fieldhandle_class;
8781 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8785 mono_class_init (klass);
8786 return mono_class_get_field (klass, token);
8788 case MONO_TOKEN_METHOD_DEF:
8789 case MONO_TOKEN_METHOD_SPEC: {
8791 meth = mono_get_method_checked (image, token, NULL, context, error);
8793 *handle_class = mono_defaults.methodhandle_class;
8799 case MONO_TOKEN_MEMBER_REF: {
8800 guint32 cols [MONO_MEMBERREF_SIZE];
8802 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8803 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8804 mono_metadata_decode_blob_size (sig, &sig);
8805 if (*sig == 0x6) { /* it's a field */
8807 MonoClassField *field;
8808 field = mono_field_from_token_checked (image, token, &klass, context, error);
8810 *handle_class = mono_defaults.fieldhandle_class;
8814 meth = mono_get_method_checked (image, token, NULL, context, error);
8816 *handle_class = mono_defaults.methodhandle_class;
8821 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8827 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8829 MonoClass *handle_class;
8830 mono_error_init (error);
8831 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8835 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8837 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8840 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8843 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8845 get_cached_class_info = func;
8849 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8851 if (!get_cached_class_info)
8854 return get_cached_class_info (klass, res);
8858 mono_install_get_class_from_name (MonoGetClassFromName func)
8860 get_class_from_name = func;
8864 * mono_class_get_image:
8866 * Use this method to get the `MonoImage*` where this class came from.
8868 * Returns: The image where this class is defined.
8871 mono_class_get_image (MonoClass *klass)
8873 return klass->image;
8877 * mono_class_get_element_class:
8878 * @klass: the MonoClass to act on
8880 * Use this function to get the element class of an array.
8882 * Returns: The element class of an array.
8885 mono_class_get_element_class (MonoClass *klass)
8887 return klass->element_class;
8891 * mono_class_is_valuetype:
8892 * @klass: the MonoClass to act on
8894 * Use this method to determine if the provided `MonoClass*` represents a value type,
8895 * or a reference type.
8897 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8900 mono_class_is_valuetype (MonoClass *klass)
8902 return klass->valuetype;
8906 * mono_class_is_enum:
8907 * @klass: the MonoClass to act on
8909 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8911 * Returns: TRUE if the MonoClass represents an enumeration.
8914 mono_class_is_enum (MonoClass *klass)
8916 return klass->enumtype;
8920 * mono_class_enum_basetype:
8921 * @klass: the MonoClass to act on
8923 * Use this function to get the underlying type for an enumeration value.
8925 * Returns: The underlying type representation for an enumeration.
8928 mono_class_enum_basetype (MonoClass *klass)
8930 if (klass->element_class == klass)
8931 /* SRE or broken types */
8934 return &klass->element_class->byval_arg;
8938 * mono_class_get_parent
8939 * @klass: the MonoClass to act on
8941 * Returns: The parent class for this class.
8944 mono_class_get_parent (MonoClass *klass)
8946 return klass->parent;
8950 * mono_class_get_nesting_type:
8951 * @klass: the MonoClass to act on
8953 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8955 * If the return is NULL, this indicates that this class is not nested.
8957 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8960 mono_class_get_nesting_type (MonoClass *klass)
8962 return klass->nested_in;
8966 * mono_class_get_rank:
8967 * @klass: the MonoClass to act on
8969 * Returns: The rank for the array (the number of dimensions).
8972 mono_class_get_rank (MonoClass *klass)
8978 * mono_class_get_flags:
8979 * @klass: the MonoClass to act on
8981 * The type flags from the TypeDef table from the metadata.
8982 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8985 * Returns: The flags from the TypeDef table.
8988 mono_class_get_flags (MonoClass *klass)
8990 return klass->flags;
8994 * mono_class_get_name
8995 * @klass: the MonoClass to act on
8997 * Returns: The name of the class.
9000 mono_class_get_name (MonoClass *klass)
9006 * mono_class_get_namespace:
9007 * @klass: the MonoClass to act on
9009 * Returns: The namespace of the class.
9012 mono_class_get_namespace (MonoClass *klass)
9014 return klass->name_space;
9018 * mono_class_get_type:
9019 * @klass: the MonoClass to act on
9021 * This method returns the internal Type representation for the class.
9023 * Returns: The MonoType from the class.
9026 mono_class_get_type (MonoClass *klass)
9028 return &klass->byval_arg;
9032 * mono_class_get_type_token:
9033 * @klass: the MonoClass to act on
9035 * This method returns type token for the class.
9037 * Returns: The type token for the class.
9040 mono_class_get_type_token (MonoClass *klass)
9042 return klass->type_token;
9046 * mono_class_get_byref_type:
9047 * @klass: the MonoClass to act on
9052 mono_class_get_byref_type (MonoClass *klass)
9054 return &klass->this_arg;
9058 * mono_class_num_fields:
9059 * @klass: the MonoClass to act on
9061 * Returns: The number of static and instance fields in the class.
9064 mono_class_num_fields (MonoClass *klass)
9066 return klass->field.count;
9070 * mono_class_num_methods:
9071 * @klass: the MonoClass to act on
9073 * Returns: The number of methods in the class.
9076 mono_class_num_methods (MonoClass *klass)
9078 return klass->method.count;
9082 * mono_class_num_properties
9083 * @klass: the MonoClass to act on
9085 * Returns: The number of properties in the class.
9088 mono_class_num_properties (MonoClass *klass)
9090 mono_class_setup_properties (klass);
9092 return klass->ext->property.count;
9096 * mono_class_num_events:
9097 * @klass: the MonoClass to act on
9099 * Returns: The number of events in the class.
9102 mono_class_num_events (MonoClass *klass)
9104 mono_class_setup_events (klass);
9106 return klass->ext->event.count;
9110 * mono_class_get_fields:
9111 * @klass: the MonoClass to act on
9113 * This routine is an iterator routine for retrieving the fields in a class.
9115 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9116 * iterate over all of the elements. When no more values are
9117 * available, the return value is NULL.
9119 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9122 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9124 MonoClassField* field;
9128 mono_class_setup_fields_locking (klass);
9129 if (mono_class_has_failure (klass))
9131 /* start from the first */
9132 if (klass->field.count) {
9133 *iter = &klass->fields [0];
9134 return &klass->fields [0];
9140 field = (MonoClassField *)*iter;
9142 if (field < &klass->fields [klass->field.count]) {
9150 * mono_class_get_methods
9151 * @klass: the MonoClass to act on
9153 * This routine is an iterator routine for retrieving the fields in a class.
9155 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9156 * iterate over all of the elements. When no more values are
9157 * available, the return value is NULL.
9159 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9162 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9164 MonoMethod** method;
9168 mono_class_setup_methods (klass);
9171 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9172 * FIXME we should better report this error to the caller
9174 if (!klass->methods)
9176 /* start from the first */
9177 if (klass->method.count) {
9178 *iter = &klass->methods [0];
9179 return klass->methods [0];
9185 method = (MonoMethod **)*iter;
9187 if (method < &klass->methods [klass->method.count]) {
9195 * mono_class_get_virtual_methods:
9197 * Iterate over the virtual methods of KLASS.
9199 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9202 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9204 MonoMethod** method;
9207 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9209 mono_class_setup_methods (klass);
9211 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9212 * FIXME we should better report this error to the caller
9214 if (!klass->methods)
9216 /* start from the first */
9217 method = &klass->methods [0];
9219 method = (MonoMethod **)*iter;
9222 while (method < &klass->methods [klass->method.count]) {
9223 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9227 if (method < &klass->methods [klass->method.count]) {
9234 /* Search directly in metadata to avoid calling setup_methods () */
9235 MonoMethod *res = NULL;
9241 start_index = GPOINTER_TO_UINT (*iter);
9244 for (i = start_index; i < klass->method.count; ++i) {
9247 /* klass->method.first points into the methodptr table */
9248 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9250 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9254 if (i < klass->method.count) {
9256 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9257 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9259 /* Add 1 here so the if (*iter) check fails */
9260 *iter = GUINT_TO_POINTER (i + 1);
9269 * mono_class_get_properties:
9270 * @klass: the MonoClass to act on
9272 * This routine is an iterator routine for retrieving the properties in a class.
9274 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9275 * iterate over all of the elements. When no more values are
9276 * available, the return value is NULL.
9278 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9281 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9283 MonoProperty* property;
9287 mono_class_setup_properties (klass);
9288 /* start from the first */
9289 if (klass->ext->property.count) {
9290 *iter = &klass->ext->properties [0];
9291 return (MonoProperty *)*iter;
9297 property = (MonoProperty *)*iter;
9299 if (property < &klass->ext->properties [klass->ext->property.count]) {
9301 return (MonoProperty *)*iter;
9307 * mono_class_get_events:
9308 * @klass: the MonoClass to act on
9310 * This routine is an iterator routine for retrieving the properties in a class.
9312 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9313 * iterate over all of the elements. When no more values are
9314 * available, the return value is NULL.
9316 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9319 mono_class_get_events (MonoClass* klass, gpointer *iter)
9325 mono_class_setup_events (klass);
9326 /* start from the first */
9327 if (klass->ext->event.count) {
9328 *iter = &klass->ext->events [0];
9329 return (MonoEvent *)*iter;
9335 event = (MonoEvent *)*iter;
9337 if (event < &klass->ext->events [klass->ext->event.count]) {
9339 return (MonoEvent *)*iter;
9345 * mono_class_get_interfaces
9346 * @klass: the MonoClass to act on
9348 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9350 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9351 * iterate over all of the elements. When no more values are
9352 * available, the return value is NULL.
9354 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9357 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9365 mono_class_init (klass);
9366 if (!klass->interfaces_inited) {
9367 mono_class_setup_interfaces (klass, &error);
9368 if (!mono_error_ok (&error)) {
9369 mono_error_cleanup (&error);
9373 /* start from the first */
9374 if (klass->interface_count) {
9375 *iter = &klass->interfaces [0];
9376 return klass->interfaces [0];
9382 iface = (MonoClass **)*iter;
9384 if (iface < &klass->interfaces [klass->interface_count]) {
9392 setup_nested_types (MonoClass *klass)
9395 GList *classes, *nested_classes, *l;
9398 if (klass->nested_classes_inited)
9401 if (!klass->type_token)
9402 klass->nested_classes_inited = TRUE;
9404 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9408 guint32 cols [MONO_NESTED_CLASS_SIZE];
9409 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9410 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9411 if (!mono_error_ok (&error)) {
9412 /*FIXME don't swallow the error message*/
9413 mono_error_cleanup (&error);
9415 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9419 classes = g_list_prepend (classes, nclass);
9421 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9424 mono_class_alloc_ext (klass);
9426 nested_classes = NULL;
9427 for (l = classes; l; l = l->next)
9428 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9429 g_list_free (classes);
9431 mono_image_lock (klass->image);
9433 mono_memory_barrier ();
9434 if (!klass->nested_classes_inited) {
9435 klass->ext->nested_classes = nested_classes;
9436 mono_memory_barrier ();
9437 klass->nested_classes_inited = TRUE;
9440 mono_image_unlock (klass->image);
9444 * mono_class_get_nested_types
9445 * @klass: the MonoClass to act on
9447 * This routine is an iterator routine for retrieving the nested types of a class.
9448 * This works only if @klass is non-generic, or a generic type definition.
9450 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9451 * iterate over all of the elements. When no more values are
9452 * available, the return value is NULL.
9454 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9457 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9463 if (!klass->nested_classes_inited)
9464 setup_nested_types (klass);
9467 /* start from the first */
9468 if (klass->ext && klass->ext->nested_classes) {
9469 *iter = klass->ext->nested_classes;
9470 return (MonoClass *)klass->ext->nested_classes->data;
9472 /* no nested types */
9476 item = (GList *)*iter;
9480 return (MonoClass *)item->data;
9487 * mono_class_is_delegate
9488 * @klass: the MonoClass to act on
9490 * Returns: TRUE if the MonoClass represents a System.Delegate.
9493 mono_class_is_delegate (MonoClass *klass)
9495 return klass->delegate;
9499 * mono_class_implements_interface
9500 * @klass: The MonoClass to act on
9501 * @interface: The interface to check if @klass implements.
9503 * Returns: TRUE if @klass implements @interface.
9506 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9508 return mono_class_is_assignable_from (iface, klass);
9512 * mono_field_get_name:
9513 * @field: the MonoClassField to act on
9515 * Returns: The name of the field.
9518 mono_field_get_name (MonoClassField *field)
9524 * mono_field_get_type:
9525 * @field: the MonoClassField to act on
9527 * Returns: MonoType of the field.
9530 mono_field_get_type (MonoClassField *field)
9533 MonoType *type = mono_field_get_type_checked (field, &error);
9534 if (!mono_error_ok (&error)) {
9535 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9536 mono_error_cleanup (&error);
9543 * mono_field_get_type_checked:
9544 * @field: the MonoClassField to act on
9545 * @error: used to return any erro found while retrieving @field type
9547 * Returns: MonoType of the field.
9550 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9552 mono_error_init (error);
9554 mono_field_resolve_type (field, error);
9559 * mono_field_get_parent:
9560 * @field: the MonoClassField to act on
9562 * Returns: MonoClass where the field was defined.
9565 mono_field_get_parent (MonoClassField *field)
9567 return field->parent;
9571 * mono_field_get_flags;
9572 * @field: the MonoClassField to act on
9574 * The metadata flags for a field are encoded using the
9575 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9577 * Returns: The flags for the field.
9580 mono_field_get_flags (MonoClassField *field)
9583 return mono_field_resolve_flags (field);
9584 return field->type->attrs;
9588 * mono_field_get_offset:
9589 * @field: the MonoClassField to act on
9591 * Returns: The field offset.
9594 mono_field_get_offset (MonoClassField *field)
9596 return field->offset;
9600 mono_field_get_rva (MonoClassField *field)
9604 MonoClass *klass = field->parent;
9605 MonoFieldDefaultValue *field_def_values;
9607 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9609 if (!klass->ext || !klass->ext->field_def_values) {
9610 mono_class_alloc_ext (klass);
9612 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9614 mono_image_lock (klass->image);
9615 if (!klass->ext->field_def_values)
9616 klass->ext->field_def_values = field_def_values;
9617 mono_image_unlock (klass->image);
9620 field_index = mono_field_get_index (field);
9622 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9623 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9625 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9626 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9629 return klass->ext->field_def_values [field_index].data;
9633 * mono_field_get_data:
9634 * @field: the MonoClassField to act on
9636 * Returns: A pointer to the metadata constant value or to the field
9637 * data if it has an RVA flag.
9640 mono_field_get_data (MonoClassField *field)
9642 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9643 MonoTypeEnum def_type;
9645 return mono_class_get_field_default_value (field, &def_type);
9646 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9647 return mono_field_get_rva (field);
9654 * mono_property_get_name:
9655 * @prop: the MonoProperty to act on
9657 * Returns: The name of the property
9660 mono_property_get_name (MonoProperty *prop)
9666 * mono_property_get_set_method
9667 * @prop: the MonoProperty to act on.
9669 * Returns: The setter method of the property (A MonoMethod)
9672 mono_property_get_set_method (MonoProperty *prop)
9678 * mono_property_get_get_method
9679 * @prop: the MonoProperty to act on.
9681 * Returns: The setter method of the property (A MonoMethod)
9684 mono_property_get_get_method (MonoProperty *prop)
9690 * mono_property_get_parent:
9691 * @prop: the MonoProperty to act on.
9693 * Returns: The MonoClass where the property was defined.
9696 mono_property_get_parent (MonoProperty *prop)
9698 return prop->parent;
9702 * mono_property_get_flags:
9703 * @prop: the MonoProperty to act on.
9705 * The metadata flags for a property are encoded using the
9706 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9708 * Returns: The flags for the property.
9711 mono_property_get_flags (MonoProperty *prop)
9717 * mono_event_get_name:
9718 * @event: the MonoEvent to act on
9720 * Returns: The name of the event.
9723 mono_event_get_name (MonoEvent *event)
9729 * mono_event_get_add_method:
9730 * @event: The MonoEvent to act on.
9732 * Returns: The @add' method for the event (a MonoMethod).
9735 mono_event_get_add_method (MonoEvent *event)
9741 * mono_event_get_remove_method:
9742 * @event: The MonoEvent to act on.
9744 * Returns: The @remove method for the event (a MonoMethod).
9747 mono_event_get_remove_method (MonoEvent *event)
9749 return event->remove;
9753 * mono_event_get_raise_method:
9754 * @event: The MonoEvent to act on.
9756 * Returns: The @raise method for the event (a MonoMethod).
9759 mono_event_get_raise_method (MonoEvent *event)
9761 return event->raise;
9765 * mono_event_get_parent:
9766 * @event: the MonoEvent to act on.
9768 * Returns: The MonoClass where the event is defined.
9771 mono_event_get_parent (MonoEvent *event)
9773 return event->parent;
9777 * mono_event_get_flags
9778 * @event: the MonoEvent to act on.
9780 * The metadata flags for an event are encoded using the
9781 * EVENT_* constants. See the tabledefs.h file for details.
9783 * Returns: The flags for the event.
9786 mono_event_get_flags (MonoEvent *event)
9788 return event->attrs;
9792 * mono_class_get_method_from_name:
9793 * @klass: where to look for the method
9794 * @name: name of the method
9795 * @param_count: number of parameters. -1 for any number.
9797 * Obtains a MonoMethod with a given name and number of parameters.
9798 * It only works if there are no multiple signatures for any given method name.
9801 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9803 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9807 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9809 MonoMethod *res = NULL;
9812 /* Search directly in the metadata to avoid calling setup_methods () */
9813 for (i = 0; i < klass->method.count; ++i) {
9815 guint32 cols [MONO_METHOD_SIZE];
9817 MonoMethodSignature *sig;
9819 /* klass->method.first points into the methodptr table */
9820 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9822 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9823 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9825 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9828 if (param_count == -1) {
9832 sig = mono_method_signature_checked (method, &error);
9834 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9837 if (sig->param_count == param_count) {
9848 * mono_class_get_method_from_name_flags:
9849 * @klass: where to look for the method
9850 * @name_space: name of the method
9851 * @param_count: number of parameters. -1 for any number.
9852 * @flags: flags which must be set in the method
9854 * Obtains a MonoMethod with a given name and number of parameters.
9855 * It only works if there are no multiple signatures for any given method name.
9858 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9860 MonoMethod *res = NULL;
9863 mono_class_init (klass);
9865 if (klass->generic_class && !klass->methods) {
9866 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9869 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9870 if (!mono_error_ok (&error))
9871 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9876 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9877 mono_class_setup_methods (klass);
9879 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9880 See mono/tests/array_load_exception.il
9881 FIXME we should better report this error to the caller
9883 if (!klass->methods)
9885 for (i = 0; i < klass->method.count; ++i) {
9886 MonoMethod *method = klass->methods [i];
9888 if (method->name[0] == name [0] &&
9889 !strcmp (name, method->name) &&
9890 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9891 ((method->flags & flags) == flags)) {
9898 res = find_method_in_metadata (klass, name, param_count, flags);
9905 * mono_class_set_failure:
9906 * @klass: class in which the failure was detected
9907 * @ex_type: the kind of exception/error to be thrown (later)
9908 * @ex_data: exception data (specific to each type of exception/error)
9910 * Keep a detected failure informations in the class for later processing.
9911 * Note that only the first failure is kept.
9913 * LOCKING: Acquires the loader lock.
9916 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9918 if (mono_class_has_failure (klass))
9921 mono_loader_lock ();
9922 klass->exception_type = ex_type;
9924 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9925 mono_loader_unlock ();
9931 * mono_class_get_exception_data:
9933 * Return the exception_data property of KLASS.
9935 * LOCKING: Acquires the loader lock.
9938 mono_class_get_exception_data (MonoClass *klass)
9940 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9944 * mono_classes_init:
9946 * Initialize the resources used by this module.
9949 mono_classes_init (void)
9951 mono_os_mutex_init (&classes_mutex);
9953 mono_counters_register ("Inflated methods size",
9954 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9955 mono_counters_register ("Inflated classes",
9956 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9957 mono_counters_register ("Inflated classes size",
9958 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9959 mono_counters_register ("MonoClass size",
9960 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9961 mono_counters_register ("MonoClassExt size",
9962 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9966 * mono_classes_cleanup:
9968 * Free the resources used by this module.
9971 mono_classes_cleanup (void)
9973 if (global_interface_bitset)
9974 mono_bitset_free (global_interface_bitset);
9975 global_interface_bitset = NULL;
9976 mono_os_mutex_destroy (&classes_mutex);
9980 * mono_class_get_exception_for_failure:
9981 * @klass: class in which the failure was detected
9983 * Return a constructed MonoException than the caller can then throw
9984 * using mono_raise_exception - or NULL if no failure is present (or
9985 * doesn't result in an exception).
9988 mono_class_get_exception_for_failure (MonoClass *klass)
9990 gpointer exception_data = mono_class_get_exception_data (klass);
9992 switch (mono_class_get_failure(klass)) {
9993 case MONO_EXCEPTION_TYPE_LOAD: {
9996 char *str = mono_type_get_full_name (klass);
9997 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9998 name = mono_string_new (mono_domain_get (), str);
10000 ex = mono_get_exception_type_load (name, astr);
10004 case MONO_EXCEPTION_MISSING_METHOD: {
10005 char *class_name = (char *)exception_data;
10006 char *assembly_name = class_name + strlen (class_name) + 1;
10008 return mono_get_exception_missing_method (class_name, assembly_name);
10010 case MONO_EXCEPTION_MISSING_FIELD: {
10011 char *class_name = (char *)exception_data;
10012 char *member_name = class_name + strlen (class_name) + 1;
10014 return mono_get_exception_missing_field (class_name, member_name);
10016 case MONO_EXCEPTION_FILE_NOT_FOUND: {
10017 char *msg_format = (char *)exception_data;
10018 char *assembly_name = msg_format + strlen (msg_format) + 1;
10019 char *msg = g_strdup_printf (msg_format, assembly_name);
10022 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10028 case MONO_EXCEPTION_BAD_IMAGE: {
10029 return mono_get_exception_bad_image_format ((const char *)exception_data);
10031 case MONO_EXCEPTION_INVALID_PROGRAM: {
10032 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10035 /* TODO - handle other class related failures */
10036 return mono_get_exception_execution_engine ("Unknown class failure");
10042 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10044 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10045 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10047 if (outer_klass == inner_klass)
10049 inner_klass = inner_klass->nested_in;
10050 } while (inner_klass);
10055 mono_class_get_generic_type_definition (MonoClass *klass)
10057 return klass->generic_class ? klass->generic_class->container_class : klass;
10061 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10063 * Generic instantiations are ignored for all super types of @klass.
10065 * Visibility checks ignoring generic instantiations.
10068 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10071 klass = mono_class_get_generic_type_definition (klass);
10072 parent = mono_class_get_generic_type_definition (parent);
10073 mono_class_setup_supertypes (klass);
10075 for (i = 0; i < klass->idepth; ++i) {
10076 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10082 * Subtype can only access parent members with family protection if the site object
10083 * is subclass of Subtype. For example:
10084 * class A { protected int x; }
10086 * void valid_access () {
10090 * void invalid_access () {
10097 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10099 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10102 if (context_klass == NULL)
10104 /*if access_klass is not member_klass context_klass must be type compat*/
10105 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10111 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10114 if (accessing == accessed)
10116 if (!accessed || !accessing)
10119 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10120 * anywhere so untrusted friends are not safe to access platform's code internals */
10121 if (mono_security_core_clr_enabled ()) {
10122 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10126 mono_assembly_load_friends (accessed);
10127 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10128 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10129 /* Be conservative with checks */
10130 if (!friend_->name)
10132 if (strcmp (accessing->aname.name, friend_->name))
10134 if (friend_->public_key_token [0]) {
10135 if (!accessing->aname.public_key_token [0])
10137 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10146 * If klass is a generic type or if it is derived from a generic type, return the
10147 * MonoClass of the generic definition
10148 * Returns NULL if not found
10151 get_generic_definition_class (MonoClass *klass)
10154 if (klass->generic_class && klass->generic_class->container_class)
10155 return klass->generic_class->container_class;
10156 klass = klass->parent;
10162 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10165 for (i = 0; i < ginst->type_argc; ++i) {
10166 MonoType *type = ginst->type_argv[i];
10167 switch (type->type) {
10168 case MONO_TYPE_SZARRAY:
10169 if (!can_access_type (access_klass, type->data.klass))
10172 case MONO_TYPE_ARRAY:
10173 if (!can_access_type (access_klass, type->data.array->eklass))
10176 case MONO_TYPE_PTR:
10177 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10180 case MONO_TYPE_CLASS:
10181 case MONO_TYPE_VALUETYPE:
10182 case MONO_TYPE_GENERICINST:
10183 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10193 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10197 if (access_klass == member_klass)
10200 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10203 if (access_klass->element_class && !access_klass->enumtype)
10204 access_klass = access_klass->element_class;
10206 if (member_klass->element_class && !member_klass->enumtype)
10207 member_klass = member_klass->element_class;
10209 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10211 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10214 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10217 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10220 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10223 /*Non nested type with nested visibility. We just fail it.*/
10224 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10227 switch (access_level) {
10228 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10229 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10231 case TYPE_ATTRIBUTE_PUBLIC:
10234 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10237 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10238 return is_nesting_type (member_klass, access_klass);
10240 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10241 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10243 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10244 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10246 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10247 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10248 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10250 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10251 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10252 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10257 /* FIXME: check visibility of type, too */
10259 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10261 MonoClass *member_generic_def;
10262 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10265 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10266 access_klass->generic_container) &&
10267 (member_generic_def = get_generic_definition_class (member_klass))) {
10268 MonoClass *access_container;
10270 if (access_klass->generic_container)
10271 access_container = access_klass;
10273 access_container = access_klass->generic_class->container_class;
10275 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10279 /* Partition I 8.5.3.2 */
10280 /* the access level values are the same for fields and methods */
10281 switch (access_level) {
10282 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10283 /* same compilation unit */
10284 return access_klass->image == member_klass->image;
10285 case FIELD_ATTRIBUTE_PRIVATE:
10286 return access_klass == member_klass;
10287 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10288 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10289 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10292 case FIELD_ATTRIBUTE_ASSEMBLY:
10293 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10294 case FIELD_ATTRIBUTE_FAMILY:
10295 if (is_valid_family_access (access_klass, member_klass, context_klass))
10298 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10299 if (is_valid_family_access (access_klass, member_klass, context_klass))
10301 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10302 case FIELD_ATTRIBUTE_PUBLIC:
10309 * mono_method_can_access_field:
10310 * @method: Method that will attempt to access the field
10311 * @field: the field to access
10313 * Used to determine if a method is allowed to access the specified field.
10315 * Returns: TRUE if the given @method is allowed to access the @field while following
10316 * the accessibility rules of the CLI.
10319 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10321 /* FIXME: check all overlapping fields */
10322 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10324 MonoClass *nested = method->klass->nested_in;
10326 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10329 nested = nested->nested_in;
10336 * mono_method_can_access_method:
10337 * @method: Method that will attempt to access the other method
10338 * @called: the method that we want to probe for accessibility.
10340 * Used to determine if the @method is allowed to access the specified @called method.
10342 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10343 * the accessibility rules of the CLI.
10346 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10348 method = mono_method_get_method_definition (method);
10349 called = mono_method_get_method_definition (called);
10350 return mono_method_can_access_method_full (method, called, NULL);
10354 * mono_method_can_access_method_full:
10355 * @method: The caller method
10356 * @called: The called method
10357 * @context_klass: The static type on stack of the owner @called object used
10359 * This function must be used with instance calls, as they have more strict family accessibility.
10360 * It can be used with static methods, but context_klass should be NULL.
10362 * Returns: TRUE if caller have proper visibility and acessibility to @called
10365 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10367 /* Wrappers are except from access checks */
10368 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10371 MonoClass *access_class = method->klass;
10372 MonoClass *member_class = called->klass;
10373 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10375 MonoClass *nested = access_class->nested_in;
10377 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10380 nested = nested->nested_in;
10387 can = can_access_type (access_class, member_class);
10389 MonoClass *nested = access_class->nested_in;
10391 can = can_access_type (nested, member_class);
10394 nested = nested->nested_in;
10401 if (called->is_inflated) {
10402 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10403 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10412 * mono_method_can_access_field_full:
10413 * @method: The caller method
10414 * @field: The accessed field
10415 * @context_klass: The static type on stack of the owner @field object used
10417 * This function must be used with instance fields, as they have more strict family accessibility.
10418 * It can be used with static fields, but context_klass should be NULL.
10420 * Returns: TRUE if caller have proper visibility and acessibility to @field
10423 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10425 MonoClass *access_class = method->klass;
10426 MonoClass *member_class = field->parent;
10427 /* FIXME: check all overlapping fields */
10428 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10430 MonoClass *nested = access_class->nested_in;
10432 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10435 nested = nested->nested_in;
10442 can = can_access_type (access_class, member_class);
10444 MonoClass *nested = access_class->nested_in;
10446 can = can_access_type (nested, member_class);
10449 nested = nested->nested_in;
10459 * mono_class_can_access_class:
10460 * @source_class: The source class
10461 * @target_class: The accessed class
10463 * This function returns is @target_class is visible to @source_class
10465 * Returns: TRUE if source have proper visibility and acessibility to target
10468 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10470 return can_access_type (source_class, target_class);
10474 * mono_type_is_valid_enum_basetype:
10475 * @type: The MonoType to check
10477 * Returns: TRUE if the type can be used as the basetype of an enum
10479 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10480 switch (type->type) {
10483 case MONO_TYPE_BOOLEAN:
10486 case MONO_TYPE_CHAR:
10500 * mono_class_is_valid_enum:
10501 * @klass: An enum class to be validated
10503 * This method verify the required properties an enum should have.
10505 * Returns: TRUE if the informed enum class is valid
10507 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10508 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10509 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10511 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10512 MonoClassField * field;
10513 gpointer iter = NULL;
10514 gboolean found_base_field = FALSE;
10516 g_assert (klass->enumtype);
10517 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10518 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10522 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10525 while ((field = mono_class_get_fields (klass, &iter))) {
10526 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10527 if (found_base_field)
10529 found_base_field = TRUE;
10530 if (!mono_type_is_valid_enum_basetype (field->type))
10535 if (!found_base_field)
10538 if (klass->method.count > 0)
10545 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10547 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10551 * mono_class_setup_interface_id:
10553 * Initializes MonoClass::interface_id if required.
10555 * LOCKING: Acquires the loader lock.
10558 mono_class_setup_interface_id (MonoClass *klass)
10560 mono_loader_lock ();
10561 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10562 klass->interface_id = mono_get_unique_iid (klass);
10563 mono_loader_unlock ();
10567 * mono_class_alloc_ext:
10569 * Allocate klass->ext if not already done.
10572 mono_class_alloc_ext (MonoClass *klass)
10579 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10580 mono_image_lock (klass->image);
10581 mono_memory_barrier ();
10584 class_ext_size += sizeof (MonoClassExt);
10585 mono_image_unlock (klass->image);
10589 * mono_class_setup_interfaces:
10591 * Initialize klass->interfaces/interfaces_count.
10592 * LOCKING: Acquires the loader lock.
10593 * This function can fail the type.
10596 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10598 int i, interface_count;
10599 MonoClass **interfaces;
10601 mono_error_init (error);
10603 if (klass->interfaces_inited)
10606 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10607 MonoType *args [1];
10609 /* generic IList, ICollection, IEnumerable */
10610 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10611 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10613 args [0] = &klass->element_class->byval_arg;
10614 interfaces [0] = mono_class_bind_generic_parameters (
10615 mono_defaults.generic_ilist_class, 1, args, FALSE);
10616 if (interface_count > 1)
10617 interfaces [1] = mono_class_bind_generic_parameters (
10618 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10619 } else if (klass->generic_class) {
10620 MonoClass *gklass = klass->generic_class->container_class;
10622 mono_class_setup_interfaces (gklass, error);
10623 if (!mono_error_ok (error)) {
10624 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Could not setup the interfaces"));
10628 interface_count = gklass->interface_count;
10629 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10630 for (i = 0; i < interface_count; i++) {
10631 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10632 if (!mono_error_ok (error)) {
10633 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Could not setup the interfaces"));
10638 interface_count = 0;
10642 mono_image_lock (klass->image);
10644 if (!klass->interfaces_inited) {
10645 klass->interface_count = interface_count;
10646 klass->interfaces = interfaces;
10648 mono_memory_barrier ();
10650 klass->interfaces_inited = TRUE;
10653 mono_image_unlock (klass->image);
10657 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10659 MonoClass *klass = field->parent;
10660 MonoImage *image = klass->image;
10661 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10662 int field_idx = field - klass->fields;
10664 mono_error_init (error);
10667 MonoClassField *gfield = >d->fields [field_idx];
10668 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10669 if (!mono_error_ok (error)) {
10670 char *err_msg = mono_image_strdup_printf (klass->image, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10671 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10674 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10675 if (!mono_error_ok (error)) {
10676 char *err_msg = mono_image_strdup_printf (klass->image, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10677 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10681 guint32 cols [MONO_FIELD_SIZE];
10682 MonoGenericContainer *container = NULL;
10683 int idx = klass->field.first + field_idx;
10685 /*FIXME, in theory we do not lazy load SRE fields*/
10686 g_assert (!image_is_dynamic (image));
10688 if (klass->generic_container) {
10689 container = klass->generic_container;
10691 container = gtd->generic_container;
10692 g_assert (container);
10695 /* klass->field.first and idx points into the fieldptr table */
10696 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10698 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10699 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10700 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, mono_error_get_message (error)));
10704 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10706 mono_metadata_decode_value (sig, &sig);
10707 /* FIELD signature == 0x06 */
10708 g_assert (*sig == 0x06);
10710 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10711 if (!field->type) {
10712 char *err_msg = mono_image_strdup_printf (klass->image, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10713 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10719 mono_field_resolve_flags (MonoClassField *field)
10721 MonoClass *klass = field->parent;
10722 MonoImage *image = klass->image;
10723 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10724 int field_idx = field - klass->fields;
10728 MonoClassField *gfield = >d->fields [field_idx];
10729 return mono_field_get_flags (gfield);
10731 int idx = klass->field.first + field_idx;
10733 /*FIXME, in theory we do not lazy load SRE fields*/
10734 g_assert (!image_is_dynamic (image));
10736 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10741 * mono_class_setup_basic_field_info:
10742 * @class: The class to initialize
10744 * Initializes the klass->fields array of fields.
10745 * Aquires the loader lock.
10748 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10750 mono_loader_lock ();
10751 mono_class_setup_basic_field_info (klass);
10752 mono_loader_unlock ();
10756 * mono_class_get_fields_lazy:
10757 * @klass: the MonoClass to act on
10759 * This routine is an iterator routine for retrieving the fields in a class.
10760 * Only minimal information about fields are loaded. Accessors must be used
10761 * for all MonoClassField returned.
10763 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10764 * iterate over all of the elements. When no more values are
10765 * available, the return value is NULL.
10767 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10770 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10772 MonoClassField* field;
10776 mono_class_setup_basic_field_info_locking (klass);
10777 if (!klass->fields)
10779 /* start from the first */
10780 if (klass->field.count) {
10781 *iter = &klass->fields [0];
10782 return (MonoClassField *)*iter;
10788 field = (MonoClassField *)*iter;
10790 if (field < &klass->fields [klass->field.count]) {
10792 return (MonoClassField *)*iter;
10798 mono_class_full_name (MonoClass *klass)
10800 return mono_type_full_name (&klass->byval_arg);
10803 /* Declare all shared lazy type lookup functions */
10804 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)