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 (iresult->context.method_inst) {
1136 /* Set the generic_container of the result to the generic_container of method */
1137 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1139 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1140 result->is_generic = 1;
1141 mono_method_set_generic_container (result, generic_container);
1145 if (!klass_hint || !klass_hint->generic_class ||
1146 klass_hint->generic_class->container_class != method->klass ||
1147 klass_hint->generic_class->context.class_inst != context->class_inst)
1150 if (method->klass->generic_container)
1151 result->klass = klass_hint;
1153 if (!result->klass) {
1154 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1155 if (!mono_error_ok (error))
1158 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1160 mono_metadata_free_type (inflated);
1164 * FIXME: This should hold, but it doesn't:
1166 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1167 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1168 * g_assert (result->is_generic);
1171 * Fixing this here causes other things to break, hence a very
1172 * ugly hack in mini-trampolines.c - see
1173 * is_generic_method_definition().
1177 mono_image_set_lock (set);
1178 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1180 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1181 iresult->owner = set;
1184 mono_image_set_unlock (set);
1186 return (MonoMethod*)cached;
1194 * mono_get_inflated_method:
1196 * Obsolete. We keep it around since it's mentioned in the public API.
1199 mono_get_inflated_method (MonoMethod *method)
1205 * mono_method_get_context_general:
1207 * @uninflated: handle uninflated methods?
1209 * Returns the generic context of a method or NULL if it doesn't have
1210 * one. For an inflated method that's the context stored in the
1211 * method. Otherwise it's in the method's generic container or in the
1212 * generic container of the method's class.
1215 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1217 if (method->is_inflated) {
1218 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1219 return &imethod->context;
1223 if (method->is_generic)
1224 return &(mono_method_get_generic_container (method)->context);
1225 if (method->klass->generic_container)
1226 return &method->klass->generic_container->context;
1231 * mono_method_get_context:
1234 * Returns the generic context for method if it's inflated, otherwise
1238 mono_method_get_context (MonoMethod *method)
1240 return mono_method_get_context_general (method, FALSE);
1244 * mono_method_get_generic_container:
1246 * Returns the generic container of METHOD, which should be a generic method definition.
1247 * Returns NULL if METHOD is not a generic method definition.
1248 * LOCKING: Acquires the loader lock.
1250 MonoGenericContainer*
1251 mono_method_get_generic_container (MonoMethod *method)
1253 MonoGenericContainer *container;
1255 if (!method->is_generic)
1258 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1259 g_assert (container);
1265 * mono_method_set_generic_container:
1267 * Sets the generic container of METHOD to CONTAINER.
1268 * LOCKING: Acquires the image lock.
1271 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1273 g_assert (method->is_generic);
1275 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1279 * mono_class_find_enum_basetype:
1280 * @class: The enum class
1282 * Determine the basetype of an enum by iterating through its fields. We do this
1283 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1286 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1288 MonoGenericContainer *container = NULL;
1289 MonoImage *m = klass->image;
1290 const int top = klass->field.count;
1293 g_assert (klass->enumtype);
1295 mono_error_init (error);
1297 if (klass->generic_container)
1298 container = klass->generic_container;
1299 else if (klass->generic_class) {
1300 MonoClass *gklass = klass->generic_class->container_class;
1302 container = gklass->generic_container;
1303 g_assert (container);
1307 * Fetch all the field information.
1309 for (i = 0; i < top; i++){
1311 guint32 cols [MONO_FIELD_SIZE];
1312 int idx = klass->field.first + i;
1315 /* klass->field.first and idx points into the fieldptr table */
1316 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1318 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1321 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1322 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1326 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1327 mono_metadata_decode_value (sig, &sig);
1328 /* FIELD signature == 0x06 */
1330 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1334 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1338 if (klass->generic_class) {
1339 //FIXME do we leak here?
1340 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1341 if (!mono_error_ok (error))
1343 ftype->attrs = cols [MONO_FIELD_FLAGS];
1348 mono_error_set_type_load_class (error, klass, "Could not find base type");
1355 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1358 mono_type_has_exceptions (MonoType *type)
1360 switch (type->type) {
1361 case MONO_TYPE_CLASS:
1362 case MONO_TYPE_VALUETYPE:
1363 case MONO_TYPE_SZARRAY:
1364 return mono_class_has_failure (type->data.klass);
1365 case MONO_TYPE_ARRAY:
1366 return mono_class_has_failure (type->data.array->eklass);
1367 case MONO_TYPE_GENERICINST:
1368 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1375 mono_error_set_for_class_failure (MonoError *oerror, MonoClass *klass)
1377 gpointer exception_data = mono_class_get_exception_data (klass);
1379 switch (mono_class_get_failure(klass)) {
1380 case MONO_EXCEPTION_TYPE_LOAD: {
1381 mono_error_set_type_load_class (oerror, klass, "Error Loading class");
1384 case MONO_EXCEPTION_MISSING_METHOD: {
1385 char *class_name = (char *)exception_data;
1386 char *member_name = class_name + strlen (class_name) + 1;
1388 mono_error_set_method_load (oerror, klass, member_name, "Error Loading Method");
1391 case MONO_EXCEPTION_MISSING_FIELD: {
1392 char *class_name = (char *)exception_data;
1393 char *member_name = class_name + strlen (class_name) + 1;
1395 mono_error_set_field_load (oerror, klass, member_name, "Error Loading Field");
1398 case MONO_EXCEPTION_FILE_NOT_FOUND: {
1399 char *msg_format = (char *)exception_data;
1400 char *assembly_name = msg_format + strlen (msg_format) + 1;
1401 char *msg = g_strdup_printf (msg_format, assembly_name);
1403 mono_error_set_assembly_load (oerror, assembly_name, msg);
1406 case MONO_EXCEPTION_BAD_IMAGE: {
1407 mono_error_set_bad_image (oerror, NULL, (const char *)exception_data);
1410 case MONO_EXCEPTION_INVALID_PROGRAM: {
1411 mono_error_set_invalid_program (oerror, (const char *)exception_data);
1415 g_assert_not_reached ();
1424 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1428 mono_class_alloc (MonoClass *klass, int size)
1430 if (klass->generic_class)
1431 return mono_image_set_alloc (klass->generic_class->owner, size);
1433 return mono_image_alloc (klass->image, size);
1437 mono_class_alloc0 (MonoClass *klass, int size)
1441 res = mono_class_alloc (klass, size);
1442 memset (res, 0, size);
1446 #define mono_class_new0(klass,struct_type, n_structs) \
1447 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1450 * mono_class_setup_basic_field_info:
1451 * @class: The class to initialize
1453 * Initializes the klass->fields.
1454 * LOCKING: Assumes the loader lock is held.
1457 mono_class_setup_basic_field_info (MonoClass *klass)
1459 MonoClassField *field;
1467 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1468 image = klass->image;
1469 top = klass->field.count;
1471 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1473 * This happens when a generic instance of an unfinished generic typebuilder
1474 * is used as an element type for creating an array type. We can't initialize
1475 * the fields of this class using the fields of gklass, since gklass is not
1476 * finished yet, fields could be added to it later.
1482 mono_class_setup_basic_field_info (gtd);
1484 top = gtd->field.count;
1485 klass->field.first = gtd->field.first;
1486 klass->field.count = gtd->field.count;
1489 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1492 * Fetch all the field information.
1494 for (i = 0; i < top; i++){
1495 field = &klass->fields [i];
1496 field->parent = klass;
1499 field->name = mono_field_get_name (>d->fields [i]);
1501 int idx = klass->field.first + i;
1502 /* klass->field.first and idx points into the fieldptr table */
1503 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1504 /* The name is needed for fieldrefs */
1505 field->name = mono_metadata_string_heap (image, name_idx);
1511 * mono_class_setup_fields:
1512 * @class: The class to initialize
1514 * Initializes the klass->fields.
1515 * LOCKING: Assumes the loader lock is held.
1518 mono_class_setup_fields (MonoClass *klass)
1521 MonoImage *m = klass->image;
1523 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1524 int i, blittable = TRUE;
1525 guint32 real_size = 0;
1526 guint32 packing_size = 0;
1528 gboolean explicit_size;
1529 MonoClassField *field;
1530 MonoGenericContainer *container = NULL;
1531 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1534 * FIXME: We have a race condition here. It's possible that this function returns
1535 * to its caller with `instance_size` set to `0` instead of the actual size. This
1536 * is not a problem when the function is called recursively on the same class,
1537 * because the size will be initialized by the outer invocation. What follows is a
1538 * description of how it can occur in other cases, too. There it is a problem,
1539 * because it can lead to the GC being asked to allocate an object of size `0`,
1540 * which SGen chokes on. The race condition is triggered infrequently by
1541 * `tests/sgen-suspend.cs`.
1543 * This function is called for a class whenever one of its subclasses is inited.
1544 * For example, it's called for every subclass of Object. What it does is this:
1546 * if (klass->setup_fields_called)
1549 * klass->instance_size = 0;
1551 * klass->setup_fields_called = 1;
1552 * ... critical point
1553 * klass->instance_size = actual_instance_size;
1555 * The last two steps are sometimes reversed, but that only changes the way in which
1556 * the race condition works.
1558 * Assume thread A goes through this function and makes it to the critical point.
1559 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1560 * immediately, but `instance_size` is incorrect.
1562 * The other case looks like this:
1564 * if (klass->setup_fields_called)
1566 * ... critical point X
1567 * klass->instance_size = 0;
1568 * ... critical point Y
1569 * klass->instance_size = actual_instance_size;
1571 * klass->setup_fields_called = 1;
1573 * Assume thread A goes through the function and makes it to critical point X. Now
1574 * thread B runs through the whole of the function, returning, assuming
1575 * `instance_size` is set. At that point thread A gets to run and makes it to
1576 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1579 if (klass->setup_fields_called)
1582 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1584 * This happens when a generic instance of an unfinished generic typebuilder
1585 * is used as an element type for creating an array type. We can't initialize
1586 * the fields of this class using the fields of gklass, since gklass is not
1587 * finished yet, fields could be added to it later.
1592 mono_class_setup_basic_field_info (klass);
1593 top = klass->field.count;
1596 mono_class_setup_fields (gtd);
1597 if (mono_class_has_failure (gtd)) {
1598 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1605 klass->sizes.class_size = 0;
1607 if (klass->parent) {
1608 /* For generic instances, klass->parent might not have been initialized */
1609 mono_class_init (klass->parent);
1610 if (!klass->parent->size_inited) {
1611 mono_class_setup_fields (klass->parent);
1612 if (mono_class_has_failure (klass->parent)) {
1613 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1617 instance_size += klass->parent->instance_size;
1618 klass->min_align = klass->parent->min_align;
1619 /* we use |= since it may have been set already */
1620 klass->has_references |= klass->parent->has_references;
1621 blittable = klass->parent->blittable;
1623 instance_size = sizeof (MonoObject);
1624 klass->min_align = 1;
1627 /* We can't really enable 16 bytes alignment until the GC supports it.
1628 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1629 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1630 Bug #506144 is an example of this issue.
1632 if (klass->simd_type)
1633 klass->min_align = 16;
1635 /* Get the real size */
1636 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1638 if (explicit_size) {
1639 if ((packing_size & 0xffffff00) != 0) {
1640 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1641 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1644 klass->packing_size = packing_size;
1645 real_size += instance_size;
1649 if (explicit_size && real_size) {
1650 instance_size = MAX (real_size, instance_size);
1652 klass->blittable = blittable;
1653 if (!klass->instance_size)
1654 klass->instance_size = instance_size;
1655 mono_memory_barrier ();
1656 klass->size_inited = 1;
1657 klass->fields_inited = 1;
1658 klass->setup_fields_called = 1;
1662 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1665 /* Prevent infinite loops if the class references itself */
1666 klass->setup_fields_called = 1;
1668 if (klass->generic_container) {
1669 container = klass->generic_container;
1671 container = gtd->generic_container;
1672 g_assert (container);
1676 * Fetch all the field information.
1678 for (i = 0; i < top; i++){
1679 int idx = klass->field.first + i;
1680 field = &klass->fields [i];
1682 field->parent = klass;
1685 mono_field_resolve_type (field, &error);
1686 if (!mono_error_ok (&error)) {
1687 /*mono_field_resolve_type already failed class*/
1688 mono_error_cleanup (&error);
1692 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1693 g_assert (field->type);
1696 if (mono_field_is_deleted (field))
1699 MonoClassField *gfield = >d->fields [i];
1700 field->offset = gfield->offset;
1702 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1704 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1705 field->offset = offset;
1707 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1708 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1711 if (field->offset < -1) { /*-1 is used to encode special static fields */
1712 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1715 if (klass->generic_container) {
1716 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1722 /* Only do these checks if we still think this type is blittable */
1723 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1724 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1727 MonoClass *field_class = mono_class_from_mono_type (field->type);
1729 mono_class_setup_fields (field_class);
1730 if (mono_class_has_failure (field_class)) {
1731 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1735 if (!field_class || !field_class->blittable)
1740 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1741 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1742 blittable = klass->element_class->blittable;
1745 if (mono_type_has_exceptions (field->type)) {
1746 char *class_name = mono_type_get_full_name (klass);
1747 char *type_name = mono_type_full_name (field->type);
1749 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1750 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1751 g_free (class_name);
1755 /* The def_value of fields is compute lazily during vtable creation */
1758 if (klass == mono_defaults.string_class)
1761 klass->blittable = blittable;
1763 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1764 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1767 if (explicit_size && real_size) {
1768 instance_size = MAX (real_size, instance_size);
1771 if (mono_class_has_failure (klass))
1773 mono_class_layout_fields (klass, instance_size);
1775 /*valuetypes can't be neither bigger than 1Mb or empty. */
1776 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1777 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1779 mono_memory_barrier ();
1780 klass->fields_inited = 1;
1784 * mono_class_setup_fields_locking:
1785 * @class: The class to initialize
1787 * Initializes the klass->fields array of fields.
1788 * Aquires the loader lock.
1791 mono_class_setup_fields_locking (MonoClass *klass)
1793 /* This can be checked without locks */
1794 if (klass->fields_inited)
1796 mono_loader_lock ();
1797 mono_class_setup_fields (klass);
1798 mono_loader_unlock ();
1802 * mono_class_has_references:
1804 * Returns whenever @klass->has_references is set, initializing it if needed.
1805 * Aquires the loader lock.
1808 mono_class_has_references (MonoClass *klass)
1810 if (klass->init_pending) {
1811 /* Be conservative */
1814 mono_class_init (klass);
1816 return klass->has_references;
1821 * mono_type_get_basic_type_from_generic:
1824 * Returns a closed type corresponding to the possibly open type
1828 mono_type_get_basic_type_from_generic (MonoType *type)
1830 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1831 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1832 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1833 return &mono_defaults.object_class->byval_arg;
1838 type_has_references (MonoClass *klass, MonoType *ftype)
1840 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)))))
1842 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1843 MonoGenericParam *gparam = ftype->data.generic_param;
1845 if (gparam->gshared_constraint)
1846 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1852 * mono_class_layout_fields:
1854 * @instance_size: base instance size
1856 * Compute the placement of fields inside an object or struct, according to
1857 * the layout rules and set the following fields in @class:
1858 * - has_references (if the class contains instance references firled or structs that contain references)
1859 * - has_static_refs (same, but for static fields)
1860 * - instance_size (size of the object in memory)
1861 * - class_size (size needed for the static fields)
1862 * - size_inited (flag set when the instance_size is set)
1864 * LOCKING: this is supposed to be called with the loader lock held.
1867 mono_class_layout_fields (MonoClass *klass, int instance_size)
1870 const int top = klass->field.count;
1871 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1872 guint32 pass, passes, real_size;
1873 gboolean gc_aware_layout = FALSE;
1874 gboolean has_static_fields = FALSE;
1875 MonoClassField *field;
1878 * When we do generic sharing we need to have layout
1879 * information for open generic classes (either with a generic
1880 * context containing type variables or with a generic
1881 * container), so we don't return in that case anymore.
1885 * Enable GC aware auto layout: in this mode, reference
1886 * fields are grouped together inside objects, increasing collector
1888 * Requires that all classes whose layout is known to native code be annotated
1889 * with [StructLayout (LayoutKind.Sequential)]
1890 * Value types have gc_aware_layout disabled by default, as per
1891 * what the default is for other runtimes.
1893 /* corlib is missing [StructLayout] directives in many places */
1894 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1895 if (!klass->valuetype)
1896 gc_aware_layout = TRUE;
1899 /* Compute klass->has_references */
1901 * Process non-static fields first, since static fields might recursively
1902 * refer to the class itself.
1904 for (i = 0; i < top; i++) {
1907 field = &klass->fields [i];
1909 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1910 ftype = mono_type_get_underlying_type (field->type);
1911 ftype = mono_type_get_basic_type_from_generic (ftype);
1912 if (type_has_references (klass, ftype))
1913 klass->has_references = TRUE;
1917 for (i = 0; i < top; i++) {
1920 field = &klass->fields [i];
1922 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1923 ftype = mono_type_get_underlying_type (field->type);
1924 ftype = mono_type_get_basic_type_from_generic (ftype);
1925 if (type_has_references (klass, ftype))
1926 klass->has_static_refs = TRUE;
1930 for (i = 0; i < top; i++) {
1933 field = &klass->fields [i];
1935 ftype = mono_type_get_underlying_type (field->type);
1936 ftype = mono_type_get_basic_type_from_generic (ftype);
1937 if (type_has_references (klass, ftype)) {
1938 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1939 klass->has_static_refs = TRUE;
1941 klass->has_references = TRUE;
1946 * Compute field layout and total size (not considering static fields)
1949 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1950 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1952 if (gc_aware_layout)
1957 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1960 if (klass->parent) {
1961 mono_class_setup_fields (klass->parent);
1962 if (mono_class_has_failure (klass->parent)) {
1963 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1966 real_size = klass->parent->instance_size;
1968 real_size = sizeof (MonoObject);
1971 for (pass = 0; pass < passes; ++pass) {
1972 for (i = 0; i < top; i++){
1977 field = &klass->fields [i];
1979 if (mono_field_is_deleted (field))
1981 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1984 ftype = mono_type_get_underlying_type (field->type);
1985 ftype = mono_type_get_basic_type_from_generic (ftype);
1986 if (gc_aware_layout) {
1987 if (type_has_references (klass, ftype)) {
1996 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1997 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1998 /* This field is a hack inserted by MCS to empty structures */
2002 size = mono_type_size (field->type, &align);
2004 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
2005 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2006 /* if the field has managed references, we need to force-align it
2009 if (type_has_references (klass, ftype))
2010 align = MAX (align, sizeof (gpointer));
2012 klass->min_align = MAX (align, klass->min_align);
2013 field->offset = real_size;
2015 field->offset += align - 1;
2016 field->offset &= ~(align - 1);
2018 /*TypeBuilders produce all sort of weird things*/
2019 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
2020 real_size = field->offset + size;
2023 instance_size = MAX (real_size, instance_size);
2025 if (instance_size & (klass->min_align - 1)) {
2026 instance_size += klass->min_align - 1;
2027 instance_size &= ~(klass->min_align - 1);
2031 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
2035 for (i = 0; i < top; i++) {
2040 field = &klass->fields [i];
2043 * There must be info about all the fields in a type if it
2044 * uses explicit layout.
2046 if (mono_field_is_deleted (field))
2048 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2051 size = mono_type_size (field->type, &align);
2052 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2053 klass->min_align = MAX (align, klass->min_align);
2056 * When we get here, field->offset is already set by the
2057 * loader (for either runtime fields or fields loaded from metadata).
2058 * The offset is from the start of the object: this works for both
2059 * classes and valuetypes.
2061 field->offset += sizeof (MonoObject);
2062 ftype = mono_type_get_underlying_type (field->type);
2063 ftype = mono_type_get_basic_type_from_generic (ftype);
2064 if (type_has_references (klass, ftype)) {
2065 if (field->offset % sizeof (gpointer)) {
2066 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2073 real_size = MAX (real_size, size + field->offset);
2076 if (klass->has_references) {
2077 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2079 /* Check for overlapping reference and non-reference fields */
2080 for (i = 0; i < top; i++) {
2083 field = &klass->fields [i];
2085 if (mono_field_is_deleted (field))
2087 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2089 ftype = mono_type_get_underlying_type (field->type);
2090 if (MONO_TYPE_IS_REFERENCE (ftype))
2091 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2093 for (i = 0; i < top; i++) {
2094 field = &klass->fields [i];
2096 if (mono_field_is_deleted (field))
2098 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2101 // FIXME: Too much code does this
2103 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2104 char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", klass->name, field->offset);
2105 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2109 g_free (ref_bitmap);
2112 instance_size = MAX (real_size, instance_size);
2113 if (instance_size & (klass->min_align - 1)) {
2114 instance_size += klass->min_align - 1;
2115 instance_size &= ~(klass->min_align - 1);
2121 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2123 * This leads to all kinds of problems with nested structs, so only
2124 * enable it when a MONO_DEBUG property is set.
2126 * For small structs, set min_align to at least the struct size to improve
2127 * performance, and since the JIT memset/memcpy code assumes this and generates
2128 * unaligned accesses otherwise. See #78990 for a testcase.
2130 if (mono_align_small_structs) {
2131 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2132 klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
2136 if (klass->instance_size && !klass->image->dynamic) {
2137 /* Might be already set using cached info */
2138 g_assert (klass->instance_size == instance_size);
2140 klass->instance_size = instance_size;
2142 mono_memory_barrier ();
2143 klass->size_inited = 1;
2146 * Compute static field layout and size
2148 for (i = 0; i < top; i++){
2152 field = &klass->fields [i];
2154 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2156 if (mono_field_is_deleted (field))
2159 if (mono_type_has_exceptions (field->type)) {
2160 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2164 has_static_fields = TRUE;
2166 size = mono_type_size (field->type, &align);
2167 field->offset = klass->sizes.class_size;
2168 /*align is always non-zero here*/
2169 field->offset += align - 1;
2170 field->offset &= ~(align - 1);
2171 klass->sizes.class_size = field->offset + size;
2174 if (has_static_fields && klass->sizes.class_size == 0)
2175 /* Simplify code which depends on class_size != 0 if the class has static fields */
2176 klass->sizes.class_size = 8;
2180 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2184 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2185 method->klass = klass;
2186 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2187 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2188 method->signature = sig;
2189 method->name = name;
2192 if (name [0] == '.') {
2193 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2195 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2201 * mono_class_setup_methods:
2204 * Initializes the 'methods' array in CLASS.
2205 * Calling this method should be avoided if possible since it allocates a lot
2206 * of long-living MonoMethod structures.
2207 * Methods belonging to an interface are assigned a sequential slot starting
2210 * On failure this function sets klass->exception_type
2213 mono_class_setup_methods (MonoClass *klass)
2216 MonoMethod **methods;
2221 if (klass->generic_class) {
2223 MonoClass *gklass = klass->generic_class->container_class;
2225 mono_class_init (gklass);
2226 if (!mono_class_has_failure (gklass))
2227 mono_class_setup_methods (gklass);
2228 if (mono_class_has_failure (gklass)) {
2229 /* FIXME make exception_data less opaque so it's possible to dup it here */
2230 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2234 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2235 count = gklass->method.count;
2236 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2238 for (i = 0; i < count; i++) {
2239 methods [i] = mono_class_inflate_generic_method_full_checked (
2240 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2241 if (!mono_error_ok (&error)) {
2242 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2243 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not inflate method %s due to %s", method, mono_error_get_message (&error)));
2246 mono_error_cleanup (&error);
2250 } else if (klass->rank) {
2252 MonoMethod *amethod;
2253 MonoMethodSignature *sig;
2254 int count_generic = 0, first_generic = 0;
2256 gboolean jagged_ctor = FALSE;
2258 count = 3 + (klass->rank > 1? 2: 1);
2260 mono_class_setup_interfaces (klass, &error);
2261 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2263 if (klass->rank == 1 && klass->element_class->rank) {
2265 klass->method.count ++;
2268 if (klass->interface_count) {
2269 count_generic = generic_array_methods (klass);
2270 first_generic = count;
2271 count += klass->interface_count * count_generic;
2274 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2276 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2277 sig->ret = &mono_defaults.void_class->byval_arg;
2278 sig->pinvoke = TRUE;
2279 sig->hasthis = TRUE;
2280 for (i = 0; i < klass->rank; ++i)
2281 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2283 amethod = create_array_method (klass, ".ctor", sig);
2284 methods [method_num++] = amethod;
2285 if (klass->rank > 1) {
2286 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2287 sig->ret = &mono_defaults.void_class->byval_arg;
2288 sig->pinvoke = TRUE;
2289 sig->hasthis = TRUE;
2290 for (i = 0; i < klass->rank * 2; ++i)
2291 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2293 amethod = create_array_method (klass, ".ctor", sig);
2294 methods [method_num++] = amethod;
2298 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2299 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2300 sig->ret = &mono_defaults.void_class->byval_arg;
2301 sig->pinvoke = TRUE;
2302 sig->hasthis = TRUE;
2303 for (i = 0; i < klass->rank + 1; ++i)
2304 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2305 amethod = create_array_method (klass, ".ctor", sig);
2306 methods [method_num++] = amethod;
2309 /* element Get (idx11, [idx2, ...]) */
2310 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2311 sig->ret = &klass->element_class->byval_arg;
2312 sig->pinvoke = TRUE;
2313 sig->hasthis = TRUE;
2314 for (i = 0; i < klass->rank; ++i)
2315 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2316 amethod = create_array_method (klass, "Get", sig);
2317 methods [method_num++] = amethod;
2318 /* element& Address (idx11, [idx2, ...]) */
2319 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2320 sig->ret = &klass->element_class->this_arg;
2321 sig->pinvoke = TRUE;
2322 sig->hasthis = TRUE;
2323 for (i = 0; i < klass->rank; ++i)
2324 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2325 amethod = create_array_method (klass, "Address", sig);
2326 methods [method_num++] = amethod;
2327 /* void Set (idx11, [idx2, ...], element) */
2328 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2329 sig->ret = &mono_defaults.void_class->byval_arg;
2330 sig->pinvoke = TRUE;
2331 sig->hasthis = TRUE;
2332 for (i = 0; i < klass->rank; ++i)
2333 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2334 sig->params [i] = &klass->element_class->byval_arg;
2335 amethod = create_array_method (klass, "Set", sig);
2336 methods [method_num++] = amethod;
2338 for (i = 0; i < klass->interface_count; i++)
2339 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2343 count = klass->method.count;
2344 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2345 for (i = 0; i < count; ++i) {
2346 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2347 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2349 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load method %d due to %s", i, mono_error_get_message (&error)));
2350 mono_error_cleanup (&error);
2355 if (MONO_CLASS_IS_INTERFACE (klass)) {
2357 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2358 for (i = 0; i < count; ++i) {
2359 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2360 methods [i]->slot = slot++;
2364 mono_image_lock (klass->image);
2366 if (!klass->methods) {
2367 klass->method.count = count;
2369 /* Needed because of the double-checking locking pattern */
2370 mono_memory_barrier ();
2372 klass->methods = methods;
2375 mono_image_unlock (klass->image);
2379 * mono_class_get_method_by_index:
2381 * Returns klass->methods [index], initializing klass->methods if neccesary.
2383 * LOCKING: Acquires the loader lock.
2386 mono_class_get_method_by_index (MonoClass *klass, int index)
2389 /* Avoid calling setup_methods () if possible */
2390 if (klass->generic_class && !klass->methods) {
2391 MonoClass *gklass = klass->generic_class->container_class;
2394 m = mono_class_inflate_generic_method_full_checked (
2395 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2396 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2398 * If setup_methods () is called later for this class, no duplicates are created,
2399 * since inflate_generic_method guarantees that only one instance of a method
2400 * is created for each context.
2403 mono_class_setup_methods (klass);
2404 g_assert (m == klass->methods [index]);
2408 mono_class_setup_methods (klass);
2409 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2411 g_assert (index >= 0 && index < klass->method.count);
2412 return klass->methods [index];
2417 * mono_class_get_inflated_method:
2419 * Given an inflated class CLASS and a method METHOD which should be a method of
2420 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2423 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2425 MonoClass *gklass = klass->generic_class->container_class;
2428 g_assert (method->klass == gklass);
2430 mono_class_setup_methods (gklass);
2431 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2433 for (i = 0; i < gklass->method.count; ++i) {
2434 if (gklass->methods [i] == method) {
2435 if (klass->methods) {
2436 return klass->methods [i];
2439 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2440 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2450 * mono_class_get_vtable_entry:
2452 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2453 * LOCKING: Acquires the loader lock.
2456 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2460 if (klass->rank == 1) {
2462 * szarrays do not overwrite any methods of Array, so we can avoid
2463 * initializing their vtables in some cases.
2465 mono_class_setup_vtable (klass->parent);
2466 if (offset < klass->parent->vtable_size)
2467 return klass->parent->vtable [offset];
2470 if (klass->generic_class) {
2472 MonoClass *gklass = klass->generic_class->container_class;
2473 mono_class_setup_vtable (gklass);
2474 m = gklass->vtable [offset];
2476 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2477 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2479 mono_class_setup_vtable (klass);
2480 if (mono_class_has_failure (klass))
2482 m = klass->vtable [offset];
2489 * mono_class_get_vtable_size:
2491 * Return the vtable size for KLASS.
2494 mono_class_get_vtable_size (MonoClass *klass)
2496 mono_class_setup_vtable (klass);
2498 return klass->vtable_size;
2502 * mono_class_setup_properties:
2504 * Initialize klass->ext.property and klass->ext.properties.
2506 * This method can fail the class.
2509 mono_class_setup_properties (MonoClass *klass)
2511 guint startm, endm, i, j;
2512 guint32 cols [MONO_PROPERTY_SIZE];
2513 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2514 MonoProperty *properties;
2518 if (klass->ext && klass->ext->properties)
2521 if (klass->generic_class) {
2522 MonoClass *gklass = klass->generic_class->container_class;
2524 mono_class_init (gklass);
2525 mono_class_setup_properties (gklass);
2526 if (mono_class_has_failure (gklass)) {
2527 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2531 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2533 for (i = 0; i < gklass->ext->property.count; i++) {
2535 MonoProperty *prop = &properties [i];
2537 *prop = gklass->ext->properties [i];
2540 prop->get = mono_class_inflate_generic_method_full_checked (
2541 prop->get, klass, mono_class_get_context (klass), &error);
2543 prop->set = mono_class_inflate_generic_method_full_checked (
2544 prop->set, klass, mono_class_get_context (klass), &error);
2546 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2547 prop->parent = klass;
2550 first = gklass->ext->property.first;
2551 count = gklass->ext->property.count;
2553 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2554 count = last - first;
2557 mono_class_setup_methods (klass);
2558 if (mono_class_has_failure (klass))
2562 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2563 for (i = first; i < last; ++i) {
2564 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2565 properties [i - first].parent = klass;
2566 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2567 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2569 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2570 for (j = startm; j < endm; ++j) {
2573 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2575 if (klass->image->uncompressed_metadata) {
2577 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2578 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2579 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2581 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2584 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2585 case METHOD_SEMANTIC_SETTER:
2586 properties [i - first].set = method;
2588 case METHOD_SEMANTIC_GETTER:
2589 properties [i - first].get = method;
2598 mono_class_alloc_ext (klass);
2600 mono_image_lock (klass->image);
2602 if (klass->ext->properties) {
2603 /* We leak 'properties' which was allocated from the image mempool */
2604 mono_image_unlock (klass->image);
2608 klass->ext->property.first = first;
2609 klass->ext->property.count = count;
2611 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2612 mono_memory_barrier ();
2614 /* Leave this assignment as the last op in the function */
2615 klass->ext->properties = properties;
2617 mono_image_unlock (klass->image);
2621 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2623 MonoMethod **om, **retval;
2626 for (om = methods, count = 0; *om; ++om, ++count)
2629 retval = g_new0 (MonoMethod*, count + 1);
2631 for (om = methods, count = 0; *om; ++om, ++count) {
2633 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2634 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2640 /*This method can fail the class.*/
2642 mono_class_setup_events (MonoClass *klass)
2645 guint startm, endm, i, j;
2646 guint32 cols [MONO_EVENT_SIZE];
2647 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2651 if (klass->ext && klass->ext->events)
2654 if (klass->generic_class) {
2655 MonoClass *gklass = klass->generic_class->container_class;
2656 MonoGenericContext *context = NULL;
2658 mono_class_setup_events (gklass);
2659 if (mono_class_has_failure (gklass)) {
2660 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2664 first = gklass->ext->event.first;
2665 count = gklass->ext->event.count;
2667 events = mono_class_new0 (klass, MonoEvent, count);
2670 context = mono_class_get_context (klass);
2672 for (i = 0; i < count; i++) {
2674 MonoEvent *event = &events [i];
2675 MonoEvent *gevent = &gklass->ext->events [i];
2677 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2679 event->parent = klass;
2680 event->name = gevent->name;
2681 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2682 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2683 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2684 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2685 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2686 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2688 #ifndef MONO_SMALL_CONFIG
2689 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2691 event->attrs = gevent->attrs;
2694 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2695 count = last - first;
2698 mono_class_setup_methods (klass);
2699 if (mono_class_has_failure (klass)) {
2700 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2705 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2706 for (i = first; i < last; ++i) {
2707 MonoEvent *event = &events [i - first];
2709 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2710 event->parent = klass;
2711 event->attrs = cols [MONO_EVENT_FLAGS];
2712 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2714 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2715 for (j = startm; j < endm; ++j) {
2718 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2720 if (klass->image->uncompressed_metadata) {
2722 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2723 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2724 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2726 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2729 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2730 case METHOD_SEMANTIC_ADD_ON:
2731 event->add = method;
2733 case METHOD_SEMANTIC_REMOVE_ON:
2734 event->remove = method;
2736 case METHOD_SEMANTIC_FIRE:
2737 event->raise = method;
2739 case METHOD_SEMANTIC_OTHER: {
2740 #ifndef MONO_SMALL_CONFIG
2743 if (event->other == NULL) {
2744 event->other = g_new0 (MonoMethod*, 2);
2746 while (event->other [n])
2748 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2750 event->other [n] = method;
2751 /* NULL terminated */
2752 event->other [n + 1] = NULL;
2763 mono_class_alloc_ext (klass);
2765 mono_image_lock (klass->image);
2767 if (klass->ext->events) {
2768 mono_image_unlock (klass->image);
2772 klass->ext->event.first = first;
2773 klass->ext->event.count = count;
2775 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2776 mono_memory_barrier ();
2778 /* Leave this assignment as the last op in the function */
2779 klass->ext->events = events;
2781 mono_image_unlock (klass->image);
2785 * Global pool of interface IDs, represented as a bitset.
2786 * LOCKING: Protected by the classes lock.
2788 static MonoBitSet *global_interface_bitset = NULL;
2791 * mono_unload_interface_ids:
2792 * @bitset: bit set of interface IDs
2794 * When an image is unloaded, the interface IDs associated with
2795 * the image are put back in the global pool of IDs so the numbers
2799 mono_unload_interface_ids (MonoBitSet *bitset)
2802 mono_bitset_sub (global_interface_bitset, bitset);
2807 mono_unload_interface_id (MonoClass *klass)
2809 if (global_interface_bitset && klass->interface_id) {
2811 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2817 * mono_get_unique_iid:
2820 * Assign a unique integer ID to the interface represented by @class.
2821 * The ID will positive and as small as possible.
2822 * LOCKING: Acquires the classes lock.
2823 * Returns: The new ID.
2826 mono_get_unique_iid (MonoClass *klass)
2830 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2834 if (!global_interface_bitset) {
2835 global_interface_bitset = mono_bitset_new (128, 0);
2838 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2840 int old_size = mono_bitset_size (global_interface_bitset);
2841 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2842 mono_bitset_free (global_interface_bitset);
2843 global_interface_bitset = new_set;
2846 mono_bitset_set (global_interface_bitset, iid);
2847 /* set the bit also in the per-image set */
2848 if (!klass->generic_class) {
2849 if (klass->image->interface_bitset) {
2850 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2851 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2852 mono_bitset_free (klass->image->interface_bitset);
2853 klass->image->interface_bitset = new_set;
2856 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2858 mono_bitset_set (klass->image->interface_bitset, iid);
2863 #ifndef MONO_SMALL_CONFIG
2864 if (mono_print_vtable) {
2866 char *type_name = mono_type_full_name (&klass->byval_arg);
2867 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2868 generic_id = klass->generic_class->context.class_inst->id;
2869 g_assert (generic_id != 0);
2873 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2878 g_assert (iid <= 65535);
2883 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2888 mono_class_setup_interfaces (klass, error);
2889 return_if_nok (error);
2891 for (i = 0; i < klass->interface_count; i++) {
2892 ic = klass->interfaces [i];
2895 *res = g_ptr_array_new ();
2896 g_ptr_array_add (*res, ic);
2897 mono_class_init (ic);
2898 if (mono_class_has_failure (ic)) {
2899 mono_error_set_type_load_class (error, ic, "Error Loading class");
2903 collect_implemented_interfaces_aux (ic, res, error);
2904 return_if_nok (error);
2909 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2911 GPtrArray *res = NULL;
2913 collect_implemented_interfaces_aux (klass, &res, error);
2914 if (!mono_error_ok (error)) {
2916 g_ptr_array_free (res, TRUE);
2923 compare_interface_ids (const void *p_key, const void *p_element) {
2924 const MonoClass *key = (const MonoClass *)p_key;
2925 const MonoClass *element = *(const MonoClass **)p_element;
2927 return (key->interface_id - element->interface_id);
2930 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2932 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2933 MonoClass **result = (MonoClass **)mono_binary_search (
2935 klass->interfaces_packed,
2936 klass->interface_offsets_count,
2937 sizeof (MonoClass *),
2938 compare_interface_ids);
2940 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2947 * mono_class_interface_offset_with_variance:
2949 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2950 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2952 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2954 * FIXME figure out MS disambiguation rules and fix this function.
2957 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2958 int i = mono_class_interface_offset (klass, itf);
2959 *non_exact_match = FALSE;
2963 if (!mono_class_has_variant_generic_params (itf))
2966 for (i = 0; i < klass->interface_offsets_count; i++) {
2967 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2968 *non_exact_match = TRUE;
2969 return klass->interface_offsets_packed [i];
2977 print_implemented_interfaces (MonoClass *klass) {
2980 GPtrArray *ifaces = NULL;
2982 int ancestor_level = 0;
2984 name = mono_type_get_full_name (klass);
2985 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2988 for (i = 0; i < klass->interface_offsets_count; i++)
2989 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2990 klass->interfaces_packed [i]->interface_id,
2991 klass->interface_offsets_packed [i],
2992 klass->interfaces_packed [i]->method.count,
2993 klass->interfaces_packed [i]->name_space,
2994 klass->interfaces_packed [i]->name );
2995 printf ("Interface flags: ");
2996 for (i = 0; i <= klass->max_interface_id; i++)
2997 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2998 printf ("(%d,T)", i);
3000 printf ("(%d,F)", i);
3002 printf ("Dump interface flags:");
3003 #ifdef COMPRESSED_INTERFACE_BITMAP
3005 const uint8_t* p = klass->interface_bitmap;
3006 i = klass->max_interface_id;
3008 printf (" %d x 00 %02X", p [0], p [1]);
3014 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3015 printf (" %02X", klass->interface_bitmap [i]);
3018 while (klass != NULL) {
3019 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3020 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3021 if (!mono_error_ok (&error)) {
3022 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3023 mono_error_cleanup (&error);
3024 } else if (ifaces) {
3025 for (i = 0; i < ifaces->len; i++) {
3026 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3027 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3028 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3030 mono_class_interface_offset (klass, ic),
3035 g_ptr_array_free (ifaces, TRUE);
3038 klass = klass->parent;
3043 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3046 args [0] = &arg0->byval_arg;
3048 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3052 array_class_get_if_rank (MonoClass *klass, guint rank)
3054 return rank ? mono_array_class_get (klass, rank) : klass;
3058 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3060 valuetype_types [0] = eclass;
3061 if (eclass == mono_defaults.int16_class)
3062 valuetype_types [1] = mono_defaults.uint16_class;
3063 else if (eclass == mono_defaults.uint16_class)
3064 valuetype_types [1] = mono_defaults.int16_class;
3065 else if (eclass == mono_defaults.int32_class)
3066 valuetype_types [1] = mono_defaults.uint32_class;
3067 else if (eclass == mono_defaults.uint32_class)
3068 valuetype_types [1] = mono_defaults.int32_class;
3069 else if (eclass == mono_defaults.int64_class)
3070 valuetype_types [1] = mono_defaults.uint64_class;
3071 else if (eclass == mono_defaults.uint64_class)
3072 valuetype_types [1] = mono_defaults.int64_class;
3073 else if (eclass == mono_defaults.byte_class)
3074 valuetype_types [1] = mono_defaults.sbyte_class;
3075 else if (eclass == mono_defaults.sbyte_class)
3076 valuetype_types [1] = mono_defaults.byte_class;
3077 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3078 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3081 /* this won't be needed once bug #325495 is completely fixed
3082 * though we'll need something similar to know which interfaces to allow
3083 * in arrays when they'll be lazyly created
3085 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3086 * MS returns diferrent types based on which instance is called. For example:
3087 * object obj = new byte[10][];
3088 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3089 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3092 * Fixing this should kill quite some code, save some bits and improve compatibility.
3095 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3097 MonoClass *eclass = klass->element_class;
3098 static MonoClass* generic_icollection_class = NULL;
3099 static MonoClass* generic_ienumerable_class = NULL;
3100 static MonoClass* generic_ienumerator_class = NULL;
3101 static MonoClass* generic_ireadonlylist_class = NULL;
3102 static MonoClass* generic_ireadonlycollection_class = NULL;
3103 MonoClass *valuetype_types[2] = { NULL, NULL };
3104 MonoClass **interfaces = NULL;
3105 int i, nifaces, interface_count, real_count, original_rank;
3107 gboolean internal_enumerator;
3108 gboolean eclass_is_valuetype;
3110 if (!mono_defaults.generic_ilist_class) {
3114 internal_enumerator = FALSE;
3115 eclass_is_valuetype = FALSE;
3116 original_rank = eclass->rank;
3117 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3118 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3120 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3122 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3123 original_rank = eclass->rank;
3125 eclass = eclass->element_class;
3126 internal_enumerator = TRUE;
3127 *is_enumerator = TRUE;
3135 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3136 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3138 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3140 if (!generic_icollection_class) {
3141 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3142 "System.Collections.Generic", "ICollection`1");
3143 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3144 "System.Collections.Generic", "IEnumerable`1");
3145 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3146 "System.Collections.Generic", "IEnumerator`1");
3147 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3148 "System.Collections.Generic", "IReadOnlyList`1");
3149 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3150 "System.Collections.Generic", "IReadOnlyCollection`1");
3153 mono_class_init (eclass);
3156 * Arrays in 2.0 need to implement a number of generic interfaces
3157 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3158 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3159 * We collect the types needed to build the
3160 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3161 * the generic interfaces needed to implement.
3163 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3164 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3166 if (eclass->valuetype) {
3167 nifaces = generic_ireadonlylist_class ? 5 : 3;
3168 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3170 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3171 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3172 if (internal_enumerator) {
3174 if (valuetype_types [1])
3178 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3179 interfaces [0] = valuetype_types [0];
3180 if (valuetype_types [1])
3181 interfaces [nifaces] = valuetype_types [1];
3183 eclass_is_valuetype = TRUE;
3186 int idepth = eclass->idepth;
3187 if (!internal_enumerator)
3189 nifaces = generic_ireadonlylist_class ? 2 : 3;
3191 // FIXME: This doesn't seem to work/required for generic params
3192 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3193 mono_class_setup_interface_offsets (eclass);
3195 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3196 /* we add object for interfaces and the supertypes for the other
3197 * types. The last of the supertypes is the element class itself which we
3198 * already created the explicit interfaces for (so we include it for IEnumerator
3199 * and exclude it for arrays).
3201 if (MONO_CLASS_IS_INTERFACE (eclass))
3204 interface_count += idepth;
3205 if (eclass->rank && eclass->element_class->valuetype) {
3206 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3207 if (valuetype_types [1])
3210 /* IList, ICollection, IEnumerable, IReadOnlyList */
3211 interface_count *= nifaces;
3212 real_count = interface_count;
3213 if (internal_enumerator) {
3214 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3215 if (valuetype_types [1])
3218 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3219 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3220 interfaces [0] = mono_defaults.object_class;
3224 for (i = 0; i < idepth; i++) {
3225 mono_class_init (eclass->supertypes [i]);
3226 interfaces [j] = eclass->supertypes [i];
3230 if (all_interfaces) {
3231 for (i = 0; i < eclass->interface_offsets_count; i++) {
3232 interfaces [j] = eclass->interfaces_packed [i];
3236 for (i = 0; i < eclass->interface_count; i++) {
3237 interfaces [j] = eclass->interfaces [i];
3241 if (valuetype_types [1]) {
3242 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3247 /* instantiate the generic interfaces */
3248 for (i = 0; i < interface_count; i += nifaces) {
3249 MonoClass *iface = interfaces [i];
3251 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3252 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3254 if (eclass->valuetype) {
3255 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3256 if (generic_ireadonlylist_class) {
3257 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3258 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3261 if (!generic_ireadonlylist_class)
3262 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3265 if (internal_enumerator) {
3267 /* instantiate IEnumerator<iface> */
3268 for (i = 0; i < interface_count; i++) {
3269 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3271 j = interface_count;
3272 if (!eclass_is_valuetype) {
3273 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3274 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3277 for (i = 0; i < eclass->idepth; i++) {
3278 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3282 for (i = 0; i < eclass->interface_offsets_count; i++) {
3283 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3287 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3289 if (valuetype_types [1])
3290 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3294 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3295 for (i = 0; i < real_count; ++i) {
3296 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3297 g_print ("%s implements %s\n", type_name, name);
3308 find_array_interface (MonoClass *klass, const char *name)
3311 for (i = 0; i < klass->interface_count; ++i) {
3312 if (strcmp (klass->interfaces [i]->name, name) == 0)
3319 * Return the number of virtual methods.
3320 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3321 * Return -1 on failure.
3322 * FIXME It would be nice if this information could be cached somewhere.
3325 count_virtual_methods (MonoClass *klass)
3329 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3331 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3332 mono_class_setup_methods (klass);
3333 if (mono_class_has_failure (klass))
3336 for (i = 0; i < klass->method.count; ++i) {
3337 flags = klass->methods [i]->flags;
3338 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3342 for (i = 0; i < klass->method.count; ++i) {
3343 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3345 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3353 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3361 m = (l + num_ifaces) / 2;
3362 if (interfaces_full [m] == ic)
3364 if (l == num_ifaces)
3366 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3375 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3377 int i = find_interface (num_ifaces, interfaces_full, ic);
3379 return interface_offsets_full [i];
3384 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3386 int i = find_interface (num_ifaces, interfaces_full, ic);
3390 interface_offsets_full [i] = offset;
3393 for (i = 0; i < num_ifaces; ++i) {
3394 if (interfaces_full [i]) {
3396 if (interfaces_full [i]->interface_id < ic->interface_id)
3399 while (end < num_ifaces && interfaces_full [end]) end++;
3400 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3401 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3403 interfaces_full [i] = ic;
3404 interface_offsets_full [i] = offset;
3410 #ifdef COMPRESSED_INTERFACE_BITMAP
3413 * Compressed interface bitmap design.
3415 * Interface bitmaps take a large amount of memory, because their size is
3416 * linear with the maximum interface id assigned in the process (each interface
3417 * is assigned a unique id as it is loaded). The number of interface classes
3418 * is high because of the many implicit interfaces implemented by arrays (we'll
3419 * need to lazy-load them in the future).
3420 * Most classes implement a very small number of interfaces, so the bitmap is
3421 * sparse. This bitmap needs to be checked by interface casts, so access to the
3422 * needed bit must be fast and doable with few jit instructions.
3424 * The current compression format is as follows:
3425 * *) it is a sequence of one or more two-byte elements
3426 * *) the first byte in the element is the count of empty bitmap bytes
3427 * at the current bitmap position
3428 * *) the second byte in the element is an actual bitmap byte at the current
3431 * As an example, the following compressed bitmap bytes:
3432 * 0x07 0x01 0x00 0x7
3433 * correspond to the following bitmap:
3434 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3436 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3437 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3438 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3442 * mono_compress_bitmap:
3443 * @dest: destination buffer
3444 * @bitmap: bitmap buffer
3445 * @size: size of @bitmap in bytes
3447 * This is a mono internal function.
3448 * The @bitmap data is compressed into a format that is small but
3449 * still searchable in few instructions by the JIT and runtime.
3450 * The compressed data is stored in the buffer pointed to by the
3451 * @dest array. Passing a #NULL value for @dest allows to just compute
3452 * the size of the buffer.
3453 * This compression algorithm assumes the bits set in the bitmap are
3454 * few and far between, like in interface bitmaps.
3455 * Returns: The size of the compressed bitmap in bytes.
3458 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3462 const uint8_t *end = bitmap + size;
3463 while (bitmap < end) {
3464 if (*bitmap || numz == 255) {
3488 * mono_class_interface_match:
3489 * @bitmap: a compressed bitmap buffer
3490 * @id: the index to check in the bitmap
3492 * This is a mono internal function.
3493 * Checks if a bit is set in a compressed interface bitmap. @id must
3494 * be already checked for being smaller than the maximum id encoded in the
3497 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3501 mono_class_interface_match (const uint8_t *bitmap, int id)
3504 id -= bitmap [0] * 8;
3508 return bitmap [1] & (1 << id);
3517 * LOCKING: this is supposed to be called with the loader lock held.
3518 * Return -1 on failure and set exception_type
3521 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3525 int i, j, max_iid, num_ifaces;
3526 MonoClass **interfaces_full = NULL;
3527 int *interface_offsets_full = NULL;
3529 GPtrArray **ifaces_array = NULL;
3530 int interface_offsets_count;
3531 MonoClass **array_interfaces = NULL;
3532 int num_array_interfaces;
3533 int is_enumerator = FALSE;
3535 mono_class_setup_supertypes (klass);
3537 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3538 * implicit interfaces have the property that they are assigned the same slot in the
3539 * vtables for compatible interfaces
3541 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3543 /* compute maximum number of slots and maximum interface id */
3545 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3546 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3547 for (j = 0; j < klass->idepth; j++) {
3548 k = klass->supertypes [j];
3549 num_ifaces += k->interface_count;
3550 for (i = 0; i < k->interface_count; i++) {
3551 ic = k->interfaces [i];
3554 mono_class_init (ic);
3556 if (max_iid < ic->interface_id)
3557 max_iid = ic->interface_id;
3559 ifaces = mono_class_get_implemented_interfaces (k, &error);
3560 if (!mono_error_ok (&error)) {
3561 char *name = mono_type_get_full_name (k);
3562 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error)));
3564 mono_error_cleanup (&error);
3569 num_ifaces += ifaces->len;
3570 for (i = 0; i < ifaces->len; ++i) {
3571 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3572 if (max_iid < ic->interface_id)
3573 max_iid = ic->interface_id;
3575 ifaces_array [j] = ifaces;
3579 for (i = 0; i < num_array_interfaces; ++i) {
3580 ic = array_interfaces [i];
3581 mono_class_init (ic);
3582 if (max_iid < ic->interface_id)
3583 max_iid = ic->interface_id;
3586 if (MONO_CLASS_IS_INTERFACE (klass)) {
3588 if (max_iid < klass->interface_id)
3589 max_iid = klass->interface_id;
3591 klass->max_interface_id = max_iid;
3592 /* compute vtable offset for interfaces */
3593 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3594 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3596 for (i = 0; i < num_ifaces; i++) {
3597 interface_offsets_full [i] = -1;
3600 /* skip the current class */
3601 for (j = 0; j < klass->idepth - 1; j++) {
3602 k = klass->supertypes [j];
3603 ifaces = ifaces_array [j];
3606 for (i = 0; i < ifaces->len; ++i) {
3608 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3610 /*Force the sharing of interface offsets between parent and subtypes.*/
3611 io = mono_class_interface_offset (k, ic);
3613 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3618 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3619 ifaces = ifaces_array [klass->idepth - 1];
3621 for (i = 0; i < ifaces->len; ++i) {
3623 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3624 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3626 count = count_virtual_methods (ic);
3628 char *name = mono_type_get_full_name (ic);
3629 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3638 if (MONO_CLASS_IS_INTERFACE (klass))
3639 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3641 if (num_array_interfaces) {
3642 if (is_enumerator) {
3643 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3644 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3645 g_assert (ienumerator_offset >= 0);
3646 for (i = 0; i < num_array_interfaces; ++i) {
3647 ic = array_interfaces [i];
3648 if (strcmp (ic->name, "IEnumerator`1") == 0)
3649 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3651 g_assert_not_reached ();
3652 /*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);*/
3655 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3656 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3657 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3658 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3659 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3660 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3661 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3662 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3663 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3664 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3665 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3666 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3667 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3668 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3669 for (i = 0; i < num_array_interfaces; ++i) {
3671 ic = array_interfaces [i];
3672 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3673 offset = ilist_offset;
3674 else if (strcmp (ic->name, "ICollection`1") == 0)
3675 offset = icollection_offset;
3676 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3677 offset = ienumerable_offset;
3678 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3679 offset = ireadonlylist_offset;
3680 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3681 offset = ireadonlycollection_offset;
3683 g_assert_not_reached ();
3684 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3685 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3690 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3691 if (interface_offsets_full [i] != -1) {
3692 interface_offsets_count ++;
3697 * We might get called multiple times:
3698 * - mono_class_init ()
3699 * - mono_class_setup_vtable ().
3700 * - mono_class_setup_interface_offsets ().
3701 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3702 * means we have to overwrite those when called from other places (#4440).
3704 if (klass->interfaces_packed) {
3706 g_assert (klass->interface_offsets_count == interface_offsets_count);
3710 klass->interface_offsets_count = interface_offsets_count;
3711 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3712 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3713 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3714 #ifdef COMPRESSED_INTERFACE_BITMAP
3715 bitmap = g_malloc0 (bsize);
3717 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3719 for (i = 0; i < interface_offsets_count; i++) {
3720 int id = interfaces_full [i]->interface_id;
3721 bitmap [id >> 3] |= (1 << (id & 7));
3722 klass->interfaces_packed [i] = interfaces_full [i];
3723 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3724 /*if (num_array_interfaces)
3725 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]);*/
3727 #ifdef COMPRESSED_INTERFACE_BITMAP
3728 i = mono_compress_bitmap (NULL, bitmap, bsize);
3729 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3730 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3733 klass->interface_bitmap = bitmap;
3738 g_free (interfaces_full);
3739 g_free (interface_offsets_full);
3740 g_free (array_interfaces);
3741 for (i = 0; i < klass->idepth; i++) {
3742 ifaces = ifaces_array [i];
3744 g_ptr_array_free (ifaces, TRUE);
3746 g_free (ifaces_array);
3748 //printf ("JUST DONE: ");
3749 //print_implemented_interfaces (klass);
3755 * Setup interface offsets for interfaces.
3757 * - klass->max_interface_id
3758 * - klass->interface_offsets_count
3759 * - klass->interfaces_packed
3760 * - klass->interface_offsets_packed
3761 * - klass->interface_bitmap
3763 * This function can fail @class.
3766 mono_class_setup_interface_offsets (MonoClass *klass)
3768 mono_loader_lock ();
3770 setup_interface_offsets (klass, 0, FALSE);
3772 mono_loader_unlock ();
3775 /*Checks if @klass has @parent as one of it's parents type gtd
3779 * Bar<T> : Foo<Bar<Bar<T>>>
3783 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3785 klass = mono_class_get_generic_type_definition (klass);
3786 parent = mono_class_get_generic_type_definition (parent);
3787 mono_class_setup_supertypes (klass);
3788 mono_class_setup_supertypes (parent);
3790 return klass->idepth >= parent->idepth &&
3791 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3795 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3797 MonoGenericInst *ginst;
3799 if (!klass->generic_class) {
3800 mono_class_setup_vtable_full (klass, in_setup);
3801 return !mono_class_has_failure (klass);
3804 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3805 if (mono_class_has_failure (klass->generic_class->container_class)) {
3806 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3810 ginst = klass->generic_class->context.class_inst;
3811 for (i = 0; i < ginst->type_argc; ++i) {
3813 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3815 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3816 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3817 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3819 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3820 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3828 * mono_class_setup_vtable:
3830 * Creates the generic vtable of CLASS.
3831 * Initializes the following fields in MonoClass:
3834 * Plus all the fields initialized by setup_interface_offsets ().
3835 * If there is an error during vtable construction, klass->exception_type is set.
3837 * LOCKING: Acquires the loader lock.
3840 mono_class_setup_vtable (MonoClass *klass)
3842 mono_class_setup_vtable_full (klass, NULL);
3846 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3849 MonoMethod **overrides;
3850 MonoGenericContext *context;
3858 if (MONO_CLASS_IS_INTERFACE (klass)) {
3859 /* This sets method->slot for all methods if this is an interface */
3860 mono_class_setup_methods (klass);
3864 if (mono_class_has_failure (klass))
3867 if (g_list_find (in_setup, klass))
3870 mono_loader_lock ();
3872 if (klass->vtable) {
3873 mono_loader_unlock ();
3877 mono_stats.generic_vtable_count ++;
3878 in_setup = g_list_prepend (in_setup, klass);
3880 if (klass->generic_class) {
3881 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3882 mono_loader_unlock ();
3883 g_list_remove (in_setup, klass);
3887 context = mono_class_get_context (klass);
3888 type_token = klass->generic_class->container_class->type_token;
3890 context = (MonoGenericContext *) klass->generic_container;
3891 type_token = klass->type_token;
3894 if (image_is_dynamic (klass->image)) {
3895 /* Generic instances can have zero method overrides without causing any harm.
3896 * This is true since we don't do layout all over again for them, we simply inflate
3897 * the layout of the parent.
3899 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3900 if (!is_ok (&error)) {
3901 mono_loader_unlock ();
3902 g_list_remove (in_setup, klass);
3903 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf("Could not load list of method overrides due to %s", mono_error_get_message (&error)));
3904 mono_error_cleanup (&error);
3908 /* The following call fails if there are missing methods in the type */
3909 /* FIXME it's probably a good idea to avoid this for generic instances. */
3910 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3914 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3916 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3920 mono_loader_unlock ();
3921 g_list_remove (in_setup, klass);
3926 #define DEBUG_INTERFACE_VTABLE_CODE 0
3927 #define TRACE_INTERFACE_VTABLE_CODE 0
3928 #define VERIFY_INTERFACE_VTABLE_CODE 0
3929 #define VTABLE_SELECTOR (1)
3931 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3932 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3933 if (!(VTABLE_SELECTOR)) break; \
3937 #define DEBUG_INTERFACE_VTABLE(stmt)
3940 #if TRACE_INTERFACE_VTABLE_CODE
3941 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3942 if (!(VTABLE_SELECTOR)) break; \
3946 #define TRACE_INTERFACE_VTABLE(stmt)
3949 #if VERIFY_INTERFACE_VTABLE_CODE
3950 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3951 if (!(VTABLE_SELECTOR)) break; \
3955 #define VERIFY_INTERFACE_VTABLE(stmt)
3959 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3961 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3965 GString *res = g_string_new ("");
3967 g_string_append_c (res, '(');
3968 for (i = 0; i < sig->param_count; ++i) {
3970 g_string_append_c (res, ',');
3971 mono_type_get_desc (res, sig->params [i], include_namespace);
3973 g_string_append (res, ")=>");
3974 if (sig->ret != NULL) {
3975 mono_type_get_desc (res, sig->ret, include_namespace);
3977 g_string_append (res, "NULL");
3980 g_string_free (res, FALSE);
3984 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3985 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3986 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3987 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3995 is_wcf_hack_disabled (void)
3997 static gboolean disabled;
3998 static gboolean inited = FALSE;
4000 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4007 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4009 MonoMethodSignature *cmsig, *imsig;
4010 if (strcmp (im->name, cm->name) == 0) {
4011 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4012 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4015 if (! slot_is_empty) {
4016 if (require_newslot) {
4017 if (! interface_is_explicitly_implemented_by_class) {
4018 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4021 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4022 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4026 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4029 cmsig = mono_method_signature (cm);
4030 imsig = mono_method_signature (im);
4031 if (!cmsig || !imsig) {
4032 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4036 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4037 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4038 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4039 TRACE_INTERFACE_VTABLE (printf ("]"));
4042 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4043 if (mono_security_core_clr_enabled ())
4044 mono_security_core_clr_check_override (klass, cm, im);
4046 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4047 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4048 char *body_name = mono_method_full_name (cm, TRUE);
4049 char *decl_name = mono_method_full_name (im, TRUE);
4050 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4058 MonoClass *ic = im->klass;
4059 const char *ic_name_space = ic->name_space;
4060 const char *ic_name = ic->name;
4063 if (! require_newslot) {
4064 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4067 if (cm->klass->rank == 0) {
4068 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4071 cmsig = mono_method_signature (cm);
4072 imsig = mono_method_signature (im);
4073 if (!cmsig || !imsig) {
4074 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4078 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4079 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4080 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4081 TRACE_INTERFACE_VTABLE (printf ("]"));
4084 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4085 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4088 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4089 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4092 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))) {
4093 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4097 subname = strstr (cm->name, ic_name_space);
4098 if (subname != cm->name) {
4099 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4102 subname += strlen (ic_name_space);
4103 if (subname [0] != '.') {
4104 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4108 if (strstr (subname, ic_name) != subname) {
4109 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4112 subname += strlen (ic_name);
4113 if (subname [0] != '.') {
4114 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4118 if (strcmp (subname, im->name) != 0) {
4119 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4123 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4124 if (mono_security_core_clr_enabled ())
4125 mono_security_core_clr_check_override (klass, cm, im);
4127 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4128 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4129 char *body_name = mono_method_full_name (cm, TRUE);
4130 char *decl_name = mono_method_full_name (im, TRUE);
4131 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4141 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4143 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4144 MonoMethod *method = key;
4145 MonoMethod *override = value;
4146 MonoClass *method_class = mono_method_get_class (method);
4147 MonoClass *override_class = mono_method_get_class (override);
4149 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4150 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4151 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4154 print_overrides (GHashTable *override_map, const char *message) {
4156 printf ("Override map \"%s\" START:\n", message);
4157 g_hash_table_foreach (override_map, foreach_override, NULL);
4158 printf ("Override map \"%s\" END.\n", message);
4160 printf ("Override map \"%s\" EMPTY.\n", message);
4164 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4165 char *full_name = mono_type_full_name (&klass->byval_arg);
4169 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4171 if (print_interfaces) {
4172 print_implemented_interfaces (klass);
4173 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4176 if (klass->parent) {
4177 parent_size = klass->parent->vtable_size;
4181 for (i = 0; i < size; ++i) {
4182 MonoMethod *cm = vtable [i];
4183 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4184 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4186 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4194 #if VERIFY_INTERFACE_VTABLE_CODE
4196 mono_method_try_get_vtable_index (MonoMethod *method)
4198 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4199 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4200 if (imethod->declaring->is_generic)
4201 return imethod->declaring->slot;
4203 return method->slot;
4207 mono_class_verify_vtable (MonoClass *klass)
4210 char *full_name = mono_type_full_name (&klass->byval_arg);
4212 printf ("*** Verifying VTable of class '%s' \n", full_name);
4216 if (!klass->methods)
4219 for (i = 0; i < klass->method.count; ++i) {
4220 MonoMethod *cm = klass->methods [i];
4223 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4227 full_name = mono_method_full_name (cm, TRUE);
4229 slot = mono_method_try_get_vtable_index (cm);
4231 if (slot >= klass->vtable_size) {
4232 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4236 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4237 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4238 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4239 g_free (other_name);
4242 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4249 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4251 char *method_signature;
4254 for (index = 0; index < onum; ++index) {
4255 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4256 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4258 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4259 type_name = mono_type_full_name (&klass->byval_arg);
4260 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4261 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4262 g_free (method_signature);
4264 mono_class_setup_methods (klass);
4265 if (mono_class_has_failure (klass)) {
4266 char *name = mono_type_get_full_name (klass);
4267 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4271 for (index = 0; index < klass->method.count; ++index) {
4272 MonoMethod *cm = klass->methods [index];
4273 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4275 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4276 g_free (method_signature);
4281 mono_method_get_method_definition (MonoMethod *method)
4283 while (method->is_inflated)
4284 method = ((MonoMethodInflated*)method)->declaring;
4289 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4293 for (i = 0; i < onum; ++i) {
4294 MonoMethod *decl = overrides [i * 2];
4295 MonoMethod *body = overrides [i * 2 + 1];
4297 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4298 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4302 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4303 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4304 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4306 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4310 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4311 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4312 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4314 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4318 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4319 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that is not extended or implemented by this type"));
4323 body = mono_method_get_method_definition (body);
4324 decl = mono_method_get_method_definition (decl);
4326 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4327 char *body_name = mono_method_full_name (body, TRUE);
4328 char *decl_name = mono_method_full_name (decl, TRUE);
4329 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4339 mono_class_need_stelemref_method (MonoClass *klass)
4341 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4345 * LOCKING: this is supposed to be called with the loader lock held.
4348 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4352 MonoMethod **vtable;
4353 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4354 GPtrArray *ifaces = NULL;
4355 GHashTable *override_map = NULL;
4357 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4358 int first_non_interface_slot;
4360 GSList *virt_methods = NULL, *l;
4361 int stelemref_slot = 0;
4366 if (overrides && !verify_class_overrides (klass, overrides, onum))
4369 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4370 if (!mono_error_ok (&error)) {
4371 char *name = mono_type_get_full_name (klass);
4372 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error)));
4374 mono_error_cleanup (&error);
4376 } else if (ifaces) {
4377 for (i = 0; i < ifaces->len; i++) {
4378 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4379 max_vtsize += ic->method.count;
4381 g_ptr_array_free (ifaces, TRUE);
4385 if (klass->parent) {
4386 mono_class_init (klass->parent);
4387 mono_class_setup_vtable_full (klass->parent, in_setup);
4389 if (mono_class_has_failure (klass->parent)) {
4390 char *name = mono_type_get_full_name (klass->parent);
4391 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4396 max_vtsize += klass->parent->vtable_size;
4397 cur_slot = klass->parent->vtable_size;
4400 max_vtsize += klass->method.count;
4402 /*Array have a slot for stelemref*/
4403 if (mono_class_need_stelemref_method (klass)) {
4404 stelemref_slot = cur_slot;
4409 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4410 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4412 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4414 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4415 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4418 max_iid = klass->max_interface_id;
4419 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4421 /* Optimized version for generic instances */
4422 if (klass->generic_class) {
4424 MonoClass *gklass = klass->generic_class->container_class;
4427 mono_class_setup_vtable_full (gklass, in_setup);
4428 if (mono_class_has_failure (gklass)) {
4429 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4433 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4434 klass->vtable_size = gklass->vtable_size;
4435 for (i = 0; i < gklass->vtable_size; ++i)
4436 if (gklass->vtable [i]) {
4437 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4438 if (!mono_error_ok (&error)) {
4439 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4440 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4442 mono_error_cleanup (&error);
4446 tmp [i]->slot = gklass->vtable [i]->slot;
4448 mono_memory_barrier ();
4449 klass->vtable = tmp;
4451 /* Have to set method->slot for abstract virtual methods */
4452 if (klass->methods && gklass->methods) {
4453 for (i = 0; i < klass->method.count; ++i)
4454 if (klass->methods [i]->slot == -1)
4455 klass->methods [i]->slot = gklass->methods [i]->slot;
4461 if (klass->parent && klass->parent->vtable_size) {
4462 MonoClass *parent = klass->parent;
4465 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4467 // Also inherit parent interface vtables, just as a starting point.
4468 // This is needed otherwise bug-77127.exe fails when the property methods
4469 // have different names in the iterface and the class, because for child
4470 // classes the ".override" information is not used anymore.
4471 for (i = 0; i < parent->interface_offsets_count; i++) {
4472 MonoClass *parent_interface = parent->interfaces_packed [i];
4473 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4474 /*FIXME this is now dead code as this condition will never hold true.
4475 Since interface offsets are inherited then the offset of an interface implemented
4476 by a parent will never be the out of it's vtable boundary.
4478 if (interface_offset >= parent->vtable_size) {
4479 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4482 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4483 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4484 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4485 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4486 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4487 parent_interface_offset + j, parent_interface_offset, j,
4488 interface_offset + j, interface_offset, j));
4495 /*Array have a slot for stelemref*/
4496 if (mono_class_need_stelemref_method (klass)) {
4497 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4499 method->slot = stelemref_slot;
4501 g_assert (method->slot == stelemref_slot);
4503 vtable [stelemref_slot] = method;
4506 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4507 /* override interface methods */
4508 for (i = 0; i < onum; i++) {
4509 MonoMethod *decl = overrides [i*2];
4510 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4512 dslot = mono_method_get_vtable_slot (decl);
4514 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4518 dslot += mono_class_interface_offset (klass, decl->klass);
4519 vtable [dslot] = overrides [i*2 + 1];
4520 vtable [dslot]->slot = dslot;
4522 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4524 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4526 if (mono_security_core_clr_enabled ())
4527 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4530 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4531 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4534 * Create a list of virtual methods to avoid calling
4535 * mono_class_get_virtual_methods () which is slow because of the metadata
4539 gpointer iter = NULL;
4542 virt_methods = NULL;
4543 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4544 virt_methods = g_slist_prepend (virt_methods, cm);
4546 if (mono_class_has_failure (klass))
4550 // Loop on all implemented interfaces...
4551 for (i = 0; i < klass->interface_offsets_count; i++) {
4552 MonoClass *parent = klass->parent;
4554 gboolean interface_is_explicitly_implemented_by_class;
4557 ic = klass->interfaces_packed [i];
4558 ic_offset = mono_class_interface_offset (klass, ic);
4560 mono_class_setup_methods (ic);
4561 if (mono_class_has_failure (ic))
4564 // Check if this interface is explicitly implemented (instead of just inherited)
4565 if (parent != NULL) {
4566 int implemented_interfaces_index;
4567 interface_is_explicitly_implemented_by_class = FALSE;
4568 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4569 if (ic == klass->interfaces [implemented_interfaces_index]) {
4570 interface_is_explicitly_implemented_by_class = TRUE;
4575 interface_is_explicitly_implemented_by_class = TRUE;
4578 // Loop on all interface methods...
4579 for (im_index = 0; im_index < ic->method.count; im_index++) {
4580 MonoMethod *im = ic->methods [im_index];
4581 int im_slot = ic_offset + im->slot;
4582 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4584 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4587 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4589 // If there is an explicit implementation, just use it right away,
4590 // otherwise look for a matching method
4591 if (override_im == NULL) {
4595 // First look for a suitable method among the class methods
4596 for (l = virt_methods; l; l = l->next) {
4597 cm = (MonoMethod *)l->data;
4598 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)));
4599 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4600 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4601 vtable [im_slot] = cm;
4602 /* Why do we need this? */
4607 TRACE_INTERFACE_VTABLE (printf ("\n"));
4608 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4612 // If the slot is still empty, look in all the inherited virtual methods...
4613 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4614 MonoClass *parent = klass->parent;
4615 // Reverse order, so that last added methods are preferred
4616 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4617 MonoMethod *cm = parent->vtable [cm_index];
4619 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));
4620 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4621 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4622 vtable [im_slot] = cm;
4623 /* Why do we need this? */
4629 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4631 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4635 g_assert (vtable [im_slot] == override_im);
4640 // If the class is not abstract, check that all its interface slots are full.
4641 // The check is done here and not directly at the end of the loop above because
4642 // it can happen (for injected generic array interfaces) that the same slot is
4643 // processed multiple times (those interfaces have overlapping slots), and it
4644 // will not always be the first pass the one that fills the slot.
4645 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4646 for (i = 0; i < klass->interface_offsets_count; i++) {
4650 ic = klass->interfaces_packed [i];
4651 ic_offset = mono_class_interface_offset (klass, ic);
4653 for (im_index = 0; im_index < ic->method.count; im_index++) {
4654 MonoMethod *im = ic->methods [im_index];
4655 int im_slot = ic_offset + im->slot;
4657 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4660 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4661 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4662 if (vtable [im_slot] == NULL) {
4663 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4670 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4671 for (l = virt_methods; l; l = l->next) {
4672 cm = (MonoMethod *)l->data;
4674 * If the method is REUSE_SLOT, we must check in the
4675 * base class for a method to override.
4677 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4679 for (k = klass->parent; k ; k = k->parent) {
4684 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4685 MonoMethodSignature *cmsig, *m1sig;
4687 cmsig = mono_method_signature (cm);
4688 m1sig = mono_method_signature (m1);
4690 if (!cmsig || !m1sig) {
4691 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4695 if (!strcmp(cm->name, m1->name) &&
4696 mono_metadata_signature_equal (cmsig, m1sig)) {
4698 if (mono_security_core_clr_enabled ())
4699 mono_security_core_clr_check_override (klass, cm, m1);
4701 slot = mono_method_get_vtable_slot (m1);
4705 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4706 char *body_name = mono_method_full_name (cm, TRUE);
4707 char *decl_name = mono_method_full_name (m1, TRUE);
4708 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4714 g_assert (cm->slot < max_vtsize);
4716 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4717 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4718 mono_method_full_name (m1, 1), m1,
4719 mono_method_full_name (cm, 1), cm));
4720 g_hash_table_insert (override_map, m1, cm);
4724 if (mono_class_has_failure (k))
4734 /*Non final newslot methods must be given a non-interface vtable slot*/
4735 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4739 cm->slot = cur_slot++;
4741 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4742 vtable [cm->slot] = cm;
4745 /* override non interface methods */
4746 for (i = 0; i < onum; i++) {
4747 MonoMethod *decl = overrides [i*2];
4748 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4749 g_assert (decl->slot != -1);
4750 vtable [decl->slot] = overrides [i*2 + 1];
4751 overrides [i * 2 + 1]->slot = decl->slot;
4753 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4754 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4755 mono_method_full_name (decl, 1), decl,
4756 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4757 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4759 if (mono_security_core_clr_enabled ())
4760 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4765 * If a method occupies more than one place in the vtable, and it is
4766 * overriden, then change the other occurances too.
4771 for (i = 0; i < max_vtsize; ++i)
4773 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4775 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4780 g_hash_table_destroy (override_map);
4781 override_map = NULL;
4784 g_slist_free (virt_methods);
4785 virt_methods = NULL;
4787 /* Ensure that all vtable slots are filled with concrete instance methods */
4788 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4789 for (i = 0; i < cur_slot; ++i) {
4790 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4791 char *type_name = mono_type_get_full_name (klass);
4792 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4793 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name));
4795 g_free (method_name);
4801 if (klass->generic_class) {
4802 MonoClass *gklass = klass->generic_class->container_class;
4804 mono_class_init (gklass);
4806 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4808 /* Check that the vtable_size value computed in mono_class_init () is correct */
4809 if (klass->vtable_size)
4810 g_assert (cur_slot == klass->vtable_size);
4811 klass->vtable_size = cur_slot;
4814 /* Try to share the vtable with our parent. */
4815 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4816 mono_memory_barrier ();
4817 klass->vtable = klass->parent->vtable;
4819 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4820 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4821 mono_memory_barrier ();
4822 klass->vtable = tmp;
4825 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4826 if (mono_print_vtable) {
4829 print_implemented_interfaces (klass);
4831 for (i = 0; i <= max_iid; i++)
4832 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4835 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4836 klass->vtable_size, icount);
4838 for (i = 0; i < cur_slot; ++i) {
4843 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4844 mono_method_full_name (cm, TRUE));
4850 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4851 klass->name, max_iid);
4853 for (i = 0; i < klass->interface_count; i++) {
4854 ic = klass->interfaces [i];
4855 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4856 mono_class_interface_offset (klass, ic),
4857 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4860 for (k = klass->parent; k ; k = k->parent) {
4861 for (i = 0; i < k->interface_count; i++) {
4862 ic = k->interfaces [i];
4863 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4864 mono_class_interface_offset (klass, ic),
4865 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4871 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4876 char *name = mono_type_get_full_name (klass);
4877 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4880 g_hash_table_destroy (override_map);
4882 g_slist_free (virt_methods);
4887 * mono_method_get_vtable_slot:
4889 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4890 * LOCKING: Acquires the loader lock.
4892 * FIXME Use proper MonoError machinery here.
4895 mono_method_get_vtable_slot (MonoMethod *method)
4897 if (method->slot == -1) {
4898 mono_class_setup_vtable (method->klass);
4899 if (mono_class_has_failure (method->klass))
4901 if (method->slot == -1) {
4905 if (!method->klass->generic_class) {
4906 g_assert (method->is_inflated);
4907 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4910 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4911 g_assert (method->klass->generic_class);
4912 gklass = method->klass->generic_class->container_class;
4913 mono_class_setup_methods (method->klass);
4914 g_assert (method->klass->methods);
4915 for (i = 0; i < method->klass->method.count; ++i) {
4916 if (method->klass->methods [i] == method)
4919 g_assert (i < method->klass->method.count);
4920 g_assert (gklass->methods);
4921 method->slot = gklass->methods [i]->slot;
4923 g_assert (method->slot != -1);
4925 return method->slot;
4929 * mono_method_get_vtable_index:
4932 * Returns the index into the runtime vtable to access the method or,
4933 * in the case of a virtual generic method, the virtual generic method
4934 * thunk. Returns -1 on failure.
4936 * FIXME Use proper MonoError machinery here.
4939 mono_method_get_vtable_index (MonoMethod *method)
4941 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4942 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4943 if (imethod->declaring->is_generic)
4944 return mono_method_get_vtable_slot (imethod->declaring);
4946 return mono_method_get_vtable_slot (method);
4949 static MonoMethod *default_ghc = NULL;
4950 static MonoMethod *default_finalize = NULL;
4951 static int finalize_slot = -1;
4952 static int ghc_slot = -1;
4955 initialize_object_slots (MonoClass *klass)
4960 if (klass == mono_defaults.object_class) {
4961 mono_class_setup_vtable (klass);
4962 for (i = 0; i < klass->vtable_size; ++i) {
4963 MonoMethod *cm = klass->vtable [i];
4965 if (!strcmp (cm->name, "GetHashCode"))
4967 else if (!strcmp (cm->name, "Finalize"))
4971 g_assert (ghc_slot > 0);
4972 default_ghc = klass->vtable [ghc_slot];
4974 g_assert (finalize_slot > 0);
4975 default_finalize = klass->vtable [finalize_slot];
4980 MonoMethod *array_method;
4982 } GenericArrayMethodInfo;
4984 static int generic_array_method_num = 0;
4985 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4988 generic_array_methods (MonoClass *klass)
4990 int i, count_generic = 0;
4991 GList *list = NULL, *tmp;
4992 if (generic_array_method_num)
4993 return generic_array_method_num;
4994 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4995 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4996 for (i = 0; i < klass->parent->method.count; i++) {
4997 MonoMethod *m = klass->parent->methods [i];
4998 if (!strncmp (m->name, "InternalArray__", 15)) {
5000 list = g_list_prepend (list, m);
5003 list = g_list_reverse (list);
5004 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
5006 for (tmp = list; tmp; tmp = tmp->next) {
5007 const char *mname, *iname;
5009 MonoMethod *m = (MonoMethod *)tmp->data;
5010 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5011 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5013 generic_array_method_info [i].array_method = m;
5014 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5015 iname = "System.Collections.Generic.ICollection`1.";
5016 mname = m->name + 27;
5017 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5018 iname = "System.Collections.Generic.IEnumerable`1.";
5019 mname = m->name + 27;
5020 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5021 iname = "System.Collections.Generic.IReadOnlyList`1.";
5022 mname = m->name + strlen (ireadonlylist_prefix);
5023 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5024 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5025 mname = m->name + strlen (ireadonlycollection_prefix);
5026 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5027 iname = "System.Collections.Generic.IList`1.";
5028 mname = m->name + 15;
5030 g_assert_not_reached ();
5033 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5034 strcpy (name, iname);
5035 strcpy (name + strlen (iname), mname);
5036 generic_array_method_info [i].name = name;
5039 /*g_print ("array generic methods: %d\n", count_generic);*/
5041 generic_array_method_num = count_generic;
5043 return generic_array_method_num;
5047 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5049 MonoGenericContext tmp_context;
5052 tmp_context.class_inst = NULL;
5053 tmp_context.method_inst = iface->generic_class->context.class_inst;
5054 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5056 for (i = 0; i < generic_array_method_num; i++) {
5058 MonoMethod *m = generic_array_method_info [i].array_method;
5059 MonoMethod *inflated;
5061 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5062 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5063 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5068 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5070 int null_length = strlen ("(null)");
5071 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5072 char *s = (char *)mono_image_alloc (image, len);
5075 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5076 g_assert (result == len - 1);
5083 * @class: the class to initialize
5085 * Compute the instance_size, class_size and other infos that cannot be
5086 * computed at mono_class_get() time. Also compute vtable_size if possible.
5087 * Returns TRUE on success or FALSE if there was a problem in loading
5088 * the type (incorrect assemblies, missing assemblies, methods, etc).
5090 * LOCKING: Acquires the loader lock.
5093 mono_class_init (MonoClass *klass)
5096 MonoCachedClassInfo cached_info;
5097 gboolean has_cached_info;
5101 /* Double-checking locking pattern */
5102 if (klass->inited || mono_class_has_failure (klass))
5103 return !mono_class_has_failure (klass);
5105 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5107 /* We do everything inside the lock to prevent races */
5108 mono_loader_lock ();
5110 if (klass->inited || mono_class_has_failure (klass)) {
5111 mono_loader_unlock ();
5112 /* Somebody might have gotten in before us */
5113 return !mono_class_has_failure (klass);
5116 if (klass->init_pending) {
5117 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5121 klass->init_pending = 1;
5123 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5124 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5129 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5130 MonoClass *element_class = klass->element_class;
5131 if (!element_class->inited)
5132 mono_class_init (element_class);
5133 if (mono_class_has_failure (element_class)) {
5134 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5139 mono_stats.initialized_class_count++;
5141 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5142 MonoClass *gklass = klass->generic_class->container_class;
5144 mono_stats.generic_class_count++;
5146 klass->method = gklass->method;
5147 klass->field = gklass->field;
5149 mono_class_init (gklass);
5150 // FIXME: Why is this needed ?
5151 if (!mono_class_has_failure (gklass))
5152 mono_class_setup_methods (gklass);
5153 if (mono_class_has_failure (gklass)) {
5154 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5158 if (MONO_CLASS_IS_INTERFACE (klass))
5159 klass->interface_id = mono_get_unique_iid (klass);
5162 if (klass->parent && !klass->parent->inited)
5163 mono_class_init (klass->parent);
5165 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5167 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5168 klass->nested_classes_inited = TRUE;
5171 * Computes the size used by the fields, and their locations
5173 if (has_cached_info) {
5174 klass->instance_size = cached_info.instance_size;
5175 klass->sizes.class_size = cached_info.class_size;
5176 klass->packing_size = cached_info.packing_size;
5177 klass->min_align = cached_info.min_align;
5178 klass->blittable = cached_info.blittable;
5179 klass->has_references = cached_info.has_references;
5180 klass->has_static_refs = cached_info.has_static_refs;
5181 klass->no_special_static_fields = cached_info.no_special_static_fields;
5184 if (!klass->size_inited){
5185 mono_class_setup_fields (klass);
5186 if (mono_class_has_failure (klass))
5190 /* Initialize arrays */
5192 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5194 if (klass->interface_count) {
5195 int count_generic = generic_array_methods (klass);
5196 klass->method.count += klass->interface_count * count_generic;
5200 mono_class_setup_supertypes (klass);
5203 initialize_object_slots (klass);
5206 * Initialize the rest of the data without creating a generic vtable if possible.
5207 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5208 * also avoid computing a generic vtable.
5210 if (has_cached_info) {
5212 klass->vtable_size = cached_info.vtable_size;
5213 klass->has_finalize = cached_info.has_finalize;
5214 klass->has_finalize_inited = TRUE;
5215 klass->ghcimpl = cached_info.ghcimpl;
5216 klass->has_cctor = cached_info.has_cctor;
5217 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5218 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5219 * The first slot if for array with.
5221 static int szarray_vtable_size[2] = { 0 };
5223 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5226 if (!szarray_vtable_size [slot]) {
5227 mono_class_setup_vtable (klass);
5228 szarray_vtable_size [slot] = klass->vtable_size;
5230 klass->vtable_size = szarray_vtable_size[slot];
5232 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5233 MonoClass *gklass = klass->generic_class->container_class;
5235 /* Generic instance case */
5236 klass->ghcimpl = gklass->ghcimpl;
5237 klass->has_cctor = gklass->has_cctor;
5239 mono_class_setup_vtable (gklass);
5240 if (mono_class_has_failure (gklass)) {
5241 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5245 klass->vtable_size = gklass->vtable_size;
5249 /* ghcimpl is not currently used
5251 if (klass->parent) {
5252 MonoMethod *cmethod = klass->vtable [ghc_slot];
5253 if (cmethod->is_inflated)
5254 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5255 if (cmethod == default_ghc) {
5261 /* C# doesn't allow interfaces to have cctors */
5262 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5263 MonoMethod *cmethod = NULL;
5265 if (klass->type_token && !image_is_dynamic(klass->image)) {
5266 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5267 /* The find_method function ignores the 'flags' argument */
5268 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5269 klass->has_cctor = 1;
5271 mono_class_setup_methods (klass);
5272 if (mono_class_has_failure (klass))
5275 for (i = 0; i < klass->method.count; ++i) {
5276 MonoMethod *method = klass->methods [i];
5277 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5278 (strcmp (".cctor", method->name) == 0)) {
5279 klass->has_cctor = 1;
5287 if (klass->parent) {
5288 int first_iface_slot;
5289 /* This will compute klass->parent->vtable_size for some classes */
5290 mono_class_init (klass->parent);
5291 if (mono_class_has_failure (klass->parent)) {
5292 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5295 if (!klass->parent->vtable_size) {
5296 /* FIXME: Get rid of this somehow */
5297 mono_class_setup_vtable (klass->parent);
5298 if (mono_class_has_failure (klass->parent)) {
5299 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5303 first_iface_slot = klass->parent->vtable_size;
5304 if (mono_class_need_stelemref_method (klass))
5306 setup_interface_offsets (klass, first_iface_slot, TRUE);
5308 setup_interface_offsets (klass, 0, TRUE);
5311 if (mono_security_core_clr_enabled ())
5312 mono_security_core_clr_check_inheritance (klass);
5314 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5315 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5320 /* Because of the double-checking locking pattern */
5321 mono_memory_barrier ();
5323 klass->init_pending = 0;
5325 mono_loader_unlock ();
5327 return !mono_class_has_failure (klass);
5331 * mono_class_has_finalizer:
5333 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5337 mono_class_has_finalizer (MonoClass *klass)
5339 gboolean has_finalize = FALSE;
5341 if (klass->has_finalize_inited)
5342 return klass->has_finalize;
5344 /* Interfaces and valuetypes are not supposed to have finalizers */
5345 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5346 MonoMethod *cmethod = NULL;
5348 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5349 } else if (klass->generic_class) {
5350 MonoClass *gklass = klass->generic_class->container_class;
5352 has_finalize = mono_class_has_finalizer (gklass);
5353 } else if (klass->parent && klass->parent->has_finalize) {
5354 has_finalize = TRUE;
5356 if (klass->parent) {
5358 * Can't search in metadata for a method named Finalize, because that
5359 * ignores overrides.
5361 mono_class_setup_vtable (klass);
5362 if (mono_class_has_failure (klass))
5365 cmethod = klass->vtable [finalize_slot];
5369 g_assert (klass->vtable_size > finalize_slot);
5371 if (klass->parent) {
5372 if (cmethod->is_inflated)
5373 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5374 if (cmethod != default_finalize)
5375 has_finalize = TRUE;
5381 mono_image_lock (klass->image);
5383 if (!klass->has_finalize_inited) {
5384 klass->has_finalize = has_finalize ? 1 : 0;
5386 mono_memory_barrier ();
5387 klass->has_finalize_inited = TRUE;
5390 mono_image_unlock (klass->image);
5392 return klass->has_finalize;
5396 mono_is_corlib_image (MonoImage *image)
5398 /* FIXME: allow the dynamic case for our compilers and with full trust */
5399 if (image_is_dynamic (image))
5400 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5402 return image == mono_defaults.corlib;
5406 * LOCKING: this assumes the loader lock is held
5409 mono_class_setup_mono_type (MonoClass *klass)
5411 const char *name = klass->name;
5412 const char *nspace = klass->name_space;
5413 gboolean is_corlib = mono_is_corlib_image (klass->image);
5415 klass->this_arg.byref = 1;
5416 klass->this_arg.data.klass = klass;
5417 klass->this_arg.type = MONO_TYPE_CLASS;
5418 klass->byval_arg.data.klass = klass;
5419 klass->byval_arg.type = MONO_TYPE_CLASS;
5421 if (is_corlib && !strcmp (nspace, "System")) {
5422 if (!strcmp (name, "ValueType")) {
5424 * do not set the valuetype bit for System.ValueType.
5425 * klass->valuetype = 1;
5427 klass->blittable = TRUE;
5428 } else if (!strcmp (name, "Enum")) {
5430 * do not set the valuetype bit for System.Enum.
5431 * klass->valuetype = 1;
5433 klass->valuetype = 0;
5434 klass->enumtype = 0;
5435 } else if (!strcmp (name, "Object")) {
5436 klass->byval_arg.type = MONO_TYPE_OBJECT;
5437 klass->this_arg.type = MONO_TYPE_OBJECT;
5438 } else if (!strcmp (name, "String")) {
5439 klass->byval_arg.type = MONO_TYPE_STRING;
5440 klass->this_arg.type = MONO_TYPE_STRING;
5441 } else if (!strcmp (name, "TypedReference")) {
5442 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5443 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5447 if (klass->valuetype) {
5448 int t = MONO_TYPE_VALUETYPE;
5450 if (is_corlib && !strcmp (nspace, "System")) {
5453 if (!strcmp (name, "Boolean")) {
5454 t = MONO_TYPE_BOOLEAN;
5455 } else if (!strcmp(name, "Byte")) {
5457 klass->blittable = TRUE;
5461 if (!strcmp (name, "Char")) {
5466 if (!strcmp (name, "Double")) {
5468 klass->blittable = TRUE;
5472 if (!strcmp (name, "Int32")) {
5474 klass->blittable = TRUE;
5475 } else if (!strcmp(name, "Int16")) {
5477 klass->blittable = TRUE;
5478 } else if (!strcmp(name, "Int64")) {
5480 klass->blittable = TRUE;
5481 } else if (!strcmp(name, "IntPtr")) {
5483 klass->blittable = TRUE;
5487 if (!strcmp (name, "Single")) {
5489 klass->blittable = TRUE;
5490 } else if (!strcmp(name, "SByte")) {
5492 klass->blittable = TRUE;
5496 if (!strcmp (name, "UInt32")) {
5498 klass->blittable = TRUE;
5499 } else if (!strcmp(name, "UInt16")) {
5501 klass->blittable = TRUE;
5502 } else if (!strcmp(name, "UInt64")) {
5504 klass->blittable = TRUE;
5505 } else if (!strcmp(name, "UIntPtr")) {
5507 klass->blittable = TRUE;
5511 if (!strcmp (name, "TypedReference")) {
5512 t = MONO_TYPE_TYPEDBYREF;
5513 klass->blittable = TRUE;
5517 if (!strcmp (name, "Void")) {
5525 klass->byval_arg.type = (MonoTypeEnum)t;
5526 klass->this_arg.type = (MonoTypeEnum)t;
5529 if (MONO_CLASS_IS_INTERFACE (klass))
5530 klass->interface_id = mono_get_unique_iid (klass);
5536 * COM initialization is delayed until needed.
5537 * However when a [ComImport] attribute is present on a type it will trigger
5538 * the initialization. This is not a problem unless the BCL being executed
5539 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5542 init_com_from_comimport (MonoClass *klass)
5544 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5545 if (mono_security_core_clr_enabled ()) {
5546 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5547 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5548 /* but it can not be made available for application (i.e. user code) since all COM calls
5549 * are considered native calls. In this case we fail with a TypeLoadException (just like
5550 * Silverlight 2 does */
5551 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5556 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5558 #endif /*DISABLE_COM*/
5561 * LOCKING: this assumes the loader lock is held
5564 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5566 gboolean system_namespace;
5567 gboolean is_corlib = mono_is_corlib_image (klass->image);
5569 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5571 /* if root of the hierarchy */
5572 if (system_namespace && !strcmp (klass->name, "Object")) {
5573 klass->parent = NULL;
5574 klass->instance_size = sizeof (MonoObject);
5577 if (!strcmp (klass->name, "<Module>")) {
5578 klass->parent = NULL;
5579 klass->instance_size = 0;
5583 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5584 /* Imported COM Objects always derive from __ComObject. */
5586 if (MONO_CLASS_IS_IMPORT (klass)) {
5587 init_com_from_comimport (klass);
5588 if (parent == mono_defaults.object_class)
5589 parent = mono_class_get_com_object_class ();
5593 /* set the parent to something useful and safe, but mark the type as broken */
5594 parent = mono_defaults.object_class;
5595 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5599 klass->parent = parent;
5601 if (parent->generic_class && !parent->name) {
5603 * If the parent is a generic instance, we may get
5604 * called before it is fully initialized, especially
5605 * before it has its name.
5610 #ifndef DISABLE_REMOTING
5611 klass->marshalbyref = parent->marshalbyref;
5612 klass->contextbound = parent->contextbound;
5615 klass->delegate = parent->delegate;
5617 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5618 mono_class_set_is_com_object (klass);
5620 if (system_namespace) {
5621 #ifndef DISABLE_REMOTING
5622 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5623 klass->marshalbyref = 1;
5625 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5626 klass->contextbound = 1;
5628 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5629 klass->delegate = 1;
5632 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5633 (strcmp (klass->parent->name_space, "System") == 0)))
5634 klass->valuetype = 1;
5635 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5636 klass->valuetype = klass->enumtype = 1;
5638 /*klass->enumtype = klass->parent->enumtype; */
5640 /* initialize com types if COM interfaces are present */
5642 if (MONO_CLASS_IS_IMPORT (klass))
5643 init_com_from_comimport (klass);
5645 klass->parent = NULL;
5651 * mono_class_setup_supertypes:
5654 * Build the data structure needed to make fast type checks work.
5655 * This currently sets two fields in @class:
5656 * - idepth: distance between @class and System.Object in the type
5658 * - supertypes: array of classes: each element has a class in the hierarchy
5659 * starting from @class up to System.Object
5661 * LOCKING: This function is atomic, in case of contention we waste memory.
5664 mono_class_setup_supertypes (MonoClass *klass)
5667 MonoClass **supertypes;
5669 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5673 if (klass->parent && !klass->parent->supertypes)
5674 mono_class_setup_supertypes (klass->parent);
5676 klass->idepth = klass->parent->idepth + 1;
5680 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5681 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5683 if (klass->parent) {
5684 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5687 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5688 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5690 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5693 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5697 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5699 MonoClass *gtd = (MonoClass*)user_data;
5700 /* Only try to fix generic instances of @gtd */
5701 if (gclass->generic_class->container_class != gtd)
5704 /* Check if the generic instance has no parent. */
5705 if (gtd->parent && !gclass->parent)
5706 mono_generic_class_setup_parent (gclass, gtd);
5712 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5714 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5715 mono_error_set_type_load_class (error, klass, msg);
5719 * mono_class_create_from_typedef:
5720 * @image: image where the token is valid
5721 * @type_token: typedef token
5722 * @error: used to return any error found while creating the type
5724 * Create the MonoClass* representing the specified type token.
5725 * @type_token must be a TypeDef token.
5727 * FIXME: don't return NULL on failure, just the the caller figure it out.
5730 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5732 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5733 MonoClass *klass, *parent = NULL;
5734 guint32 cols [MONO_TYPEDEF_SIZE];
5735 guint32 cols_next [MONO_TYPEDEF_SIZE];
5736 guint tidx = mono_metadata_token_index (type_token);
5737 MonoGenericContext *context = NULL;
5738 const char *name, *nspace;
5740 MonoClass **interfaces;
5741 guint32 field_last, method_last;
5742 guint32 nesting_tokeen;
5744 mono_error_init (error);
5746 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5747 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5751 mono_loader_lock ();
5753 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5754 mono_loader_unlock ();
5758 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5760 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5761 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5763 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5766 klass->name_space = nspace;
5768 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5770 klass->image = image;
5771 klass->type_token = type_token;
5772 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5774 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5776 classes_size += sizeof (MonoClass);
5779 * Check whether we're a generic type definition.
5781 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5782 if (klass->generic_container) {
5783 klass->is_generic = 1;
5784 klass->generic_container->owner.klass = klass;
5785 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5786 context = &klass->generic_container->context;
5789 if (klass->generic_container)
5790 enable_gclass_recording ();
5792 if (cols [MONO_TYPEDEF_EXTENDS]) {
5794 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5796 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5797 /*WARNING: this must satisfy mono_metadata_type_hash*/
5798 klass->this_arg.byref = 1;
5799 klass->this_arg.data.klass = klass;
5800 klass->this_arg.type = MONO_TYPE_CLASS;
5801 klass->byval_arg.data.klass = klass;
5802 klass->byval_arg.type = MONO_TYPE_CLASS;
5804 parent = mono_class_get_checked (image, parent_token, error);
5805 if (parent && context) /* Always inflate */
5806 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5808 if (parent == NULL) {
5809 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5810 goto parent_failure;
5813 for (tmp = parent; tmp; tmp = tmp->parent) {
5815 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5816 goto parent_failure;
5818 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5819 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5820 goto parent_failure;
5825 mono_class_setup_parent (klass, parent);
5827 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5828 mono_class_setup_mono_type (klass);
5830 if (klass->generic_container)
5831 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5834 * This might access klass->byval_arg for recursion generated by generic constraints,
5835 * so it has to come after setup_mono_type ().
5837 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5838 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5839 if (!mono_error_ok (error)) {
5840 /*FIXME implement a mono_class_set_failure_from_mono_error */
5841 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5842 mono_loader_unlock ();
5843 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5848 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5852 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5856 klass->cast_class = klass->element_class = klass;
5858 if (!klass->enumtype) {
5859 if (!mono_metadata_interfaces_from_typedef_full (
5860 image, type_token, &interfaces, &icount, FALSE, context, error)){
5862 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5863 mono_loader_unlock ();
5864 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5868 klass->interfaces = interfaces;
5869 klass->interface_count = icount;
5870 klass->interfaces_inited = 1;
5873 /*g_print ("Load class %s\n", name);*/
5876 * Compute the field and method lists
5878 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5879 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5881 if (tt->rows > tidx){
5882 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5883 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5884 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5886 field_last = image->tables [MONO_TABLE_FIELD].rows;
5887 method_last = image->tables [MONO_TABLE_METHOD].rows;
5890 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5891 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5892 klass->field.count = field_last - klass->field.first;
5894 klass->field.count = 0;
5896 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5897 klass->method.count = method_last - klass->method.first;
5899 klass->method.count = 0;
5901 /* reserve space to store vector pointer in arrays */
5902 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5903 klass->instance_size += 2 * sizeof (gpointer);
5904 g_assert (klass->field.count == 0);
5907 if (klass->enumtype) {
5908 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5909 if (!enum_basetype) {
5910 /*set it to a default value as the whole runtime can't handle this to be null*/
5911 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5912 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5913 mono_loader_unlock ();
5914 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5917 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5921 * If we're a generic type definition, load the constraints.
5922 * We must do this after the class has been constructed to make certain recursive scenarios
5925 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5926 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
5927 mono_loader_unlock ();
5928 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5932 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5933 if (!strncmp (name, "Vector", 6))
5934 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");
5937 mono_loader_unlock ();
5939 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5944 mono_class_setup_mono_type (klass);
5945 mono_loader_unlock ();
5946 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5950 /** Is klass a Nullable<T> ginst? */
5952 mono_class_is_nullable (MonoClass *klass)
5954 return klass->generic_class != NULL &&
5955 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5959 /** if klass is T? return T */
5961 mono_class_get_nullable_param (MonoClass *klass)
5963 g_assert (mono_class_is_nullable (klass));
5964 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5968 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5972 MonoGenericClass *gclass = klass->generic_class;
5974 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5975 if (!mono_error_ok (&error)) {
5976 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5977 klass->parent = mono_defaults.object_class;
5978 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5979 mono_error_cleanup (&error);
5983 mono_class_setup_parent (klass, klass->parent);
5985 if (klass->enumtype) {
5986 klass->cast_class = gtd->cast_class;
5987 klass->element_class = gtd->element_class;
5993 * Create the `MonoClass' for an instantiation of a generic type.
5994 * We only do this if we actually need it.
5997 mono_generic_class_get_class (MonoGenericClass *gclass)
5999 MonoClass *klass, *gklass;
6001 if (gclass->cached_class)
6002 return gclass->cached_class;
6004 mono_loader_lock ();
6005 if (gclass->cached_class) {
6006 mono_loader_unlock ();
6007 return gclass->cached_class;
6010 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6012 gklass = gclass->container_class;
6014 if (record_gclass_instantiation > 0)
6015 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6017 if (gklass->nested_in) {
6018 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6019 klass->nested_in = gklass->nested_in;
6022 klass->name = gklass->name;
6023 klass->name_space = gklass->name_space;
6025 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6027 klass->image = gklass->image;
6028 klass->flags = gklass->flags;
6029 klass->type_token = gklass->type_token;
6030 klass->field.count = gklass->field.count;
6032 klass->is_inflated = 1;
6033 klass->generic_class = gclass;
6035 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6036 klass->this_arg.type = klass->byval_arg.type;
6037 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6038 klass->this_arg.byref = TRUE;
6039 klass->enumtype = gklass->enumtype;
6040 klass->valuetype = gklass->valuetype;
6042 klass->cast_class = klass->element_class = klass;
6044 if (mono_class_is_nullable (klass))
6045 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6048 * We're not interested in the nested classes of a generic instance.
6049 * We use the generic type definition to look for nested classes.
6052 mono_generic_class_setup_parent (klass, gklass);
6054 if (gclass->is_dynamic) {
6056 * 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.
6057 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6058 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6060 if (!gklass->wastypebuilder)
6063 mono_class_setup_supertypes (klass);
6065 if (klass->enumtype) {
6067 * For enums, gklass->fields might not been set, but instance_size etc. is
6068 * already set in mono_reflection_create_internal_class (). For non-enums,
6069 * these will be computed normally in mono_class_layout_fields ().
6071 klass->instance_size = gklass->instance_size;
6072 klass->sizes.class_size = gklass->sizes.class_size;
6073 mono_memory_barrier ();
6074 klass->size_inited = 1;
6078 mono_memory_barrier ();
6079 gclass->cached_class = klass;
6081 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6083 inflated_classes ++;
6084 inflated_classes_size += sizeof (MonoClass);
6086 mono_loader_unlock ();
6092 get_image_for_container (MonoGenericContainer *container)
6095 if (container->is_anonymous) {
6096 result = container->owner.image;
6099 if (container->is_method) {
6100 MonoMethod *method = container->owner.method;
6101 g_assert_checked (method);
6102 klass = method->klass;
6104 klass = container->owner.klass;
6106 g_assert_checked (klass);
6107 result = klass->image;
6114 get_image_for_generic_param (MonoGenericParam *param)
6116 MonoGenericContainer *container = mono_generic_param_owner (param);
6117 g_assert_checked (container);
6118 return get_image_for_container (container);
6121 // Make a string in the designated image consisting of a single integer.
6122 #define INT_STRING_SIZE 16
6124 make_generic_name_string (MonoImage *image, int num)
6126 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6127 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6131 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6132 // pinfo is derived from param by the caller for us.
6134 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6136 MonoClass *klass, **ptr;
6138 MonoGenericContainer *container = mono_generic_param_owner (param);
6139 g_assert_checked (container);
6141 MonoImage *image = get_image_for_container (container);
6142 gboolean is_mvar = container->is_method;
6143 gboolean is_anonymous = container->is_anonymous;
6145 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6146 classes_size += sizeof (MonoClass);
6149 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6151 int n = mono_generic_param_num (param);
6152 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6156 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6157 } else if (is_mvar) {
6158 MonoMethod *omethod = container->owner.method;
6159 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6161 MonoClass *oklass = container->owner.klass;
6162 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6165 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6167 // Count non-NULL items in pinfo->constraints
6170 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6174 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6175 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6177 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6178 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6180 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6183 if (count - pos > 0) {
6184 klass->interface_count = count - pos;
6185 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6186 klass->interfaces_inited = TRUE;
6187 for (i = pos; i < count; i++)
6188 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6191 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6193 klass->inited = TRUE;
6194 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6195 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6196 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6198 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6199 klass->this_arg.type = klass->byval_arg.type;
6200 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6201 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6202 klass->this_arg.byref = TRUE;
6204 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6205 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6207 /*Init these fields to sane values*/
6208 klass->min_align = 1;
6210 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6211 * constrained to, the JIT depends on this.
6213 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6214 mono_memory_barrier ();
6215 klass->size_inited = 1;
6216 klass->setup_fields_called = 1;
6218 mono_class_setup_supertypes (klass);
6220 if (count - pos > 0) {
6221 mono_class_setup_vtable (klass->parent);
6222 if (mono_class_has_failure (klass->parent))
6223 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6225 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6231 #define FAST_CACHE_SIZE 16
6234 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6235 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6236 * we cache the MonoClasses.
6237 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6238 * LOCKING: Takes the image lock depending on @take_lock.
6241 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6243 int n = mono_generic_param_num (param);
6244 MonoImage *image = get_image_for_generic_param (param);
6245 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6246 MonoClass *klass = NULL;
6251 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6252 // For high numbers or constraints we have to use pointer hashes.
6253 if (param->gshared_constraint) {
6254 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6257 mono_image_lock (image);
6258 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6260 mono_image_unlock (image);
6265 if (n < FAST_CACHE_SIZE) {
6267 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6269 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6271 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6274 mono_image_lock (image);
6275 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6277 mono_image_unlock (image);
6284 * LOCKING: Image lock (param->image) must be held
6287 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6289 int n = mono_generic_param_num (param);
6290 MonoImage *image = get_image_for_generic_param (param);
6291 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6295 if (param->gshared_constraint) {
6296 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6298 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6299 mono_memory_barrier ();
6301 image->mvar_cache_constrained = ht;
6303 image->var_cache_constrained = ht;
6305 g_hash_table_insert (ht, param, klass);
6306 } else if (n < FAST_CACHE_SIZE) {
6308 /* Requires locking to avoid droping an already published class */
6309 if (!image->mvar_cache_fast)
6310 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6311 image->mvar_cache_fast [n] = klass;
6313 if (!image->var_cache_fast)
6314 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6315 image->var_cache_fast [n] = klass;
6318 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6320 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6322 ht = g_hash_table_new (NULL, NULL);
6323 mono_memory_barrier ();
6325 image->mvar_cache_slow = ht;
6327 image->var_cache_slow = ht;
6330 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6335 * LOCKING: Acquires the image lock (@image).
6338 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6340 MonoImage *image = get_image_for_generic_param (param);
6341 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6342 MonoClass *klass, *klass2;
6344 // If a klass already exists for this object and is cached, return it.
6345 if (pinfo) // Non-anonymous
6346 klass = pinfo->pklass;
6348 klass = get_anon_gparam_class (param, TRUE);
6353 // Create a new klass
6354 klass = make_generic_param_class (param, pinfo);
6356 // Now we need to cache the klass we created.
6357 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6358 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6359 // and allow our newly-created klass object to just leak.
6360 mono_memory_barrier ();
6362 mono_image_lock (image);
6364 // Here "klass2" refers to the klass potentially created by the other thread.
6365 if (pinfo) // Repeat check from above
6366 klass2 = pinfo->pklass;
6368 klass2 = get_anon_gparam_class (param, FALSE);
6375 pinfo->pklass = klass;
6377 set_anon_gparam_class (param, klass);
6379 mono_image_unlock (image);
6381 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6383 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6385 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6391 * mono_class_from_generic_parameter:
6392 * @param: Parameter to find/construct a class for.
6393 * @arg2: Is ignored.
6394 * @arg3: Is ignored.
6397 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6399 return mono_class_from_generic_parameter_internal (param);
6404 mono_ptr_class_get (MonoType *type)
6407 MonoClass *el_class;
6411 el_class = mono_class_from_mono_type (type);
6412 image = el_class->image;
6414 mono_image_lock (image);
6415 if (image->ptr_cache) {
6416 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6417 mono_image_unlock (image);
6421 mono_image_unlock (image);
6423 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6425 classes_size += sizeof (MonoClass);
6427 result->parent = NULL; /* no parent for PTR types */
6428 result->name_space = el_class->name_space;
6429 name = g_strdup_printf ("%s*", el_class->name);
6430 result->name = mono_image_strdup (image, name);
6433 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6435 result->image = el_class->image;
6436 result->inited = TRUE;
6437 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6438 /* Can pointers get boxed? */
6439 result->instance_size = sizeof (gpointer);
6440 result->cast_class = result->element_class = el_class;
6441 result->blittable = TRUE;
6443 result->byval_arg.type = MONO_TYPE_PTR;
6444 result->this_arg.type = result->byval_arg.type;
6445 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6446 result->this_arg.byref = TRUE;
6448 mono_class_setup_supertypes (result);
6450 mono_image_lock (image);
6451 if (image->ptr_cache) {
6453 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6454 mono_image_unlock (image);
6455 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6459 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6461 g_hash_table_insert (image->ptr_cache, el_class, result);
6462 mono_image_unlock (image);
6464 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6470 mono_fnptr_class_get (MonoMethodSignature *sig)
6473 static GHashTable *ptr_hash = NULL;
6475 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6477 mono_loader_lock ();
6480 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6482 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6483 mono_loader_unlock ();
6486 result = g_new0 (MonoClass, 1);
6488 result->parent = NULL; /* no parent for PTR types */
6489 result->name_space = "System";
6490 result->name = "MonoFNPtrFakeClass";
6492 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6494 result->image = mono_defaults.corlib; /* need to fix... */
6495 result->inited = TRUE;
6496 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6497 /* Can pointers get boxed? */
6498 result->instance_size = sizeof (gpointer);
6499 result->cast_class = result->element_class = result;
6500 result->blittable = TRUE;
6502 result->byval_arg.type = MONO_TYPE_FNPTR;
6503 result->this_arg.type = result->byval_arg.type;
6504 result->this_arg.data.method = result->byval_arg.data.method = sig;
6505 result->this_arg.byref = TRUE;
6506 result->blittable = TRUE;
6508 mono_class_setup_supertypes (result);
6510 g_hash_table_insert (ptr_hash, sig, result);
6512 mono_loader_unlock ();
6514 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6520 * mono_class_from_mono_type:
6521 * @type: describes the type to return
6523 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6526 mono_class_from_mono_type (MonoType *type)
6528 switch (type->type) {
6529 case MONO_TYPE_OBJECT:
6530 return type->data.klass? type->data.klass: mono_defaults.object_class;
6531 case MONO_TYPE_VOID:
6532 return type->data.klass? type->data.klass: mono_defaults.void_class;
6533 case MONO_TYPE_BOOLEAN:
6534 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6535 case MONO_TYPE_CHAR:
6536 return type->data.klass? type->data.klass: mono_defaults.char_class;
6538 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6540 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6542 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6544 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6546 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6548 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6550 return type->data.klass? type->data.klass: mono_defaults.int_class;
6552 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6554 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6556 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6558 return type->data.klass? type->data.klass: mono_defaults.single_class;
6560 return type->data.klass? type->data.klass: mono_defaults.double_class;
6561 case MONO_TYPE_STRING:
6562 return type->data.klass? type->data.klass: mono_defaults.string_class;
6563 case MONO_TYPE_TYPEDBYREF:
6564 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6565 case MONO_TYPE_ARRAY:
6566 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6568 return mono_ptr_class_get (type->data.type);
6569 case MONO_TYPE_FNPTR:
6570 return mono_fnptr_class_get (type->data.method);
6571 case MONO_TYPE_SZARRAY:
6572 return mono_array_class_get (type->data.klass, 1);
6573 case MONO_TYPE_CLASS:
6574 case MONO_TYPE_VALUETYPE:
6575 return type->data.klass;
6576 case MONO_TYPE_GENERICINST:
6577 return mono_generic_class_get_class (type->data.generic_class);
6578 case MONO_TYPE_MVAR:
6580 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6582 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6583 g_assert_not_reached ();
6586 // Yes, this returns NULL, even if it is documented as not doing so, but there
6587 // is no way for the code to make it this far, due to the assert above.
6592 * mono_type_retrieve_from_typespec
6593 * @image: context where the image is created
6594 * @type_spec: typespec token
6595 * @context: the generic context used to evaluate generic instantiations in
6598 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6600 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6602 *did_inflate = FALSE;
6607 if (context && (context->class_inst || context->method_inst)) {
6608 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6610 if (!mono_error_ok (error)) {
6616 *did_inflate = TRUE;
6623 * mono_class_create_from_typespec
6624 * @image: context where the image is created
6625 * @type_spec: typespec token
6626 * @context: the generic context used to evaluate generic instantiations in
6629 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6632 gboolean inflated = FALSE;
6633 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6634 return_val_if_nok (error, NULL);
6635 ret = mono_class_from_mono_type (t);
6637 mono_metadata_free_type (t);
6642 * mono_bounded_array_class_get:
6643 * @element_class: element class
6644 * @rank: the dimension of the array class
6645 * @bounded: whenever the array has non-zero bounds
6647 * Returns: A class object describing the array with element type @element_type and
6651 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6655 MonoClass *parent = NULL;
6656 GSList *list, *rootlist = NULL;
6659 gboolean corlib_type = FALSE;
6661 g_assert (rank <= 255);
6664 /* bounded only matters for one-dimensional arrays */
6667 image = eclass->image;
6669 if (rank == 1 && !bounded) {
6671 * This case is very frequent not just during compilation because of calls
6672 * from mono_class_from_mono_type (), mono_array_new (),
6673 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6675 mono_os_mutex_lock (&image->szarray_cache_lock);
6676 if (!image->szarray_cache)
6677 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6678 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6679 mono_os_mutex_unlock (&image->szarray_cache_lock);
6683 mono_loader_lock ();
6685 mono_loader_lock ();
6687 if (!image->array_cache)
6688 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6690 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6691 for (; list; list = list->next) {
6692 klass = (MonoClass *)list->data;
6693 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6694 mono_loader_unlock ();
6701 /* for the building corlib use System.Array from it */
6702 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6703 parent = mono_class_load_from_name (image, "System", "Array");
6706 parent = mono_defaults.array_class;
6707 if (!parent->inited)
6708 mono_class_init (parent);
6711 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6713 klass->image = image;
6714 klass->name_space = eclass->name_space;
6715 nsize = strlen (eclass->name);
6716 name = (char *)g_malloc (nsize + 2 + rank + 1);
6717 memcpy (name, eclass->name, nsize);
6720 memset (name + nsize + 1, ',', rank - 1);
6722 name [nsize + rank] = '*';
6723 name [nsize + rank + bounded] = ']';
6724 name [nsize + rank + bounded + 1] = 0;
6725 klass->name = mono_image_strdup (image, name);
6728 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6730 classes_size += sizeof (MonoClass);
6732 klass->type_token = 0;
6733 /* all arrays are marked serializable and sealed, bug #42779 */
6734 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6735 klass->parent = parent;
6736 klass->instance_size = mono_class_instance_size (klass->parent);
6738 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6739 /*Arrays of those two types are invalid.*/
6740 mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL);
6741 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6742 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6743 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6744 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6746 /* element_size -1 is ok as this is not an instantitable type*/
6747 klass->sizes.element_size = -1;
6749 klass->sizes.element_size = mono_class_array_element_size (eclass);
6751 mono_class_setup_supertypes (klass);
6753 if (eclass->generic_class)
6754 mono_class_init (eclass);
6755 if (!eclass->size_inited)
6756 mono_class_setup_fields (eclass);
6757 if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6758 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6760 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6764 if (eclass->enumtype)
6765 klass->cast_class = eclass->element_class;
6767 klass->cast_class = eclass;
6769 switch (klass->cast_class->byval_arg.type) {
6771 klass->cast_class = mono_defaults.byte_class;
6774 klass->cast_class = mono_defaults.int16_class;
6777 #if SIZEOF_VOID_P == 4
6781 klass->cast_class = mono_defaults.int32_class;
6784 #if SIZEOF_VOID_P == 8
6788 klass->cast_class = mono_defaults.int64_class;
6794 klass->element_class = eclass;
6796 if ((rank > 1) || bounded) {
6797 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6798 klass->byval_arg.type = MONO_TYPE_ARRAY;
6799 klass->byval_arg.data.array = at;
6800 at->eklass = eclass;
6802 /* FIXME: complete.... */
6804 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6805 klass->byval_arg.data.klass = eclass;
6807 klass->this_arg = klass->byval_arg;
6808 klass->this_arg.byref = 1;
6813 klass->generic_container = eclass->generic_container;
6815 if (rank == 1 && !bounded) {
6816 MonoClass *prev_class;
6818 mono_os_mutex_lock (&image->szarray_cache_lock);
6819 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6821 /* Someone got in before us */
6824 g_hash_table_insert (image->szarray_cache, eclass, klass);
6825 mono_os_mutex_unlock (&image->szarray_cache_lock);
6827 list = g_slist_append (rootlist, klass);
6828 g_hash_table_insert (image->array_cache, eclass, list);
6831 mono_loader_unlock ();
6833 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6839 * mono_array_class_get:
6840 * @element_class: element class
6841 * @rank: the dimension of the array class
6843 * Returns: A class object describing the array with element type @element_type and
6847 mono_array_class_get (MonoClass *eclass, guint32 rank)
6849 return mono_bounded_array_class_get (eclass, rank, FALSE);
6853 * mono_class_instance_size:
6856 * Use to get the size of a class in bytes.
6858 * Returns: The size of an object instance
6861 mono_class_instance_size (MonoClass *klass)
6863 if (!klass->size_inited)
6864 mono_class_init (klass);
6866 return klass->instance_size;
6870 * mono_class_min_align:
6873 * Use to get the computed minimum alignment requirements for the specified class.
6875 * Returns: minimm alignment requirements
6878 mono_class_min_align (MonoClass *klass)
6880 if (!klass->size_inited)
6881 mono_class_init (klass);
6883 return klass->min_align;
6887 * mono_class_value_size:
6890 * This function is used for value types, and return the
6891 * space and the alignment to store that kind of value object.
6893 * Returns: the size of a value of kind @klass
6896 mono_class_value_size (MonoClass *klass, guint32 *align)
6900 /* fixme: check disable, because we still have external revereces to
6901 * mscorlib and Dummy Objects
6903 /*g_assert (klass->valuetype);*/
6905 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6908 *align = klass->min_align;
6914 * mono_class_data_size:
6917 * Returns: The size of the static class data
6920 mono_class_data_size (MonoClass *klass)
6923 mono_class_init (klass);
6924 /* This can happen with dynamically created types */
6925 if (!klass->fields_inited)
6926 mono_class_setup_fields_locking (klass);
6928 /* in arrays, sizes.class_size is unioned with element_size
6929 * and arrays have no static fields
6933 return klass->sizes.class_size;
6937 * Auxiliary routine to mono_class_get_field
6939 * Takes a field index instead of a field token.
6941 static MonoClassField *
6942 mono_class_get_field_idx (MonoClass *klass, int idx)
6944 mono_class_setup_fields_locking (klass);
6945 if (mono_class_has_failure (klass))
6949 if (klass->image->uncompressed_metadata) {
6951 * klass->field.first points to the FieldPtr table, while idx points into the
6952 * Field table, so we have to do a search.
6954 /*FIXME this is broken for types with multiple fields with the same name.*/
6955 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6958 for (i = 0; i < klass->field.count; ++i)
6959 if (mono_field_get_name (&klass->fields [i]) == name)
6960 return &klass->fields [i];
6961 g_assert_not_reached ();
6963 if (klass->field.count) {
6964 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6965 return &klass->fields [idx - klass->field.first];
6969 klass = klass->parent;
6975 * mono_class_get_field:
6976 * @class: the class to lookup the field.
6977 * @field_token: the field token
6979 * Returns: A MonoClassField representing the type and offset of
6980 * the field, or a NULL value if the field does not belong to this
6984 mono_class_get_field (MonoClass *klass, guint32 field_token)
6986 int idx = mono_metadata_token_index (field_token);
6988 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6990 return mono_class_get_field_idx (klass, idx - 1);
6994 * mono_class_get_field_from_name:
6995 * @klass: the class to lookup the field.
6996 * @name: the field name
6998 * Search the class @klass and it's parents for a field with the name @name.
7000 * Returns: The MonoClassField pointer of the named field or NULL
7003 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7005 return mono_class_get_field_from_name_full (klass, name, NULL);
7009 * mono_class_get_field_from_name_full:
7010 * @klass: the class to lookup the field.
7011 * @name: the field name
7012 * @type: the type of the fields. This optional.
7014 * Search the class @klass and it's parents for a field with the name @name and type @type.
7016 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7017 * of its generic type definition.
7019 * Returns: The MonoClassField pointer of the named field or NULL
7022 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7026 mono_class_setup_fields_locking (klass);
7027 if (mono_class_has_failure (klass))
7031 for (i = 0; i < klass->field.count; ++i) {
7032 MonoClassField *field = &klass->fields [i];
7034 if (strcmp (name, mono_field_get_name (field)) != 0)
7038 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7039 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7044 klass = klass->parent;
7050 * mono_class_get_field_token:
7051 * @field: the field we need the token of
7053 * Get the token of a field. Note that the tokesn is only valid for the image
7054 * the field was loaded from. Don't use this function for fields in dynamic types.
7056 * Returns: The token representing the field in the image it was loaded from.
7059 mono_class_get_field_token (MonoClassField *field)
7061 MonoClass *klass = field->parent;
7064 mono_class_setup_fields_locking (klass);
7069 for (i = 0; i < klass->field.count; ++i) {
7070 if (&klass->fields [i] == field) {
7071 int idx = klass->field.first + i + 1;
7073 if (klass->image->uncompressed_metadata)
7074 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7075 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7078 klass = klass->parent;
7081 g_assert_not_reached ();
7086 mono_field_get_index (MonoClassField *field)
7088 int index = field - field->parent->fields;
7090 g_assert (index >= 0 && index < field->parent->field.count);
7096 * mono_class_get_field_default_value:
7098 * Return the default value of the field as a pointer into the metadata blob.
7101 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7104 guint32 constant_cols [MONO_CONSTANT_SIZE];
7106 MonoClass *klass = field->parent;
7108 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7110 if (!klass->ext || !klass->ext->field_def_values) {
7111 MonoFieldDefaultValue *def_values;
7113 mono_class_alloc_ext (klass);
7115 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7117 mono_image_lock (klass->image);
7118 mono_memory_barrier ();
7119 if (!klass->ext->field_def_values)
7120 klass->ext->field_def_values = def_values;
7121 mono_image_unlock (klass->image);
7124 field_index = mono_field_get_index (field);
7126 if (!klass->ext->field_def_values [field_index].data) {
7127 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7131 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7133 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7134 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7135 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7138 *def_type = klass->ext->field_def_values [field_index].def_type;
7139 return klass->ext->field_def_values [field_index].data;
7143 mono_property_get_index (MonoProperty *prop)
7145 int index = prop - prop->parent->ext->properties;
7147 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7153 * mono_class_get_property_default_value:
7155 * Return the default value of the field as a pointer into the metadata blob.
7158 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7161 guint32 constant_cols [MONO_CONSTANT_SIZE];
7162 MonoClass *klass = property->parent;
7164 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7166 * We don't cache here because it is not used by C# so it's quite rare, but
7167 * we still do the lookup in klass->ext because that is where the data
7168 * is stored for dynamic assemblies.
7171 if (image_is_dynamic (klass->image)) {
7172 int prop_index = mono_property_get_index (property);
7173 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7174 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7175 return klass->ext->prop_def_values [prop_index].data;
7179 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7183 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7184 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7185 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7189 mono_class_get_event_token (MonoEvent *event)
7191 MonoClass *klass = event->parent;
7196 for (i = 0; i < klass->ext->event.count; ++i) {
7197 if (&klass->ext->events [i] == event)
7198 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7201 klass = klass->parent;
7204 g_assert_not_reached ();
7209 * mono_class_get_property_from_name:
7211 * @name: name of the property to lookup in the specified class
7213 * Use this method to lookup a property in a class
7214 * Returns: the MonoProperty with the given name, or NULL if the property
7215 * does not exist on the @klass.
7218 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7222 gpointer iter = NULL;
7223 while ((p = mono_class_get_properties (klass, &iter))) {
7224 if (! strcmp (name, p->name))
7227 klass = klass->parent;
7233 * mono_class_get_property_token:
7234 * @prop: MonoProperty to query
7236 * Returns: The ECMA token for the specified property.
7239 mono_class_get_property_token (MonoProperty *prop)
7241 MonoClass *klass = prop->parent;
7245 gpointer iter = NULL;
7246 while ((p = mono_class_get_properties (klass, &iter))) {
7247 if (&klass->ext->properties [i] == prop)
7248 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7252 klass = klass->parent;
7255 g_assert_not_reached ();
7260 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7262 const char *name, *nspace;
7263 if (image_is_dynamic (image))
7264 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7266 switch (type_token & 0xff000000){
7267 case MONO_TOKEN_TYPE_DEF: {
7268 guint32 cols [MONO_TYPEDEF_SIZE];
7269 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7270 guint tidx = mono_metadata_token_index (type_token);
7272 if (tidx > tt->rows)
7273 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7275 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7276 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7277 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7278 if (strlen (nspace) == 0)
7279 return g_strdup_printf ("%s", name);
7281 return g_strdup_printf ("%s.%s", nspace, name);
7284 case MONO_TOKEN_TYPE_REF: {
7286 guint32 cols [MONO_TYPEREF_SIZE];
7287 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7288 guint tidx = mono_metadata_token_index (type_token);
7291 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7293 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7294 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7295 mono_error_cleanup (&error);
7299 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7300 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7301 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7302 if (strlen (nspace) == 0)
7303 return g_strdup_printf ("%s", name);
7305 return g_strdup_printf ("%s.%s", nspace, name);
7308 case MONO_TOKEN_TYPE_SPEC:
7309 return g_strdup_printf ("Typespec 0x%08x", type_token);
7311 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7316 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7318 if (image_is_dynamic (image))
7319 return g_strdup_printf ("DynamicAssembly %s", image->name);
7321 switch (type_token & 0xff000000){
7322 case MONO_TOKEN_TYPE_DEF:
7323 if (image->assembly)
7324 return mono_stringify_assembly_name (&image->assembly->aname);
7325 else if (image->assembly_name)
7326 return g_strdup (image->assembly_name);
7327 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7328 case MONO_TOKEN_TYPE_REF: {
7330 MonoAssemblyName aname;
7331 guint32 cols [MONO_TYPEREF_SIZE];
7332 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7333 guint32 idx = mono_metadata_token_index (type_token);
7336 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7338 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7339 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7340 mono_error_cleanup (&error);
7343 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7345 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7346 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7347 case MONO_RESOLUTION_SCOPE_MODULE:
7349 return g_strdup ("");
7350 case MONO_RESOLUTION_SCOPE_MODULEREF:
7352 return g_strdup ("");
7353 case MONO_RESOLUTION_SCOPE_TYPEREF:
7355 return g_strdup ("");
7356 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7357 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7358 return mono_stringify_assembly_name (&aname);
7360 g_assert_not_reached ();
7364 case MONO_TOKEN_TYPE_SPEC:
7366 return g_strdup ("");
7368 g_assert_not_reached ();
7375 * mono_class_get_full:
7376 * @image: the image where the class resides
7377 * @type_token: the token for the class
7378 * @context: the generic context used to evaluate generic instantiations in
7379 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7381 * Returns: The MonoClass that represents @type_token in @image
7384 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
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);
7393 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7399 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7403 mono_error_init (error);
7404 klass = mono_class_get_checked (image, type_token, error);
7406 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7407 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7412 * mono_class_get_checked:
7413 * @image: the image where the class resides
7414 * @type_token: the token for the class
7415 * @error: error object to return any error
7417 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7420 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7422 MonoClass *klass = NULL;
7424 mono_error_init (error);
7426 if (image_is_dynamic (image)) {
7427 int table = mono_metadata_token_table (type_token);
7429 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7430 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7433 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7437 switch (type_token & 0xff000000){
7438 case MONO_TOKEN_TYPE_DEF:
7439 klass = mono_class_create_from_typedef (image, type_token, error);
7441 case MONO_TOKEN_TYPE_REF:
7442 klass = mono_class_from_typeref_checked (image, type_token, error);
7444 case MONO_TOKEN_TYPE_SPEC:
7445 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7448 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7452 /* Generic case, should be avoided for when a better error is possible. */
7453 if (!klass && mono_error_ok (error)) {
7454 char *name = mono_class_name_from_token (image, type_token);
7455 char *assembly = mono_assembly_name_from_token (image, type_token);
7456 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7464 * mono_type_get_checked:
7465 * @image: the image where the type resides
7466 * @type_token: the token for the type
7467 * @context: the generic context used to evaluate generic instantiations in
7468 * @error: Error handling context
7470 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7472 * Returns: The MonoType that represents @type_token in @image
7475 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7477 MonoType *type = NULL;
7478 gboolean inflated = FALSE;
7480 mono_error_init (error);
7482 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7483 if (image_is_dynamic (image)) {
7484 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7485 return_val_if_nok (error, NULL);
7486 return mono_class_get_type (klass);
7489 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7490 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7497 return mono_class_get_type (klass);
7500 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7507 MonoType *tmp = type;
7508 type = mono_class_get_type (mono_class_from_mono_type (type));
7509 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7510 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7511 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7513 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7515 if (type->type != tmp->type)
7518 mono_metadata_free_type (tmp);
7525 * @image: image where the class token will be looked up.
7526 * @type_token: a type token from the image
7528 * Returns the MonoClass with the given @type_token on the @image
7531 mono_class_get (MonoImage *image, guint32 type_token)
7533 return mono_class_get_full (image, type_token, NULL);
7537 * mono_image_init_name_cache:
7539 * Initializes the class name cache stored in image->name_cache.
7541 * LOCKING: Acquires the corresponding image lock.
7544 mono_image_init_name_cache (MonoImage *image)
7546 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7547 guint32 cols [MONO_TYPEDEF_SIZE];
7550 guint32 i, visib, nspace_index;
7551 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7553 if (image->name_cache)
7556 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7558 if (image_is_dynamic (image)) {
7559 mono_image_lock (image);
7560 if (image->name_cache) {
7561 /* Somebody initialized it before us */
7562 g_hash_table_destroy (the_name_cache);
7564 mono_atomic_store_release (&image->name_cache, the_name_cache);
7566 mono_image_unlock (image);
7570 /* Temporary hash table to avoid lookups in the nspace_table */
7571 name_cache2 = g_hash_table_new (NULL, NULL);
7573 for (i = 1; i <= t->rows; ++i) {
7574 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7575 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7577 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7578 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7580 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7582 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7583 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7585 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7586 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7587 if (!nspace_table) {
7588 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7589 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7590 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7593 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7596 /* Load type names from EXPORTEDTYPES table */
7598 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7599 guint32 cols [MONO_EXP_TYPE_SIZE];
7602 for (i = 0; i < t->rows; ++i) {
7603 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7605 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7606 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7610 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7611 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7613 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7614 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7615 if (!nspace_table) {
7616 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7617 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7618 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7621 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7625 g_hash_table_destroy (name_cache2);
7627 mono_image_lock (image);
7628 if (image->name_cache) {
7629 /* Somebody initialized it before us */
7630 g_hash_table_destroy (the_name_cache);
7632 mono_atomic_store_release (&image->name_cache, the_name_cache);
7634 mono_image_unlock (image);
7637 /*FIXME Only dynamic assemblies should allow this operation.*/
7639 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7640 const char *name, guint32 index)
7642 GHashTable *nspace_table;
7643 GHashTable *name_cache;
7646 mono_image_init_name_cache (image);
7647 mono_image_lock (image);
7649 name_cache = image->name_cache;
7650 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7651 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7652 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7655 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7656 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7658 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7660 mono_image_unlock (image);
7669 find_nocase (gpointer key, gpointer value, gpointer user_data)
7671 char *name = (char*)key;
7672 FindUserData *data = (FindUserData*)user_data;
7674 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7675 data->value = value;
7679 * mono_class_from_name_case:
7680 * @image: The MonoImage where the type is looked up in
7681 * @name_space: the type namespace
7682 * @name: the type short name.
7683 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7685 * Obtains a MonoClass with a given namespace and a given name which
7686 * is located in the given MonoImage. The namespace and name
7687 * lookups are case insensitive.
7690 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7693 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7694 mono_error_cleanup (&error);
7700 * mono_class_from_name_case:
7701 * @image: The MonoImage where the type is looked up in
7702 * @name_space: the type namespace
7703 * @name: the type short name.
7706 * Obtains a MonoClass with a given namespace and a given name which
7707 * is located in the given MonoImage. The namespace and name
7708 * lookups are case insensitive.
7710 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7711 * was not found. The @error object will contain information about the problem
7715 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7717 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7718 guint32 cols [MONO_TYPEDEF_SIZE];
7723 mono_error_init (error);
7725 if (image_is_dynamic (image)) {
7727 FindUserData user_data;
7729 mono_image_init_name_cache (image);
7730 mono_image_lock (image);
7732 user_data.key = name_space;
7733 user_data.value = NULL;
7734 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7736 if (user_data.value) {
7737 GHashTable *nspace_table = (GHashTable*)user_data.value;
7739 user_data.key = name;
7740 user_data.value = NULL;
7742 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7744 if (user_data.value)
7745 token = GPOINTER_TO_UINT (user_data.value);
7748 mono_image_unlock (image);
7751 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7757 /* add a cache if needed */
7758 for (i = 1; i <= t->rows; ++i) {
7759 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7760 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7762 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7763 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7765 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7767 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7768 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7769 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7770 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7776 return_nested_in (MonoClass *klass, char *nested)
7779 char *s = strchr (nested, '/');
7780 gpointer iter = NULL;
7787 while ((found = mono_class_get_nested_types (klass, &iter))) {
7788 if (strcmp (found->name, nested) == 0) {
7790 return return_nested_in (found, s);
7798 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7800 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7801 MonoImage *file_image;
7805 mono_error_init (error);
7808 * The EXPORTEDTYPES table only contains public types, so have to search the
7810 * Note: image->modules contains the contents of the MODULEREF table, while
7811 * the real module list is in the FILE table.
7813 for (i = 0; i < file_table->rows; i++) {
7814 guint32 cols [MONO_FILE_SIZE];
7815 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7816 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7819 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7821 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7822 if (klass || !is_ok (error))
7831 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7833 GHashTable *nspace_table;
7834 MonoImage *loaded_image;
7841 mono_error_init (error);
7843 // Checking visited images avoids stack overflows when cyclic references exist.
7844 if (g_hash_table_lookup (visited_images, image))
7847 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7849 if ((nested = strchr (name, '/'))) {
7850 int pos = nested - name;
7851 int len = strlen (name);
7854 memcpy (buf, name, len + 1);
7856 nested = buf + pos + 1;
7860 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7861 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7862 gboolean res = get_class_from_name (image, name_space, name, &klass);
7865 klass = search_modules (image, name_space, name, error);
7870 return klass ? return_nested_in (klass, nested) : NULL;
7876 mono_image_init_name_cache (image);
7877 mono_image_lock (image);
7879 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7882 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7884 mono_image_unlock (image);
7886 if (!token && image_is_dynamic (image) && image->modules) {
7887 /* Search modules as well */
7888 for (i = 0; i < image->module_count; ++i) {
7889 MonoImage *module = image->modules [i];
7891 klass = mono_class_from_name_checked (module, name_space, name, error);
7892 if (klass || !is_ok (error))
7898 klass = search_modules (image, name_space, name, error);
7899 if (klass || !is_ok (error))
7904 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7905 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7906 guint32 cols [MONO_EXP_TYPE_SIZE];
7909 idx = mono_metadata_token_index (token);
7911 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7913 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7914 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7915 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7918 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7920 return klass ? return_nested_in (klass, nested) : NULL;
7922 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7923 guint32 assembly_idx;
7925 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7927 mono_assembly_load_reference (image, assembly_idx - 1);
7928 g_assert (image->references [assembly_idx - 1]);
7929 if (image->references [assembly_idx - 1] == (gpointer)-1)
7931 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7933 return klass ? return_nested_in (klass, nested) : NULL;
7936 g_assert_not_reached ();
7940 token = MONO_TOKEN_TYPE_DEF | token;
7942 klass = mono_class_get_checked (image, token, error);
7944 return return_nested_in (klass, nested);
7949 * mono_class_from_name_checked:
7950 * @image: The MonoImage where the type is looked up in
7951 * @name_space: the type namespace
7952 * @name: the type short name.
7954 * Obtains a MonoClass with a given namespace and a given name which
7955 * is located in the given MonoImage.
7957 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7958 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7961 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7964 GHashTable *visited_images;
7966 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7968 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7970 g_hash_table_destroy (visited_images);
7976 * mono_class_from_name:
7977 * @image: The MonoImage where the type is looked up in
7978 * @name_space: the type namespace
7979 * @name: the type short name.
7981 * Obtains a MonoClass with a given namespace and a given name which
7982 * is located in the given MonoImage.
7984 * To reference nested classes, use the "/" character as a separator.
7985 * For example use "Foo/Bar" to reference the class Bar that is nested
7986 * inside Foo, like this: "class Foo { class Bar {} }".
7989 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7994 klass = mono_class_from_name_checked (image, name_space, name, &error);
7995 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8001 * mono_class_load_from_name:
8002 * @image: The MonoImage where the type is looked up in
8003 * @name_space: the type namespace
8004 * @name: the type short name.
8006 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8007 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8008 * If they are missing. Thing of System.Object or System.String.
8011 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8016 klass = mono_class_from_name_checked (image, name_space, name, &error);
8018 g_error ("Runtime critical type %s.%s not found", name_space, name);
8019 if (!mono_error_ok (&error))
8020 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8025 * mono_class_try_load_from_name:
8026 * @image: The MonoImage where the type is looked up in
8027 * @name_space: the type namespace
8028 * @name: the type short name.
8030 * This function tries to load a type, returning the class was found or NULL otherwise.
8031 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8033 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8034 * a type that we would otherwise assume to be available but was not due some error.
8038 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8043 klass = mono_class_from_name_checked (image, name_space, name, &error);
8044 if (!mono_error_ok (&error))
8045 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8051 * mono_class_is_subclass_of:
8052 * @klass: class to probe if it is a subclass of another one
8053 * @klassc: the class we suspect is the base class
8054 * @check_interfaces: whether we should perform interface checks
8056 * This method determines whether @klass is a subclass of @klassc.
8058 * If the @check_interfaces flag is set, then if @klassc is an interface
8059 * this method return TRUE if the @klass implements the interface or
8060 * if @klass is an interface, if one of its base classes is @klass.
8062 * If @check_interfaces is false then, then if @klass is not an interface
8063 * then it returns TRUE if the @klass is a subclass of @klassc.
8065 * if @klass is an interface and @klassc is System.Object, then this function
8070 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8071 gboolean check_interfaces)
8073 /* FIXME test for interfaces with variant generic arguments */
8074 mono_class_init (klass);
8075 mono_class_init (klassc);
8077 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8078 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8080 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8083 for (i = 0; i < klass->interface_count; i ++) {
8084 MonoClass *ic = klass->interfaces [i];
8089 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8094 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8097 if (klassc == mono_defaults.object_class)
8104 mono_type_is_generic_argument (MonoType *type)
8106 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8110 mono_class_has_variant_generic_params (MonoClass *klass)
8113 MonoGenericContainer *container;
8115 if (!klass->generic_class)
8118 container = klass->generic_class->container_class->generic_container;
8120 for (i = 0; i < container->type_argc; ++i)
8121 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8128 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8130 if (target == candidate)
8133 if (check_for_reference_conv &&
8134 mono_type_is_generic_argument (&target->byval_arg) &&
8135 mono_type_is_generic_argument (&candidate->byval_arg)) {
8136 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8137 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8139 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8142 if (!mono_class_is_assignable_from (target, candidate))
8148 * @container the generic container from the GTD
8149 * @klass: the class to be assigned to
8150 * @oklass: the source class
8152 * Both @klass and @oklass must be instances of the same generic interface.
8154 * Returns: TRUE if @klass can be assigned to a @klass variable
8157 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8160 MonoType **klass_argv, **oklass_argv;
8161 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8162 MonoGenericContainer *container = klass_gtd->generic_container;
8164 if (klass == oklass)
8167 /*Viable candidates are instances of the same generic interface*/
8168 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8171 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8172 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8174 for (j = 0; j < container->type_argc; ++j) {
8175 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8176 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8178 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8182 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8183 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8185 if (param1_class != param2_class) {
8186 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8187 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8189 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8190 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8200 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8202 MonoGenericParam *gparam, *ogparam;
8203 MonoGenericParamInfo *tinfo, *cinfo;
8204 MonoClass **candidate_class;
8205 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8208 if (target == candidate)
8210 if (target->byval_arg.type != candidate->byval_arg.type)
8213 gparam = target->byval_arg.data.generic_param;
8214 ogparam = candidate->byval_arg.data.generic_param;
8215 tinfo = mono_generic_param_info (gparam);
8216 cinfo = mono_generic_param_info (ogparam);
8218 class_constraint_satisfied = FALSE;
8219 valuetype_constraint_satisfied = FALSE;
8221 /*candidate must have a super set of target's special constraints*/
8222 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8223 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8225 if (cinfo->constraints) {
8226 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8227 MonoClass *cc = *candidate_class;
8229 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8230 class_constraint_satisfied = TRUE;
8231 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8232 valuetype_constraint_satisfied = TRUE;
8235 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8236 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8238 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8240 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8242 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8243 valuetype_constraint_satisfied)) {
8248 /*candidate type constraints must be a superset of target's*/
8249 if (tinfo->constraints) {
8250 MonoClass **target_class;
8251 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8252 MonoClass *tc = *target_class;
8255 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8256 * check it's constraints since it satisfy the constraint by itself.
8258 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8261 if (!cinfo->constraints)
8264 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8265 MonoClass *cc = *candidate_class;
8267 if (mono_class_is_assignable_from (tc, cc))
8271 * This happens when we have the following:
8273 * Bar<K> where K : IFace
8274 * Foo<T, U> where T : U where U : IFace
8276 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8279 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8280 if (mono_gparam_is_assignable_from (target, cc))
8284 if (!*candidate_class)
8289 /*candidate itself must have a constraint that satisfy target*/
8290 if (cinfo->constraints) {
8291 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8292 MonoClass *cc = *candidate_class;
8293 if (mono_class_is_assignable_from (target, cc))
8301 * mono_class_is_assignable_from:
8302 * @klass: the class to be assigned to
8303 * @oklass: the source class
8305 * Returns: TRUE if an instance of object oklass can be assigned to an
8306 * instance of object @klass
8309 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8312 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8314 mono_class_init (klass);
8316 if (!oklass->inited)
8317 mono_class_init (oklass);
8319 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8322 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8323 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8325 return mono_gparam_is_assignable_from (klass, oklass);
8328 if (MONO_CLASS_IS_INTERFACE (klass)) {
8329 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8330 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8331 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8335 for (i = 0; constraints [i]; ++i) {
8336 if (mono_class_is_assignable_from (klass, constraints [i]))
8344 /* interface_offsets might not be set for dynamic classes */
8345 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8347 * oklass might be a generic type parameter but they have
8348 * interface_offsets set.
8350 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8351 if (!is_ok (&error)) {
8352 mono_error_cleanup (&error);
8357 if (!oklass->interface_bitmap)
8358 /* Happens with generic instances of not-yet created dynamic types */
8360 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8363 if (mono_class_has_variant_generic_params (klass)) {
8365 mono_class_setup_interfaces (oklass, &error);
8366 if (!mono_error_ok (&error)) {
8367 mono_error_cleanup (&error);
8371 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8372 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8373 MonoClass *iface = oklass->interfaces_packed [i];
8375 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8380 } else if (klass->delegate) {
8381 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8383 }else if (klass->rank) {
8384 MonoClass *eclass, *eoclass;
8386 if (oklass->rank != klass->rank)
8389 /* vectors vs. one dimensional arrays */
8390 if (oklass->byval_arg.type != klass->byval_arg.type)
8393 eclass = klass->cast_class;
8394 eoclass = oklass->cast_class;
8397 * a is b does not imply a[] is b[] when a is a valuetype, and
8398 * b is a reference type.
8401 if (eoclass->valuetype) {
8402 if ((eclass == mono_defaults.enum_class) ||
8403 (eclass == mono_defaults.enum_class->parent) ||
8404 (eclass == mono_defaults.object_class))
8408 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8409 } else if (mono_class_is_nullable (klass)) {
8410 if (mono_class_is_nullable (oklass))
8411 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8413 return mono_class_is_assignable_from (klass->cast_class, oklass);
8414 } else if (klass == mono_defaults.object_class)
8417 return mono_class_has_parent (oklass, klass);
8420 /*Check if @oklass is variant compatible with @klass.*/
8422 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8425 MonoType **klass_argv, **oklass_argv;
8426 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8427 MonoGenericContainer *container = klass_gtd->generic_container;
8429 /*Viable candidates are instances of the same generic interface*/
8430 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8433 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8434 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8436 for (j = 0; j < container->type_argc; ++j) {
8437 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8438 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8440 if (param1_class->valuetype != param2_class->valuetype)
8444 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8445 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8447 if (param1_class != param2_class) {
8448 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8449 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8451 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8452 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8460 /*Check if @candidate implements the interface @target*/
8462 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8466 gboolean is_variant = mono_class_has_variant_generic_params (target);
8468 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8469 if (mono_class_is_variant_compatible_slow (target, candidate))
8474 if (candidate == target)
8477 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8478 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8479 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8481 if (tb && tb->interfaces) {
8482 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8483 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8484 MonoClass *iface_class;
8486 /* we can't realize the type here since it can do pretty much anything. */
8489 iface_class = mono_class_from_mono_type (iface->type);
8490 if (iface_class == target)
8492 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8494 if (mono_class_implement_interface_slow (target, iface_class))
8499 /*setup_interfaces don't mono_class_init anything*/
8500 /*FIXME this doesn't handle primitive type arrays.
8501 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8502 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8504 mono_class_setup_interfaces (candidate, &error);
8505 if (!mono_error_ok (&error)) {
8506 mono_error_cleanup (&error);
8510 for (i = 0; i < candidate->interface_count; ++i) {
8511 if (candidate->interfaces [i] == target)
8514 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8517 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8521 candidate = candidate->parent;
8522 } while (candidate);
8528 * Check if @oklass can be assigned to @klass.
8529 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8532 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8534 if (candidate == target)
8536 if (target == mono_defaults.object_class)
8539 if (mono_class_has_parent (candidate, target))
8542 /*If target is not an interface there is no need to check them.*/
8543 if (MONO_CLASS_IS_INTERFACE (target))
8544 return mono_class_implement_interface_slow (target, candidate);
8546 if (target->delegate && mono_class_has_variant_generic_params (target))
8547 return mono_class_is_variant_compatible (target, candidate, FALSE);
8550 MonoClass *eclass, *eoclass;
8552 if (target->rank != candidate->rank)
8555 /* vectors vs. one dimensional arrays */
8556 if (target->byval_arg.type != candidate->byval_arg.type)
8559 eclass = target->cast_class;
8560 eoclass = candidate->cast_class;
8563 * a is b does not imply a[] is b[] when a is a valuetype, and
8564 * b is a reference type.
8567 if (eoclass->valuetype) {
8568 if ((eclass == mono_defaults.enum_class) ||
8569 (eclass == mono_defaults.enum_class->parent) ||
8570 (eclass == mono_defaults.object_class))
8574 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8576 /*FIXME properly handle nullables */
8577 /*FIXME properly handle (M)VAR */
8582 * mono_class_get_cctor:
8583 * @klass: A MonoClass pointer
8585 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8588 mono_class_get_cctor (MonoClass *klass)
8590 MonoCachedClassInfo cached_info;
8592 if (image_is_dynamic (klass->image)) {
8594 * has_cctor is not set for these classes because mono_class_init () is
8597 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8600 if (!klass->has_cctor)
8603 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8605 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8606 if (!mono_error_ok (&error))
8607 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8611 if (klass->generic_class && !klass->methods)
8612 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8614 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8618 * mono_class_get_finalizer:
8619 * @klass: The MonoClass pointer
8621 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8624 mono_class_get_finalizer (MonoClass *klass)
8626 MonoCachedClassInfo cached_info;
8629 mono_class_init (klass);
8630 if (!mono_class_has_finalizer (klass))
8633 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8635 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8636 if (!mono_error_ok (&error))
8637 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8640 mono_class_setup_vtable (klass);
8641 return klass->vtable [finalize_slot];
8646 * mono_class_needs_cctor_run:
8647 * @klass: the MonoClass pointer
8648 * @caller: a MonoMethod describing the caller
8650 * Determines whenever the class has a static constructor and whenever it
8651 * needs to be called when executing CALLER.
8654 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8658 method = mono_class_get_cctor (klass);
8660 return (method == caller) ? FALSE : TRUE;
8666 * mono_class_array_element_size:
8669 * Returns: The number of bytes an element of type @klass
8670 * uses when stored into an array.
8673 mono_class_array_element_size (MonoClass *klass)
8675 MonoType *type = &klass->byval_arg;
8678 switch (type->type) {
8681 case MONO_TYPE_BOOLEAN:
8685 case MONO_TYPE_CHAR:
8694 case MONO_TYPE_CLASS:
8695 case MONO_TYPE_STRING:
8696 case MONO_TYPE_OBJECT:
8697 case MONO_TYPE_SZARRAY:
8698 case MONO_TYPE_ARRAY:
8699 return sizeof (gpointer);
8704 case MONO_TYPE_VALUETYPE:
8705 if (type->data.klass->enumtype) {
8706 type = mono_class_enum_basetype (type->data.klass);
8707 klass = klass->element_class;
8710 return mono_class_instance_size (klass) - sizeof (MonoObject);
8711 case MONO_TYPE_GENERICINST:
8712 type = &type->data.generic_class->container_class->byval_arg;
8715 case MONO_TYPE_MVAR: {
8718 return mono_type_size (type, &align);
8720 case MONO_TYPE_VOID:
8724 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8730 * mono_array_element_size:
8731 * @ac: pointer to a #MonoArrayClass
8733 * Returns: The size of single array element.
8736 mono_array_element_size (MonoClass *ac)
8738 g_assert (ac->rank);
8739 return ac->sizes.element_size;
8743 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8744 MonoGenericContext *context)
8747 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8748 g_assert (mono_error_ok (&error));
8753 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8754 MonoGenericContext *context, MonoError *error)
8756 mono_error_init (error);
8758 if (image_is_dynamic (image)) {
8759 MonoClass *tmp_handle_class;
8760 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8762 mono_error_assert_ok (error);
8763 g_assert (tmp_handle_class);
8765 *handle_class = tmp_handle_class;
8767 if (tmp_handle_class == mono_defaults.typehandle_class)
8768 return &((MonoClass*)obj)->byval_arg;
8773 switch (token & 0xff000000) {
8774 case MONO_TOKEN_TYPE_DEF:
8775 case MONO_TOKEN_TYPE_REF:
8776 case MONO_TOKEN_TYPE_SPEC: {
8779 *handle_class = mono_defaults.typehandle_class;
8780 type = mono_type_get_checked (image, token, context, error);
8784 mono_class_init (mono_class_from_mono_type (type));
8785 /* We return a MonoType* as handle */
8788 case MONO_TOKEN_FIELD_DEF: {
8790 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8792 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8796 *handle_class = mono_defaults.fieldhandle_class;
8797 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8801 mono_class_init (klass);
8802 return mono_class_get_field (klass, token);
8804 case MONO_TOKEN_METHOD_DEF:
8805 case MONO_TOKEN_METHOD_SPEC: {
8807 meth = mono_get_method_checked (image, token, NULL, context, error);
8809 *handle_class = mono_defaults.methodhandle_class;
8815 case MONO_TOKEN_MEMBER_REF: {
8816 guint32 cols [MONO_MEMBERREF_SIZE];
8818 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8819 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8820 mono_metadata_decode_blob_size (sig, &sig);
8821 if (*sig == 0x6) { /* it's a field */
8823 MonoClassField *field;
8824 field = mono_field_from_token_checked (image, token, &klass, context, error);
8826 *handle_class = mono_defaults.fieldhandle_class;
8830 meth = mono_get_method_checked (image, token, NULL, context, error);
8832 *handle_class = mono_defaults.methodhandle_class;
8837 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8843 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8845 MonoClass *handle_class;
8846 mono_error_init (error);
8847 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8851 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8853 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8856 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8859 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8861 get_cached_class_info = func;
8865 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8867 if (!get_cached_class_info)
8870 return get_cached_class_info (klass, res);
8874 mono_install_get_class_from_name (MonoGetClassFromName func)
8876 get_class_from_name = func;
8880 * mono_class_get_image:
8882 * Use this method to get the `MonoImage*` where this class came from.
8884 * Returns: The image where this class is defined.
8887 mono_class_get_image (MonoClass *klass)
8889 return klass->image;
8893 * mono_class_get_element_class:
8894 * @klass: the MonoClass to act on
8896 * Use this function to get the element class of an array.
8898 * Returns: The element class of an array.
8901 mono_class_get_element_class (MonoClass *klass)
8903 return klass->element_class;
8907 * mono_class_is_valuetype:
8908 * @klass: the MonoClass to act on
8910 * Use this method to determine if the provided `MonoClass*` represents a value type,
8911 * or a reference type.
8913 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8916 mono_class_is_valuetype (MonoClass *klass)
8918 return klass->valuetype;
8922 * mono_class_is_enum:
8923 * @klass: the MonoClass to act on
8925 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8927 * Returns: TRUE if the MonoClass represents an enumeration.
8930 mono_class_is_enum (MonoClass *klass)
8932 return klass->enumtype;
8936 * mono_class_enum_basetype:
8937 * @klass: the MonoClass to act on
8939 * Use this function to get the underlying type for an enumeration value.
8941 * Returns: The underlying type representation for an enumeration.
8944 mono_class_enum_basetype (MonoClass *klass)
8946 if (klass->element_class == klass)
8947 /* SRE or broken types */
8950 return &klass->element_class->byval_arg;
8954 * mono_class_get_parent
8955 * @klass: the MonoClass to act on
8957 * Returns: The parent class for this class.
8960 mono_class_get_parent (MonoClass *klass)
8962 return klass->parent;
8966 * mono_class_get_nesting_type:
8967 * @klass: the MonoClass to act on
8969 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8971 * If the return is NULL, this indicates that this class is not nested.
8973 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8976 mono_class_get_nesting_type (MonoClass *klass)
8978 return klass->nested_in;
8982 * mono_class_get_rank:
8983 * @klass: the MonoClass to act on
8985 * Returns: The rank for the array (the number of dimensions).
8988 mono_class_get_rank (MonoClass *klass)
8994 * mono_class_get_flags:
8995 * @klass: the MonoClass to act on
8997 * The type flags from the TypeDef table from the metadata.
8998 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
9001 * Returns: The flags from the TypeDef table.
9004 mono_class_get_flags (MonoClass *klass)
9006 return klass->flags;
9010 * mono_class_get_name
9011 * @klass: the MonoClass to act on
9013 * Returns: The name of the class.
9016 mono_class_get_name (MonoClass *klass)
9022 * mono_class_get_namespace:
9023 * @klass: the MonoClass to act on
9025 * Returns: The namespace of the class.
9028 mono_class_get_namespace (MonoClass *klass)
9030 return klass->name_space;
9034 * mono_class_get_type:
9035 * @klass: the MonoClass to act on
9037 * This method returns the internal Type representation for the class.
9039 * Returns: The MonoType from the class.
9042 mono_class_get_type (MonoClass *klass)
9044 return &klass->byval_arg;
9048 * mono_class_get_type_token:
9049 * @klass: the MonoClass to act on
9051 * This method returns type token for the class.
9053 * Returns: The type token for the class.
9056 mono_class_get_type_token (MonoClass *klass)
9058 return klass->type_token;
9062 * mono_class_get_byref_type:
9063 * @klass: the MonoClass to act on
9068 mono_class_get_byref_type (MonoClass *klass)
9070 return &klass->this_arg;
9074 * mono_class_num_fields:
9075 * @klass: the MonoClass to act on
9077 * Returns: The number of static and instance fields in the class.
9080 mono_class_num_fields (MonoClass *klass)
9082 return klass->field.count;
9086 * mono_class_num_methods:
9087 * @klass: the MonoClass to act on
9089 * Returns: The number of methods in the class.
9092 mono_class_num_methods (MonoClass *klass)
9094 return klass->method.count;
9098 * mono_class_num_properties
9099 * @klass: the MonoClass to act on
9101 * Returns: The number of properties in the class.
9104 mono_class_num_properties (MonoClass *klass)
9106 mono_class_setup_properties (klass);
9108 return klass->ext->property.count;
9112 * mono_class_num_events:
9113 * @klass: the MonoClass to act on
9115 * Returns: The number of events in the class.
9118 mono_class_num_events (MonoClass *klass)
9120 mono_class_setup_events (klass);
9122 return klass->ext->event.count;
9126 * mono_class_get_fields:
9127 * @klass: the MonoClass to act on
9129 * This routine is an iterator routine for retrieving the fields in a class.
9131 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9132 * iterate over all of the elements. When no more values are
9133 * available, the return value is NULL.
9135 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9138 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9140 MonoClassField* field;
9144 mono_class_setup_fields_locking (klass);
9145 if (mono_class_has_failure (klass))
9147 /* start from the first */
9148 if (klass->field.count) {
9149 *iter = &klass->fields [0];
9150 return &klass->fields [0];
9156 field = (MonoClassField *)*iter;
9158 if (field < &klass->fields [klass->field.count]) {
9166 * mono_class_get_methods
9167 * @klass: the MonoClass to act on
9169 * This routine is an iterator routine for retrieving the fields in a class.
9171 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9172 * iterate over all of the elements. When no more values are
9173 * available, the return value is NULL.
9175 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9178 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9180 MonoMethod** method;
9184 mono_class_setup_methods (klass);
9187 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9188 * FIXME we should better report this error to the caller
9190 if (!klass->methods)
9192 /* start from the first */
9193 if (klass->method.count) {
9194 *iter = &klass->methods [0];
9195 return klass->methods [0];
9201 method = (MonoMethod **)*iter;
9203 if (method < &klass->methods [klass->method.count]) {
9211 * mono_class_get_virtual_methods:
9213 * Iterate over the virtual methods of KLASS.
9215 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9218 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9220 MonoMethod** method;
9223 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9225 mono_class_setup_methods (klass);
9227 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9228 * FIXME we should better report this error to the caller
9230 if (!klass->methods)
9232 /* start from the first */
9233 method = &klass->methods [0];
9235 method = (MonoMethod **)*iter;
9238 while (method < &klass->methods [klass->method.count]) {
9239 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9243 if (method < &klass->methods [klass->method.count]) {
9250 /* Search directly in metadata to avoid calling setup_methods () */
9251 MonoMethod *res = NULL;
9257 start_index = GPOINTER_TO_UINT (*iter);
9260 for (i = start_index; i < klass->method.count; ++i) {
9263 /* klass->method.first points into the methodptr table */
9264 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9266 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9270 if (i < klass->method.count) {
9272 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9273 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9275 /* Add 1 here so the if (*iter) check fails */
9276 *iter = GUINT_TO_POINTER (i + 1);
9285 * mono_class_get_properties:
9286 * @klass: the MonoClass to act on
9288 * This routine is an iterator routine for retrieving the properties in a class.
9290 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9291 * iterate over all of the elements. When no more values are
9292 * available, the return value is NULL.
9294 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9297 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9299 MonoProperty* property;
9303 mono_class_setup_properties (klass);
9304 /* start from the first */
9305 if (klass->ext->property.count) {
9306 *iter = &klass->ext->properties [0];
9307 return (MonoProperty *)*iter;
9313 property = (MonoProperty *)*iter;
9315 if (property < &klass->ext->properties [klass->ext->property.count]) {
9317 return (MonoProperty *)*iter;
9323 * mono_class_get_events:
9324 * @klass: the MonoClass to act on
9326 * This routine is an iterator routine for retrieving the properties in a class.
9328 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9329 * iterate over all of the elements. When no more values are
9330 * available, the return value is NULL.
9332 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9335 mono_class_get_events (MonoClass* klass, gpointer *iter)
9341 mono_class_setup_events (klass);
9342 /* start from the first */
9343 if (klass->ext->event.count) {
9344 *iter = &klass->ext->events [0];
9345 return (MonoEvent *)*iter;
9351 event = (MonoEvent *)*iter;
9353 if (event < &klass->ext->events [klass->ext->event.count]) {
9355 return (MonoEvent *)*iter;
9361 * mono_class_get_interfaces
9362 * @klass: the MonoClass to act on
9364 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9366 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9367 * iterate over all of the elements. When no more values are
9368 * available, the return value is NULL.
9370 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9373 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9381 mono_class_init (klass);
9382 if (!klass->interfaces_inited) {
9383 mono_class_setup_interfaces (klass, &error);
9384 if (!mono_error_ok (&error)) {
9385 mono_error_cleanup (&error);
9389 /* start from the first */
9390 if (klass->interface_count) {
9391 *iter = &klass->interfaces [0];
9392 return klass->interfaces [0];
9398 iface = (MonoClass **)*iter;
9400 if (iface < &klass->interfaces [klass->interface_count]) {
9408 setup_nested_types (MonoClass *klass)
9411 GList *classes, *nested_classes, *l;
9414 if (klass->nested_classes_inited)
9417 if (!klass->type_token)
9418 klass->nested_classes_inited = TRUE;
9420 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9424 guint32 cols [MONO_NESTED_CLASS_SIZE];
9425 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9426 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9427 if (!mono_error_ok (&error)) {
9428 /*FIXME don't swallow the error message*/
9429 mono_error_cleanup (&error);
9431 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9435 classes = g_list_prepend (classes, nclass);
9437 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9440 mono_class_alloc_ext (klass);
9442 nested_classes = NULL;
9443 for (l = classes; l; l = l->next)
9444 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9445 g_list_free (classes);
9447 mono_image_lock (klass->image);
9449 mono_memory_barrier ();
9450 if (!klass->nested_classes_inited) {
9451 klass->ext->nested_classes = nested_classes;
9452 mono_memory_barrier ();
9453 klass->nested_classes_inited = TRUE;
9456 mono_image_unlock (klass->image);
9460 * mono_class_get_nested_types
9461 * @klass: the MonoClass to act on
9463 * This routine is an iterator routine for retrieving the nested types of a class.
9464 * This works only if @klass is non-generic, or a generic type definition.
9466 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9467 * iterate over all of the elements. When no more values are
9468 * available, the return value is NULL.
9470 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9473 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9479 if (!klass->nested_classes_inited)
9480 setup_nested_types (klass);
9483 /* start from the first */
9484 if (klass->ext && klass->ext->nested_classes) {
9485 *iter = klass->ext->nested_classes;
9486 return (MonoClass *)klass->ext->nested_classes->data;
9488 /* no nested types */
9492 item = (GList *)*iter;
9496 return (MonoClass *)item->data;
9503 * mono_class_is_delegate
9504 * @klass: the MonoClass to act on
9506 * Returns: TRUE if the MonoClass represents a System.Delegate.
9509 mono_class_is_delegate (MonoClass *klass)
9511 return klass->delegate;
9515 * mono_class_implements_interface
9516 * @klass: The MonoClass to act on
9517 * @interface: The interface to check if @klass implements.
9519 * Returns: TRUE if @klass implements @interface.
9522 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9524 return mono_class_is_assignable_from (iface, klass);
9528 * mono_field_get_name:
9529 * @field: the MonoClassField to act on
9531 * Returns: The name of the field.
9534 mono_field_get_name (MonoClassField *field)
9540 * mono_field_get_type:
9541 * @field: the MonoClassField to act on
9543 * Returns: MonoType of the field.
9546 mono_field_get_type (MonoClassField *field)
9549 MonoType *type = mono_field_get_type_checked (field, &error);
9550 if (!mono_error_ok (&error)) {
9551 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9552 mono_error_cleanup (&error);
9559 * mono_field_get_type_checked:
9560 * @field: the MonoClassField to act on
9561 * @error: used to return any erro found while retrieving @field type
9563 * Returns: MonoType of the field.
9566 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9568 mono_error_init (error);
9570 mono_field_resolve_type (field, error);
9575 * mono_field_get_parent:
9576 * @field: the MonoClassField to act on
9578 * Returns: MonoClass where the field was defined.
9581 mono_field_get_parent (MonoClassField *field)
9583 return field->parent;
9587 * mono_field_get_flags;
9588 * @field: the MonoClassField to act on
9590 * The metadata flags for a field are encoded using the
9591 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9593 * Returns: The flags for the field.
9596 mono_field_get_flags (MonoClassField *field)
9599 return mono_field_resolve_flags (field);
9600 return field->type->attrs;
9604 * mono_field_get_offset:
9605 * @field: the MonoClassField to act on
9607 * Returns: The field offset.
9610 mono_field_get_offset (MonoClassField *field)
9612 return field->offset;
9616 mono_field_get_rva (MonoClassField *field)
9620 MonoClass *klass = field->parent;
9621 MonoFieldDefaultValue *field_def_values;
9623 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9625 if (!klass->ext || !klass->ext->field_def_values) {
9626 mono_class_alloc_ext (klass);
9628 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9630 mono_image_lock (klass->image);
9631 if (!klass->ext->field_def_values)
9632 klass->ext->field_def_values = field_def_values;
9633 mono_image_unlock (klass->image);
9636 field_index = mono_field_get_index (field);
9638 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9639 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9641 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9642 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9645 return klass->ext->field_def_values [field_index].data;
9649 * mono_field_get_data:
9650 * @field: the MonoClassField to act on
9652 * Returns: A pointer to the metadata constant value or to the field
9653 * data if it has an RVA flag.
9656 mono_field_get_data (MonoClassField *field)
9658 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9659 MonoTypeEnum def_type;
9661 return mono_class_get_field_default_value (field, &def_type);
9662 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9663 return mono_field_get_rva (field);
9670 * mono_property_get_name:
9671 * @prop: the MonoProperty to act on
9673 * Returns: The name of the property
9676 mono_property_get_name (MonoProperty *prop)
9682 * mono_property_get_set_method
9683 * @prop: the MonoProperty to act on.
9685 * Returns: The setter method of the property (A MonoMethod)
9688 mono_property_get_set_method (MonoProperty *prop)
9694 * mono_property_get_get_method
9695 * @prop: the MonoProperty to act on.
9697 * Returns: The setter method of the property (A MonoMethod)
9700 mono_property_get_get_method (MonoProperty *prop)
9706 * mono_property_get_parent:
9707 * @prop: the MonoProperty to act on.
9709 * Returns: The MonoClass where the property was defined.
9712 mono_property_get_parent (MonoProperty *prop)
9714 return prop->parent;
9718 * mono_property_get_flags:
9719 * @prop: the MonoProperty to act on.
9721 * The metadata flags for a property are encoded using the
9722 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9724 * Returns: The flags for the property.
9727 mono_property_get_flags (MonoProperty *prop)
9733 * mono_event_get_name:
9734 * @event: the MonoEvent to act on
9736 * Returns: The name of the event.
9739 mono_event_get_name (MonoEvent *event)
9745 * mono_event_get_add_method:
9746 * @event: The MonoEvent to act on.
9748 * Returns: The @add' method for the event (a MonoMethod).
9751 mono_event_get_add_method (MonoEvent *event)
9757 * mono_event_get_remove_method:
9758 * @event: The MonoEvent to act on.
9760 * Returns: The @remove method for the event (a MonoMethod).
9763 mono_event_get_remove_method (MonoEvent *event)
9765 return event->remove;
9769 * mono_event_get_raise_method:
9770 * @event: The MonoEvent to act on.
9772 * Returns: The @raise method for the event (a MonoMethod).
9775 mono_event_get_raise_method (MonoEvent *event)
9777 return event->raise;
9781 * mono_event_get_parent:
9782 * @event: the MonoEvent to act on.
9784 * Returns: The MonoClass where the event is defined.
9787 mono_event_get_parent (MonoEvent *event)
9789 return event->parent;
9793 * mono_event_get_flags
9794 * @event: the MonoEvent to act on.
9796 * The metadata flags for an event are encoded using the
9797 * EVENT_* constants. See the tabledefs.h file for details.
9799 * Returns: The flags for the event.
9802 mono_event_get_flags (MonoEvent *event)
9804 return event->attrs;
9808 * mono_class_get_method_from_name:
9809 * @klass: where to look for the method
9810 * @name: name of the method
9811 * @param_count: number of parameters. -1 for any number.
9813 * Obtains a MonoMethod with a given name and number of parameters.
9814 * It only works if there are no multiple signatures for any given method name.
9817 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9819 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9823 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9825 MonoMethod *res = NULL;
9828 /* Search directly in the metadata to avoid calling setup_methods () */
9829 for (i = 0; i < klass->method.count; ++i) {
9831 guint32 cols [MONO_METHOD_SIZE];
9833 MonoMethodSignature *sig;
9835 /* klass->method.first points into the methodptr table */
9836 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9838 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9839 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9841 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9844 if (param_count == -1) {
9848 sig = mono_method_signature_checked (method, &error);
9850 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9853 if (sig->param_count == param_count) {
9864 * mono_class_get_method_from_name_flags:
9865 * @klass: where to look for the method
9866 * @name_space: name of the method
9867 * @param_count: number of parameters. -1 for any number.
9868 * @flags: flags which must be set in the method
9870 * Obtains a MonoMethod with a given name and number of parameters.
9871 * It only works if there are no multiple signatures for any given method name.
9874 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9876 MonoMethod *res = NULL;
9879 mono_class_init (klass);
9881 if (klass->generic_class && !klass->methods) {
9882 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9885 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9886 if (!mono_error_ok (&error))
9887 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9892 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9893 mono_class_setup_methods (klass);
9895 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9896 See mono/tests/array_load_exception.il
9897 FIXME we should better report this error to the caller
9899 if (!klass->methods)
9901 for (i = 0; i < klass->method.count; ++i) {
9902 MonoMethod *method = klass->methods [i];
9904 if (method->name[0] == name [0] &&
9905 !strcmp (name, method->name) &&
9906 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9907 ((method->flags & flags) == flags)) {
9914 res = find_method_in_metadata (klass, name, param_count, flags);
9921 * mono_class_set_failure:
9922 * @klass: class in which the failure was detected
9923 * @ex_type: the kind of exception/error to be thrown (later)
9924 * @ex_data: exception data (specific to each type of exception/error)
9926 * Keep a detected failure informations in the class for later processing.
9927 * Note that only the first failure is kept.
9929 * LOCKING: Acquires the loader lock.
9932 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9934 if (mono_class_has_failure (klass))
9937 mono_loader_lock ();
9938 klass->exception_type = ex_type;
9940 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9941 mono_loader_unlock ();
9947 * mono_class_get_exception_data:
9949 * Return the exception_data property of KLASS.
9951 * LOCKING: Acquires the loader lock.
9954 mono_class_get_exception_data (MonoClass *klass)
9956 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9960 * mono_classes_init:
9962 * Initialize the resources used by this module.
9965 mono_classes_init (void)
9967 mono_os_mutex_init (&classes_mutex);
9969 mono_counters_register ("Inflated methods size",
9970 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9971 mono_counters_register ("Inflated classes",
9972 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9973 mono_counters_register ("Inflated classes size",
9974 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9975 mono_counters_register ("MonoClass size",
9976 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9977 mono_counters_register ("MonoClassExt size",
9978 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9982 * mono_classes_cleanup:
9984 * Free the resources used by this module.
9987 mono_classes_cleanup (void)
9989 if (global_interface_bitset)
9990 mono_bitset_free (global_interface_bitset);
9991 global_interface_bitset = NULL;
9992 mono_os_mutex_destroy (&classes_mutex);
9996 * mono_class_get_exception_for_failure:
9997 * @klass: class in which the failure was detected
9999 * Return a constructed MonoException than the caller can then throw
10000 * using mono_raise_exception - or NULL if no failure is present (or
10001 * doesn't result in an exception).
10004 mono_class_get_exception_for_failure (MonoClass *klass)
10006 gpointer exception_data = mono_class_get_exception_data (klass);
10008 switch (mono_class_get_failure(klass)) {
10009 case MONO_EXCEPTION_TYPE_LOAD: {
10012 char *str = mono_type_get_full_name (klass);
10013 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
10014 name = mono_string_new (mono_domain_get (), str);
10016 ex = mono_get_exception_type_load (name, astr);
10020 case MONO_EXCEPTION_MISSING_METHOD: {
10021 char *class_name = (char *)exception_data;
10022 char *assembly_name = class_name + strlen (class_name) + 1;
10024 return mono_get_exception_missing_method (class_name, assembly_name);
10026 case MONO_EXCEPTION_MISSING_FIELD: {
10027 char *class_name = (char *)exception_data;
10028 char *member_name = class_name + strlen (class_name) + 1;
10030 return mono_get_exception_missing_field (class_name, member_name);
10032 case MONO_EXCEPTION_FILE_NOT_FOUND: {
10033 char *msg_format = (char *)exception_data;
10034 char *assembly_name = msg_format + strlen (msg_format) + 1;
10035 char *msg = g_strdup_printf (msg_format, assembly_name);
10038 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10044 case MONO_EXCEPTION_BAD_IMAGE: {
10045 return mono_get_exception_bad_image_format ((const char *)exception_data);
10047 case MONO_EXCEPTION_INVALID_PROGRAM: {
10048 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10051 /* TODO - handle other class related failures */
10052 return mono_get_exception_execution_engine ("Unknown class failure");
10058 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10060 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10061 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10063 if (outer_klass == inner_klass)
10065 inner_klass = inner_klass->nested_in;
10066 } while (inner_klass);
10071 mono_class_get_generic_type_definition (MonoClass *klass)
10073 return klass->generic_class ? klass->generic_class->container_class : klass;
10077 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10079 * Generic instantiations are ignored for all super types of @klass.
10081 * Visibility checks ignoring generic instantiations.
10084 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10087 klass = mono_class_get_generic_type_definition (klass);
10088 parent = mono_class_get_generic_type_definition (parent);
10089 mono_class_setup_supertypes (klass);
10091 for (i = 0; i < klass->idepth; ++i) {
10092 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10098 * Subtype can only access parent members with family protection if the site object
10099 * is subclass of Subtype. For example:
10100 * class A { protected int x; }
10102 * void valid_access () {
10106 * void invalid_access () {
10113 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10115 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10118 if (context_klass == NULL)
10120 /*if access_klass is not member_klass context_klass must be type compat*/
10121 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10127 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10130 if (accessing == accessed)
10132 if (!accessed || !accessing)
10135 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10136 * anywhere so untrusted friends are not safe to access platform's code internals */
10137 if (mono_security_core_clr_enabled ()) {
10138 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10142 mono_assembly_load_friends (accessed);
10143 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10144 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10145 /* Be conservative with checks */
10146 if (!friend_->name)
10148 if (strcmp (accessing->aname.name, friend_->name))
10150 if (friend_->public_key_token [0]) {
10151 if (!accessing->aname.public_key_token [0])
10153 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10162 * If klass is a generic type or if it is derived from a generic type, return the
10163 * MonoClass of the generic definition
10164 * Returns NULL if not found
10167 get_generic_definition_class (MonoClass *klass)
10170 if (klass->generic_class && klass->generic_class->container_class)
10171 return klass->generic_class->container_class;
10172 klass = klass->parent;
10178 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10181 for (i = 0; i < ginst->type_argc; ++i) {
10182 MonoType *type = ginst->type_argv[i];
10183 switch (type->type) {
10184 case MONO_TYPE_SZARRAY:
10185 if (!can_access_type (access_klass, type->data.klass))
10188 case MONO_TYPE_ARRAY:
10189 if (!can_access_type (access_klass, type->data.array->eklass))
10192 case MONO_TYPE_PTR:
10193 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10196 case MONO_TYPE_CLASS:
10197 case MONO_TYPE_VALUETYPE:
10198 case MONO_TYPE_GENERICINST:
10199 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10209 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10213 if (access_klass == member_klass)
10216 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10219 if (access_klass->element_class && !access_klass->enumtype)
10220 access_klass = access_klass->element_class;
10222 if (member_klass->element_class && !member_klass->enumtype)
10223 member_klass = member_klass->element_class;
10225 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10227 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10230 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10233 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10236 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10239 /*Non nested type with nested visibility. We just fail it.*/
10240 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10243 switch (access_level) {
10244 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10245 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10247 case TYPE_ATTRIBUTE_PUBLIC:
10250 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10253 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10254 return is_nesting_type (member_klass, access_klass);
10256 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10257 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10259 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10260 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10262 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10263 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10264 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10266 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10267 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10268 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10273 /* FIXME: check visibility of type, too */
10275 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10277 MonoClass *member_generic_def;
10278 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10281 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10282 access_klass->generic_container) &&
10283 (member_generic_def = get_generic_definition_class (member_klass))) {
10284 MonoClass *access_container;
10286 if (access_klass->generic_container)
10287 access_container = access_klass;
10289 access_container = access_klass->generic_class->container_class;
10291 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10295 /* Partition I 8.5.3.2 */
10296 /* the access level values are the same for fields and methods */
10297 switch (access_level) {
10298 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10299 /* same compilation unit */
10300 return access_klass->image == member_klass->image;
10301 case FIELD_ATTRIBUTE_PRIVATE:
10302 return access_klass == member_klass;
10303 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10304 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10305 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10308 case FIELD_ATTRIBUTE_ASSEMBLY:
10309 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10310 case FIELD_ATTRIBUTE_FAMILY:
10311 if (is_valid_family_access (access_klass, member_klass, context_klass))
10314 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10315 if (is_valid_family_access (access_klass, member_klass, context_klass))
10317 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10318 case FIELD_ATTRIBUTE_PUBLIC:
10325 * mono_method_can_access_field:
10326 * @method: Method that will attempt to access the field
10327 * @field: the field to access
10329 * Used to determine if a method is allowed to access the specified field.
10331 * Returns: TRUE if the given @method is allowed to access the @field while following
10332 * the accessibility rules of the CLI.
10335 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10337 /* FIXME: check all overlapping fields */
10338 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10340 MonoClass *nested = method->klass->nested_in;
10342 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10345 nested = nested->nested_in;
10352 * mono_method_can_access_method:
10353 * @method: Method that will attempt to access the other method
10354 * @called: the method that we want to probe for accessibility.
10356 * Used to determine if the @method is allowed to access the specified @called method.
10358 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10359 * the accessibility rules of the CLI.
10362 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10364 method = mono_method_get_method_definition (method);
10365 called = mono_method_get_method_definition (called);
10366 return mono_method_can_access_method_full (method, called, NULL);
10370 * mono_method_can_access_method_full:
10371 * @method: The caller method
10372 * @called: The called method
10373 * @context_klass: The static type on stack of the owner @called object used
10375 * This function must be used with instance calls, as they have more strict family accessibility.
10376 * It can be used with static methods, but context_klass should be NULL.
10378 * Returns: TRUE if caller have proper visibility and acessibility to @called
10381 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10383 /* Wrappers are except from access checks */
10384 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10387 MonoClass *access_class = method->klass;
10388 MonoClass *member_class = called->klass;
10389 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10391 MonoClass *nested = access_class->nested_in;
10393 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10396 nested = nested->nested_in;
10403 can = can_access_type (access_class, member_class);
10405 MonoClass *nested = access_class->nested_in;
10407 can = can_access_type (nested, member_class);
10410 nested = nested->nested_in;
10417 if (called->is_inflated) {
10418 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10419 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10428 * mono_method_can_access_field_full:
10429 * @method: The caller method
10430 * @field: The accessed field
10431 * @context_klass: The static type on stack of the owner @field object used
10433 * This function must be used with instance fields, as they have more strict family accessibility.
10434 * It can be used with static fields, but context_klass should be NULL.
10436 * Returns: TRUE if caller have proper visibility and acessibility to @field
10439 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10441 MonoClass *access_class = method->klass;
10442 MonoClass *member_class = field->parent;
10443 /* FIXME: check all overlapping fields */
10444 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10446 MonoClass *nested = access_class->nested_in;
10448 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10451 nested = nested->nested_in;
10458 can = can_access_type (access_class, member_class);
10460 MonoClass *nested = access_class->nested_in;
10462 can = can_access_type (nested, member_class);
10465 nested = nested->nested_in;
10475 * mono_class_can_access_class:
10476 * @source_class: The source class
10477 * @target_class: The accessed class
10479 * This function returns is @target_class is visible to @source_class
10481 * Returns: TRUE if source have proper visibility and acessibility to target
10484 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10486 return can_access_type (source_class, target_class);
10490 * mono_type_is_valid_enum_basetype:
10491 * @type: The MonoType to check
10493 * Returns: TRUE if the type can be used as the basetype of an enum
10495 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10496 switch (type->type) {
10499 case MONO_TYPE_BOOLEAN:
10502 case MONO_TYPE_CHAR:
10516 * mono_class_is_valid_enum:
10517 * @klass: An enum class to be validated
10519 * This method verify the required properties an enum should have.
10521 * Returns: TRUE if the informed enum class is valid
10523 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10524 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10525 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10527 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10528 MonoClassField * field;
10529 gpointer iter = NULL;
10530 gboolean found_base_field = FALSE;
10532 g_assert (klass->enumtype);
10533 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10534 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10538 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10541 while ((field = mono_class_get_fields (klass, &iter))) {
10542 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10543 if (found_base_field)
10545 found_base_field = TRUE;
10546 if (!mono_type_is_valid_enum_basetype (field->type))
10551 if (!found_base_field)
10554 if (klass->method.count > 0)
10561 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10563 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10567 * mono_class_setup_interface_id:
10569 * Initializes MonoClass::interface_id if required.
10571 * LOCKING: Acquires the loader lock.
10574 mono_class_setup_interface_id (MonoClass *klass)
10576 mono_loader_lock ();
10577 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10578 klass->interface_id = mono_get_unique_iid (klass);
10579 mono_loader_unlock ();
10583 * mono_class_alloc_ext:
10585 * Allocate klass->ext if not already done.
10588 mono_class_alloc_ext (MonoClass *klass)
10595 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10596 mono_image_lock (klass->image);
10597 mono_memory_barrier ();
10600 class_ext_size += sizeof (MonoClassExt);
10601 mono_image_unlock (klass->image);
10605 * mono_class_setup_interfaces:
10607 * Initialize klass->interfaces/interfaces_count.
10608 * LOCKING: Acquires the loader lock.
10609 * This function can fail the type.
10612 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10614 int i, interface_count;
10615 MonoClass **interfaces;
10617 mono_error_init (error);
10619 if (klass->interfaces_inited)
10622 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10623 MonoType *args [1];
10625 /* generic IList, ICollection, IEnumerable */
10626 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10627 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10629 args [0] = &klass->element_class->byval_arg;
10630 interfaces [0] = mono_class_bind_generic_parameters (
10631 mono_defaults.generic_ilist_class, 1, args, FALSE);
10632 if (interface_count > 1)
10633 interfaces [1] = mono_class_bind_generic_parameters (
10634 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10635 } else if (klass->generic_class) {
10636 MonoClass *gklass = klass->generic_class->container_class;
10638 mono_class_setup_interfaces (gklass, error);
10639 if (!mono_error_ok (error)) {
10640 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10644 interface_count = gklass->interface_count;
10645 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10646 for (i = 0; i < interface_count; i++) {
10647 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10648 if (!mono_error_ok (error)) {
10649 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10654 interface_count = 0;
10658 mono_image_lock (klass->image);
10660 if (!klass->interfaces_inited) {
10661 klass->interface_count = interface_count;
10662 klass->interfaces = interfaces;
10664 mono_memory_barrier ();
10666 klass->interfaces_inited = TRUE;
10669 mono_image_unlock (klass->image);
10673 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10675 MonoClass *klass = field->parent;
10676 MonoImage *image = klass->image;
10677 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10678 int field_idx = field - klass->fields;
10680 mono_error_init (error);
10683 MonoClassField *gfield = >d->fields [field_idx];
10684 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10685 if (!mono_error_ok (error)) {
10686 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10687 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10690 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10691 if (!mono_error_ok (error)) {
10692 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10693 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10697 guint32 cols [MONO_FIELD_SIZE];
10698 MonoGenericContainer *container = NULL;
10699 int idx = klass->field.first + field_idx;
10701 /*FIXME, in theory we do not lazy load SRE fields*/
10702 g_assert (!image_is_dynamic (image));
10704 if (klass->generic_container) {
10705 container = klass->generic_container;
10707 container = gtd->generic_container;
10708 g_assert (container);
10711 /* klass->field.first and idx points into the fieldptr table */
10712 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10714 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10715 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10716 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10720 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10722 mono_metadata_decode_value (sig, &sig);
10723 /* FIELD signature == 0x06 */
10724 g_assert (*sig == 0x06);
10726 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10727 if (!field->type) {
10728 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10729 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10735 mono_field_resolve_flags (MonoClassField *field)
10737 MonoClass *klass = field->parent;
10738 MonoImage *image = klass->image;
10739 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10740 int field_idx = field - klass->fields;
10744 MonoClassField *gfield = >d->fields [field_idx];
10745 return mono_field_get_flags (gfield);
10747 int idx = klass->field.first + field_idx;
10749 /*FIXME, in theory we do not lazy load SRE fields*/
10750 g_assert (!image_is_dynamic (image));
10752 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10757 * mono_class_setup_basic_field_info:
10758 * @class: The class to initialize
10760 * Initializes the klass->fields array of fields.
10761 * Aquires the loader lock.
10764 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10766 mono_loader_lock ();
10767 mono_class_setup_basic_field_info (klass);
10768 mono_loader_unlock ();
10772 * mono_class_get_fields_lazy:
10773 * @klass: the MonoClass to act on
10775 * This routine is an iterator routine for retrieving the fields in a class.
10776 * Only minimal information about fields are loaded. Accessors must be used
10777 * for all MonoClassField returned.
10779 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10780 * iterate over all of the elements. When no more values are
10781 * available, the return value is NULL.
10783 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10786 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10788 MonoClassField* field;
10792 mono_class_setup_basic_field_info_locking (klass);
10793 if (!klass->fields)
10795 /* start from the first */
10796 if (klass->field.count) {
10797 *iter = &klass->fields [0];
10798 return (MonoClassField *)*iter;
10804 field = (MonoClassField *)*iter;
10806 if (field < &klass->fields [klass->field.count]) {
10808 return (MonoClassField *)*iter;
10814 mono_class_full_name (MonoClass *klass)
10816 return mono_type_full_name (&klass->byval_arg);
10819 /* Declare all shared lazy type lookup functions */
10820 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)