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);
5598 klass->parent = parent;
5600 if (parent->generic_class && !parent->name) {
5602 * If the parent is a generic instance, we may get
5603 * called before it is fully initialized, especially
5604 * before it has its name.
5609 #ifndef DISABLE_REMOTING
5610 klass->marshalbyref = parent->marshalbyref;
5611 klass->contextbound = parent->contextbound;
5614 klass->delegate = parent->delegate;
5616 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5617 mono_class_set_is_com_object (klass);
5619 if (system_namespace) {
5620 #ifndef DISABLE_REMOTING
5621 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5622 klass->marshalbyref = 1;
5624 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5625 klass->contextbound = 1;
5627 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5628 klass->delegate = 1;
5631 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5632 (strcmp (klass->parent->name_space, "System") == 0)))
5633 klass->valuetype = 1;
5634 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5635 klass->valuetype = klass->enumtype = 1;
5637 /*klass->enumtype = klass->parent->enumtype; */
5639 /* initialize com types if COM interfaces are present */
5641 if (MONO_CLASS_IS_IMPORT (klass))
5642 init_com_from_comimport (klass);
5644 klass->parent = NULL;
5650 * mono_class_setup_supertypes:
5653 * Build the data structure needed to make fast type checks work.
5654 * This currently sets two fields in @class:
5655 * - idepth: distance between @class and System.Object in the type
5657 * - supertypes: array of classes: each element has a class in the hierarchy
5658 * starting from @class up to System.Object
5660 * LOCKING: This function is atomic, in case of contention we waste memory.
5663 mono_class_setup_supertypes (MonoClass *klass)
5666 MonoClass **supertypes;
5668 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5672 if (klass->parent && !klass->parent->supertypes)
5673 mono_class_setup_supertypes (klass->parent);
5675 klass->idepth = klass->parent->idepth + 1;
5679 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5680 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5682 if (klass->parent) {
5683 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5686 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5687 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5689 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5692 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5696 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5698 MonoClass *gtd = (MonoClass*)user_data;
5699 /* Only try to fix generic instances of @gtd */
5700 if (gclass->generic_class->container_class != gtd)
5703 /* Check if the generic instance has no parent. */
5704 if (gtd->parent && !gclass->parent)
5705 mono_generic_class_setup_parent (gclass, gtd);
5711 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5713 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5714 mono_error_set_type_load_class (error, klass, msg);
5718 * mono_class_create_from_typedef:
5719 * @image: image where the token is valid
5720 * @type_token: typedef token
5721 * @error: used to return any error found while creating the type
5723 * Create the MonoClass* representing the specified type token.
5724 * @type_token must be a TypeDef token.
5726 * FIXME: don't return NULL on failure, just the the caller figure it out.
5729 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5731 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5732 MonoClass *klass, *parent = NULL;
5733 guint32 cols [MONO_TYPEDEF_SIZE];
5734 guint32 cols_next [MONO_TYPEDEF_SIZE];
5735 guint tidx = mono_metadata_token_index (type_token);
5736 MonoGenericContext *context = NULL;
5737 const char *name, *nspace;
5739 MonoClass **interfaces;
5740 guint32 field_last, method_last;
5741 guint32 nesting_tokeen;
5743 mono_error_init (error);
5745 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5746 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5750 mono_loader_lock ();
5752 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5753 mono_loader_unlock ();
5757 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5759 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5760 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5762 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5765 klass->name_space = nspace;
5767 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5769 klass->image = image;
5770 klass->type_token = type_token;
5771 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5773 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5775 classes_size += sizeof (MonoClass);
5778 * Check whether we're a generic type definition.
5780 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5781 if (klass->generic_container) {
5782 klass->is_generic = 1;
5783 klass->generic_container->owner.klass = klass;
5784 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5785 context = &klass->generic_container->context;
5788 if (klass->generic_container)
5789 enable_gclass_recording ();
5791 if (cols [MONO_TYPEDEF_EXTENDS]) {
5793 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5795 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5796 /*WARNING: this must satisfy mono_metadata_type_hash*/
5797 klass->this_arg.byref = 1;
5798 klass->this_arg.data.klass = klass;
5799 klass->this_arg.type = MONO_TYPE_CLASS;
5800 klass->byval_arg.data.klass = klass;
5801 klass->byval_arg.type = MONO_TYPE_CLASS;
5803 parent = mono_class_get_checked (image, parent_token, error);
5804 if (parent && context) /* Always inflate */
5805 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5807 if (parent == NULL) {
5808 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5809 goto parent_failure;
5812 for (tmp = parent; tmp; tmp = tmp->parent) {
5814 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5815 goto parent_failure;
5817 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5818 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5819 goto parent_failure;
5824 mono_class_setup_parent (klass, parent);
5826 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5827 mono_class_setup_mono_type (klass);
5829 if (klass->generic_container)
5830 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5833 * This might access klass->byval_arg for recursion generated by generic constraints,
5834 * so it has to come after setup_mono_type ().
5836 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5837 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5838 if (!mono_error_ok (error)) {
5839 /*FIXME implement a mono_class_set_failure_from_mono_error */
5840 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5841 mono_loader_unlock ();
5842 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5847 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5851 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5855 klass->cast_class = klass->element_class = klass;
5857 if (!klass->enumtype) {
5858 if (!mono_metadata_interfaces_from_typedef_full (
5859 image, type_token, &interfaces, &icount, FALSE, context, error)){
5861 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5862 mono_loader_unlock ();
5863 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5867 klass->interfaces = interfaces;
5868 klass->interface_count = icount;
5869 klass->interfaces_inited = 1;
5872 /*g_print ("Load class %s\n", name);*/
5875 * Compute the field and method lists
5877 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5878 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5880 if (tt->rows > tidx){
5881 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5882 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5883 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5885 field_last = image->tables [MONO_TABLE_FIELD].rows;
5886 method_last = image->tables [MONO_TABLE_METHOD].rows;
5889 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5890 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5891 klass->field.count = field_last - klass->field.first;
5893 klass->field.count = 0;
5895 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5896 klass->method.count = method_last - klass->method.first;
5898 klass->method.count = 0;
5900 /* reserve space to store vector pointer in arrays */
5901 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5902 klass->instance_size += 2 * sizeof (gpointer);
5903 g_assert (klass->field.count == 0);
5906 if (klass->enumtype) {
5907 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5908 if (!enum_basetype) {
5909 /*set it to a default value as the whole runtime can't handle this to be null*/
5910 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5911 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5912 mono_loader_unlock ();
5913 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5916 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5920 * If we're a generic type definition, load the constraints.
5921 * We must do this after the class has been constructed to make certain recursive scenarios
5924 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5925 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)));
5926 mono_loader_unlock ();
5927 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5931 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5932 if (!strncmp (name, "Vector", 6))
5933 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");
5936 mono_loader_unlock ();
5938 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5943 mono_class_setup_mono_type (klass);
5944 mono_loader_unlock ();
5945 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5949 /** Is klass a Nullable<T> ginst? */
5951 mono_class_is_nullable (MonoClass *klass)
5953 return klass->generic_class != NULL &&
5954 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5958 /** if klass is T? return T */
5960 mono_class_get_nullable_param (MonoClass *klass)
5962 g_assert (mono_class_is_nullable (klass));
5963 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5967 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5971 MonoGenericClass *gclass = klass->generic_class;
5973 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5974 if (!mono_error_ok (&error)) {
5975 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5976 klass->parent = mono_defaults.object_class;
5977 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5978 mono_error_cleanup (&error);
5982 mono_class_setup_parent (klass, klass->parent);
5984 if (klass->enumtype) {
5985 klass->cast_class = gtd->cast_class;
5986 klass->element_class = gtd->element_class;
5992 * Create the `MonoClass' for an instantiation of a generic type.
5993 * We only do this if we actually need it.
5996 mono_generic_class_get_class (MonoGenericClass *gclass)
5998 MonoClass *klass, *gklass;
6000 if (gclass->cached_class)
6001 return gclass->cached_class;
6003 mono_loader_lock ();
6004 if (gclass->cached_class) {
6005 mono_loader_unlock ();
6006 return gclass->cached_class;
6009 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6011 gklass = gclass->container_class;
6013 if (record_gclass_instantiation > 0)
6014 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6016 if (gklass->nested_in) {
6017 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6018 klass->nested_in = gklass->nested_in;
6021 klass->name = gklass->name;
6022 klass->name_space = gklass->name_space;
6024 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6026 klass->image = gklass->image;
6027 klass->flags = gklass->flags;
6028 klass->type_token = gklass->type_token;
6029 klass->field.count = gklass->field.count;
6031 klass->is_inflated = 1;
6032 klass->generic_class = gclass;
6034 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6035 klass->this_arg.type = klass->byval_arg.type;
6036 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6037 klass->this_arg.byref = TRUE;
6038 klass->enumtype = gklass->enumtype;
6039 klass->valuetype = gklass->valuetype;
6041 klass->cast_class = klass->element_class = klass;
6043 if (mono_class_is_nullable (klass))
6044 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6047 * We're not interested in the nested classes of a generic instance.
6048 * We use the generic type definition to look for nested classes.
6051 mono_generic_class_setup_parent (klass, gklass);
6053 if (gclass->is_dynamic) {
6055 * 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.
6056 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6057 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6059 if (!gklass->wastypebuilder)
6062 mono_class_setup_supertypes (klass);
6064 if (klass->enumtype) {
6066 * For enums, gklass->fields might not been set, but instance_size etc. is
6067 * already set in mono_reflection_create_internal_class (). For non-enums,
6068 * these will be computed normally in mono_class_layout_fields ().
6070 klass->instance_size = gklass->instance_size;
6071 klass->sizes.class_size = gklass->sizes.class_size;
6072 mono_memory_barrier ();
6073 klass->size_inited = 1;
6077 mono_memory_barrier ();
6078 gclass->cached_class = klass;
6080 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6082 inflated_classes ++;
6083 inflated_classes_size += sizeof (MonoClass);
6085 mono_loader_unlock ();
6091 get_image_for_container (MonoGenericContainer *container)
6094 if (container->is_anonymous) {
6095 result = container->owner.image;
6098 if (container->is_method) {
6099 MonoMethod *method = container->owner.method;
6100 g_assert_checked (method);
6101 klass = method->klass;
6103 klass = container->owner.klass;
6105 g_assert_checked (klass);
6106 result = klass->image;
6113 get_image_for_generic_param (MonoGenericParam *param)
6115 MonoGenericContainer *container = mono_generic_param_owner (param);
6116 g_assert_checked (container);
6117 return get_image_for_container (container);
6120 // Make a string in the designated image consisting of a single integer.
6121 #define INT_STRING_SIZE 16
6123 make_generic_name_string (MonoImage *image, int num)
6125 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6126 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6130 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6131 // pinfo is derived from param by the caller for us.
6133 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6135 MonoClass *klass, **ptr;
6137 MonoGenericContainer *container = mono_generic_param_owner (param);
6138 g_assert_checked (container);
6140 MonoImage *image = get_image_for_container (container);
6141 gboolean is_mvar = container->is_method;
6142 gboolean is_anonymous = container->is_anonymous;
6144 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6145 classes_size += sizeof (MonoClass);
6148 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6150 int n = mono_generic_param_num (param);
6151 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6155 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6156 } else if (is_mvar) {
6157 MonoMethod *omethod = container->owner.method;
6158 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6160 MonoClass *oklass = container->owner.klass;
6161 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6164 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6166 // Count non-NULL items in pinfo->constraints
6169 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6173 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6174 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6176 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6177 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6179 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6182 if (count - pos > 0) {
6183 klass->interface_count = count - pos;
6184 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6185 klass->interfaces_inited = TRUE;
6186 for (i = pos; i < count; i++)
6187 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6190 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6192 klass->inited = TRUE;
6193 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6194 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6195 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6197 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6198 klass->this_arg.type = klass->byval_arg.type;
6199 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6200 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6201 klass->this_arg.byref = TRUE;
6203 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6204 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6206 /*Init these fields to sane values*/
6207 klass->min_align = 1;
6209 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6210 * constrained to, the JIT depends on this.
6212 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6213 mono_memory_barrier ();
6214 klass->size_inited = 1;
6215 klass->setup_fields_called = 1;
6217 mono_class_setup_supertypes (klass);
6219 if (count - pos > 0) {
6220 mono_class_setup_vtable (klass->parent);
6221 if (mono_class_has_failure (klass->parent))
6222 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6224 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6230 #define FAST_CACHE_SIZE 16
6233 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6234 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6235 * we cache the MonoClasses.
6236 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6237 * LOCKING: Takes the image lock depending on @take_lock.
6240 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6242 int n = mono_generic_param_num (param);
6243 MonoImage *image = get_image_for_generic_param (param);
6244 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6245 MonoClass *klass = NULL;
6250 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6251 // For high numbers or constraints we have to use pointer hashes.
6252 if (param->gshared_constraint) {
6253 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6256 mono_image_lock (image);
6257 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6259 mono_image_unlock (image);
6264 if (n < FAST_CACHE_SIZE) {
6266 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6268 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6270 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6273 mono_image_lock (image);
6274 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6276 mono_image_unlock (image);
6283 * LOCKING: Image lock (param->image) must be held
6286 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6288 int n = mono_generic_param_num (param);
6289 MonoImage *image = get_image_for_generic_param (param);
6290 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6294 if (param->gshared_constraint) {
6295 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6297 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6298 mono_memory_barrier ();
6300 image->mvar_cache_constrained = ht;
6302 image->var_cache_constrained = ht;
6304 g_hash_table_insert (ht, param, klass);
6305 } else if (n < FAST_CACHE_SIZE) {
6307 /* Requires locking to avoid droping an already published class */
6308 if (!image->mvar_cache_fast)
6309 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6310 image->mvar_cache_fast [n] = klass;
6312 if (!image->var_cache_fast)
6313 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6314 image->var_cache_fast [n] = klass;
6317 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6319 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6321 ht = g_hash_table_new (NULL, NULL);
6322 mono_memory_barrier ();
6324 image->mvar_cache_slow = ht;
6326 image->var_cache_slow = ht;
6329 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6334 * LOCKING: Acquires the image lock (@image).
6337 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6339 MonoImage *image = get_image_for_generic_param (param);
6340 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6341 MonoClass *klass, *klass2;
6343 // If a klass already exists for this object and is cached, return it.
6344 if (pinfo) // Non-anonymous
6345 klass = pinfo->pklass;
6347 klass = get_anon_gparam_class (param, TRUE);
6352 // Create a new klass
6353 klass = make_generic_param_class (param, pinfo);
6355 // Now we need to cache the klass we created.
6356 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6357 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6358 // and allow our newly-created klass object to just leak.
6359 mono_memory_barrier ();
6361 mono_image_lock (image);
6363 // Here "klass2" refers to the klass potentially created by the other thread.
6364 if (pinfo) // Repeat check from above
6365 klass2 = pinfo->pklass;
6367 klass2 = get_anon_gparam_class (param, FALSE);
6374 pinfo->pklass = klass;
6376 set_anon_gparam_class (param, klass);
6378 mono_image_unlock (image);
6380 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6382 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6384 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6390 * mono_class_from_generic_parameter:
6391 * @param: Parameter to find/construct a class for.
6392 * @arg2: Is ignored.
6393 * @arg3: Is ignored.
6396 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6398 return mono_class_from_generic_parameter_internal (param);
6403 mono_ptr_class_get (MonoType *type)
6406 MonoClass *el_class;
6410 el_class = mono_class_from_mono_type (type);
6411 image = el_class->image;
6413 mono_image_lock (image);
6414 if (image->ptr_cache) {
6415 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6416 mono_image_unlock (image);
6420 mono_image_unlock (image);
6422 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6424 classes_size += sizeof (MonoClass);
6426 result->parent = NULL; /* no parent for PTR types */
6427 result->name_space = el_class->name_space;
6428 name = g_strdup_printf ("%s*", el_class->name);
6429 result->name = mono_image_strdup (image, name);
6432 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6434 result->image = el_class->image;
6435 result->inited = TRUE;
6436 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6437 /* Can pointers get boxed? */
6438 result->instance_size = sizeof (gpointer);
6439 result->cast_class = result->element_class = el_class;
6440 result->blittable = TRUE;
6442 result->byval_arg.type = MONO_TYPE_PTR;
6443 result->this_arg.type = result->byval_arg.type;
6444 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6445 result->this_arg.byref = TRUE;
6447 mono_class_setup_supertypes (result);
6449 mono_image_lock (image);
6450 if (image->ptr_cache) {
6452 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6453 mono_image_unlock (image);
6454 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6458 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6460 g_hash_table_insert (image->ptr_cache, el_class, result);
6461 mono_image_unlock (image);
6463 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6469 mono_fnptr_class_get (MonoMethodSignature *sig)
6472 static GHashTable *ptr_hash = NULL;
6474 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6476 mono_loader_lock ();
6479 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6481 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6482 mono_loader_unlock ();
6485 result = g_new0 (MonoClass, 1);
6487 result->parent = NULL; /* no parent for PTR types */
6488 result->name_space = "System";
6489 result->name = "MonoFNPtrFakeClass";
6491 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6493 result->image = mono_defaults.corlib; /* need to fix... */
6494 result->inited = TRUE;
6495 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6496 /* Can pointers get boxed? */
6497 result->instance_size = sizeof (gpointer);
6498 result->cast_class = result->element_class = result;
6499 result->blittable = TRUE;
6501 result->byval_arg.type = MONO_TYPE_FNPTR;
6502 result->this_arg.type = result->byval_arg.type;
6503 result->this_arg.data.method = result->byval_arg.data.method = sig;
6504 result->this_arg.byref = TRUE;
6505 result->blittable = TRUE;
6507 mono_class_setup_supertypes (result);
6509 g_hash_table_insert (ptr_hash, sig, result);
6511 mono_loader_unlock ();
6513 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6519 * mono_class_from_mono_type:
6520 * @type: describes the type to return
6522 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6525 mono_class_from_mono_type (MonoType *type)
6527 switch (type->type) {
6528 case MONO_TYPE_OBJECT:
6529 return type->data.klass? type->data.klass: mono_defaults.object_class;
6530 case MONO_TYPE_VOID:
6531 return type->data.klass? type->data.klass: mono_defaults.void_class;
6532 case MONO_TYPE_BOOLEAN:
6533 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6534 case MONO_TYPE_CHAR:
6535 return type->data.klass? type->data.klass: mono_defaults.char_class;
6537 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6539 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6541 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6543 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6545 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6547 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6549 return type->data.klass? type->data.klass: mono_defaults.int_class;
6551 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6553 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6555 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6557 return type->data.klass? type->data.klass: mono_defaults.single_class;
6559 return type->data.klass? type->data.klass: mono_defaults.double_class;
6560 case MONO_TYPE_STRING:
6561 return type->data.klass? type->data.klass: mono_defaults.string_class;
6562 case MONO_TYPE_TYPEDBYREF:
6563 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6564 case MONO_TYPE_ARRAY:
6565 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6567 return mono_ptr_class_get (type->data.type);
6568 case MONO_TYPE_FNPTR:
6569 return mono_fnptr_class_get (type->data.method);
6570 case MONO_TYPE_SZARRAY:
6571 return mono_array_class_get (type->data.klass, 1);
6572 case MONO_TYPE_CLASS:
6573 case MONO_TYPE_VALUETYPE:
6574 return type->data.klass;
6575 case MONO_TYPE_GENERICINST:
6576 return mono_generic_class_get_class (type->data.generic_class);
6577 case MONO_TYPE_MVAR:
6579 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6581 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6582 g_assert_not_reached ();
6585 // Yes, this returns NULL, even if it is documented as not doing so, but there
6586 // is no way for the code to make it this far, due to the assert above.
6591 * mono_type_retrieve_from_typespec
6592 * @image: context where the image is created
6593 * @type_spec: typespec token
6594 * @context: the generic context used to evaluate generic instantiations in
6597 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6599 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6601 *did_inflate = FALSE;
6606 if (context && (context->class_inst || context->method_inst)) {
6607 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6609 if (!mono_error_ok (error)) {
6615 *did_inflate = TRUE;
6622 * mono_class_create_from_typespec
6623 * @image: context where the image is created
6624 * @type_spec: typespec token
6625 * @context: the generic context used to evaluate generic instantiations in
6628 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6631 gboolean inflated = FALSE;
6632 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6633 return_val_if_nok (error, NULL);
6634 ret = mono_class_from_mono_type (t);
6636 mono_metadata_free_type (t);
6641 * mono_bounded_array_class_get:
6642 * @element_class: element class
6643 * @rank: the dimension of the array class
6644 * @bounded: whenever the array has non-zero bounds
6646 * Returns: A class object describing the array with element type @element_type and
6650 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6654 MonoClass *parent = NULL;
6655 GSList *list, *rootlist = NULL;
6658 gboolean corlib_type = FALSE;
6660 g_assert (rank <= 255);
6663 /* bounded only matters for one-dimensional arrays */
6666 image = eclass->image;
6668 if (rank == 1 && !bounded) {
6670 * This case is very frequent not just during compilation because of calls
6671 * from mono_class_from_mono_type (), mono_array_new (),
6672 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6674 mono_os_mutex_lock (&image->szarray_cache_lock);
6675 if (!image->szarray_cache)
6676 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6677 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6678 mono_os_mutex_unlock (&image->szarray_cache_lock);
6682 mono_loader_lock ();
6684 mono_loader_lock ();
6686 if (!image->array_cache)
6687 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6689 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6690 for (; list; list = list->next) {
6691 klass = (MonoClass *)list->data;
6692 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6693 mono_loader_unlock ();
6700 /* for the building corlib use System.Array from it */
6701 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6702 parent = mono_class_load_from_name (image, "System", "Array");
6705 parent = mono_defaults.array_class;
6706 if (!parent->inited)
6707 mono_class_init (parent);
6710 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6712 klass->image = image;
6713 klass->name_space = eclass->name_space;
6714 nsize = strlen (eclass->name);
6715 name = (char *)g_malloc (nsize + 2 + rank + 1);
6716 memcpy (name, eclass->name, nsize);
6719 memset (name + nsize + 1, ',', rank - 1);
6721 name [nsize + rank] = '*';
6722 name [nsize + rank + bounded] = ']';
6723 name [nsize + rank + bounded + 1] = 0;
6724 klass->name = mono_image_strdup (image, name);
6727 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6729 classes_size += sizeof (MonoClass);
6731 klass->type_token = 0;
6732 /* all arrays are marked serializable and sealed, bug #42779 */
6733 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6734 klass->parent = parent;
6735 klass->instance_size = mono_class_instance_size (klass->parent);
6737 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6738 /*Arrays of those two types are invalid.*/
6739 mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL);
6740 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6741 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6742 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6743 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6745 /* element_size -1 is ok as this is not an instantitable type*/
6746 klass->sizes.element_size = -1;
6748 klass->sizes.element_size = mono_class_array_element_size (eclass);
6750 mono_class_setup_supertypes (klass);
6752 if (eclass->generic_class)
6753 mono_class_init (eclass);
6754 if (!eclass->size_inited)
6755 mono_class_setup_fields (eclass);
6756 if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6757 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6759 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6763 if (eclass->enumtype)
6764 klass->cast_class = eclass->element_class;
6766 klass->cast_class = eclass;
6768 switch (klass->cast_class->byval_arg.type) {
6770 klass->cast_class = mono_defaults.byte_class;
6773 klass->cast_class = mono_defaults.int16_class;
6776 #if SIZEOF_VOID_P == 4
6780 klass->cast_class = mono_defaults.int32_class;
6783 #if SIZEOF_VOID_P == 8
6787 klass->cast_class = mono_defaults.int64_class;
6793 klass->element_class = eclass;
6795 if ((rank > 1) || bounded) {
6796 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6797 klass->byval_arg.type = MONO_TYPE_ARRAY;
6798 klass->byval_arg.data.array = at;
6799 at->eklass = eclass;
6801 /* FIXME: complete.... */
6803 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6804 klass->byval_arg.data.klass = eclass;
6806 klass->this_arg = klass->byval_arg;
6807 klass->this_arg.byref = 1;
6812 klass->generic_container = eclass->generic_container;
6814 if (rank == 1 && !bounded) {
6815 MonoClass *prev_class;
6817 mono_os_mutex_lock (&image->szarray_cache_lock);
6818 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6820 /* Someone got in before us */
6823 g_hash_table_insert (image->szarray_cache, eclass, klass);
6824 mono_os_mutex_unlock (&image->szarray_cache_lock);
6826 list = g_slist_append (rootlist, klass);
6827 g_hash_table_insert (image->array_cache, eclass, list);
6830 mono_loader_unlock ();
6832 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6838 * mono_array_class_get:
6839 * @element_class: element class
6840 * @rank: the dimension of the array class
6842 * Returns: A class object describing the array with element type @element_type and
6846 mono_array_class_get (MonoClass *eclass, guint32 rank)
6848 return mono_bounded_array_class_get (eclass, rank, FALSE);
6852 * mono_class_instance_size:
6855 * Use to get the size of a class in bytes.
6857 * Returns: The size of an object instance
6860 mono_class_instance_size (MonoClass *klass)
6862 if (!klass->size_inited)
6863 mono_class_init (klass);
6865 return klass->instance_size;
6869 * mono_class_min_align:
6872 * Use to get the computed minimum alignment requirements for the specified class.
6874 * Returns: minimm alignment requirements
6877 mono_class_min_align (MonoClass *klass)
6879 if (!klass->size_inited)
6880 mono_class_init (klass);
6882 return klass->min_align;
6886 * mono_class_value_size:
6889 * This function is used for value types, and return the
6890 * space and the alignment to store that kind of value object.
6892 * Returns: the size of a value of kind @klass
6895 mono_class_value_size (MonoClass *klass, guint32 *align)
6899 /* fixme: check disable, because we still have external revereces to
6900 * mscorlib and Dummy Objects
6902 /*g_assert (klass->valuetype);*/
6904 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6907 *align = klass->min_align;
6913 * mono_class_data_size:
6916 * Returns: The size of the static class data
6919 mono_class_data_size (MonoClass *klass)
6922 mono_class_init (klass);
6923 /* This can happen with dynamically created types */
6924 if (!klass->fields_inited)
6925 mono_class_setup_fields_locking (klass);
6927 /* in arrays, sizes.class_size is unioned with element_size
6928 * and arrays have no static fields
6932 return klass->sizes.class_size;
6936 * Auxiliary routine to mono_class_get_field
6938 * Takes a field index instead of a field token.
6940 static MonoClassField *
6941 mono_class_get_field_idx (MonoClass *klass, int idx)
6943 mono_class_setup_fields_locking (klass);
6944 if (mono_class_has_failure (klass))
6948 if (klass->image->uncompressed_metadata) {
6950 * klass->field.first points to the FieldPtr table, while idx points into the
6951 * Field table, so we have to do a search.
6953 /*FIXME this is broken for types with multiple fields with the same name.*/
6954 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6957 for (i = 0; i < klass->field.count; ++i)
6958 if (mono_field_get_name (&klass->fields [i]) == name)
6959 return &klass->fields [i];
6960 g_assert_not_reached ();
6962 if (klass->field.count) {
6963 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6964 return &klass->fields [idx - klass->field.first];
6968 klass = klass->parent;
6974 * mono_class_get_field:
6975 * @class: the class to lookup the field.
6976 * @field_token: the field token
6978 * Returns: A MonoClassField representing the type and offset of
6979 * the field, or a NULL value if the field does not belong to this
6983 mono_class_get_field (MonoClass *klass, guint32 field_token)
6985 int idx = mono_metadata_token_index (field_token);
6987 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6989 return mono_class_get_field_idx (klass, idx - 1);
6993 * mono_class_get_field_from_name:
6994 * @klass: the class to lookup the field.
6995 * @name: the field name
6997 * Search the class @klass and it's parents for a field with the name @name.
6999 * Returns: The MonoClassField pointer of the named field or NULL
7002 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7004 return mono_class_get_field_from_name_full (klass, name, NULL);
7008 * mono_class_get_field_from_name_full:
7009 * @klass: the class to lookup the field.
7010 * @name: the field name
7011 * @type: the type of the fields. This optional.
7013 * Search the class @klass and it's parents for a field with the name @name and type @type.
7015 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7016 * of its generic type definition.
7018 * Returns: The MonoClassField pointer of the named field or NULL
7021 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7025 mono_class_setup_fields_locking (klass);
7026 if (mono_class_has_failure (klass))
7030 for (i = 0; i < klass->field.count; ++i) {
7031 MonoClassField *field = &klass->fields [i];
7033 if (strcmp (name, mono_field_get_name (field)) != 0)
7037 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7038 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7043 klass = klass->parent;
7049 * mono_class_get_field_token:
7050 * @field: the field we need the token of
7052 * Get the token of a field. Note that the tokesn is only valid for the image
7053 * the field was loaded from. Don't use this function for fields in dynamic types.
7055 * Returns: The token representing the field in the image it was loaded from.
7058 mono_class_get_field_token (MonoClassField *field)
7060 MonoClass *klass = field->parent;
7063 mono_class_setup_fields_locking (klass);
7068 for (i = 0; i < klass->field.count; ++i) {
7069 if (&klass->fields [i] == field) {
7070 int idx = klass->field.first + i + 1;
7072 if (klass->image->uncompressed_metadata)
7073 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7074 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7077 klass = klass->parent;
7080 g_assert_not_reached ();
7085 mono_field_get_index (MonoClassField *field)
7087 int index = field - field->parent->fields;
7089 g_assert (index >= 0 && index < field->parent->field.count);
7095 * mono_class_get_field_default_value:
7097 * Return the default value of the field as a pointer into the metadata blob.
7100 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7103 guint32 constant_cols [MONO_CONSTANT_SIZE];
7105 MonoClass *klass = field->parent;
7107 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7109 if (!klass->ext || !klass->ext->field_def_values) {
7110 MonoFieldDefaultValue *def_values;
7112 mono_class_alloc_ext (klass);
7114 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7116 mono_image_lock (klass->image);
7117 mono_memory_barrier ();
7118 if (!klass->ext->field_def_values)
7119 klass->ext->field_def_values = def_values;
7120 mono_image_unlock (klass->image);
7123 field_index = mono_field_get_index (field);
7125 if (!klass->ext->field_def_values [field_index].data) {
7126 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7130 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7132 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7133 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7134 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7137 *def_type = klass->ext->field_def_values [field_index].def_type;
7138 return klass->ext->field_def_values [field_index].data;
7142 mono_property_get_index (MonoProperty *prop)
7144 int index = prop - prop->parent->ext->properties;
7146 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7152 * mono_class_get_property_default_value:
7154 * Return the default value of the field as a pointer into the metadata blob.
7157 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7160 guint32 constant_cols [MONO_CONSTANT_SIZE];
7161 MonoClass *klass = property->parent;
7163 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7165 * We don't cache here because it is not used by C# so it's quite rare, but
7166 * we still do the lookup in klass->ext because that is where the data
7167 * is stored for dynamic assemblies.
7170 if (image_is_dynamic (klass->image)) {
7171 int prop_index = mono_property_get_index (property);
7172 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7173 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7174 return klass->ext->prop_def_values [prop_index].data;
7178 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7182 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7183 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7184 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7188 mono_class_get_event_token (MonoEvent *event)
7190 MonoClass *klass = event->parent;
7195 for (i = 0; i < klass->ext->event.count; ++i) {
7196 if (&klass->ext->events [i] == event)
7197 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7200 klass = klass->parent;
7203 g_assert_not_reached ();
7208 * mono_class_get_property_from_name:
7210 * @name: name of the property to lookup in the specified class
7212 * Use this method to lookup a property in a class
7213 * Returns: the MonoProperty with the given name, or NULL if the property
7214 * does not exist on the @klass.
7217 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7221 gpointer iter = NULL;
7222 while ((p = mono_class_get_properties (klass, &iter))) {
7223 if (! strcmp (name, p->name))
7226 klass = klass->parent;
7232 * mono_class_get_property_token:
7233 * @prop: MonoProperty to query
7235 * Returns: The ECMA token for the specified property.
7238 mono_class_get_property_token (MonoProperty *prop)
7240 MonoClass *klass = prop->parent;
7244 gpointer iter = NULL;
7245 while ((p = mono_class_get_properties (klass, &iter))) {
7246 if (&klass->ext->properties [i] == prop)
7247 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7251 klass = klass->parent;
7254 g_assert_not_reached ();
7259 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7261 const char *name, *nspace;
7262 if (image_is_dynamic (image))
7263 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7265 switch (type_token & 0xff000000){
7266 case MONO_TOKEN_TYPE_DEF: {
7267 guint32 cols [MONO_TYPEDEF_SIZE];
7268 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7269 guint tidx = mono_metadata_token_index (type_token);
7271 if (tidx > tt->rows)
7272 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7274 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7275 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7276 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7277 if (strlen (nspace) == 0)
7278 return g_strdup_printf ("%s", name);
7280 return g_strdup_printf ("%s.%s", nspace, name);
7283 case MONO_TOKEN_TYPE_REF: {
7285 guint32 cols [MONO_TYPEREF_SIZE];
7286 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7287 guint tidx = mono_metadata_token_index (type_token);
7290 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7292 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7293 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7294 mono_error_cleanup (&error);
7298 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7299 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7300 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7301 if (strlen (nspace) == 0)
7302 return g_strdup_printf ("%s", name);
7304 return g_strdup_printf ("%s.%s", nspace, name);
7307 case MONO_TOKEN_TYPE_SPEC:
7308 return g_strdup_printf ("Typespec 0x%08x", type_token);
7310 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7315 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7317 if (image_is_dynamic (image))
7318 return g_strdup_printf ("DynamicAssembly %s", image->name);
7320 switch (type_token & 0xff000000){
7321 case MONO_TOKEN_TYPE_DEF:
7322 if (image->assembly)
7323 return mono_stringify_assembly_name (&image->assembly->aname);
7324 else if (image->assembly_name)
7325 return g_strdup (image->assembly_name);
7326 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7327 case MONO_TOKEN_TYPE_REF: {
7329 MonoAssemblyName aname;
7330 guint32 cols [MONO_TYPEREF_SIZE];
7331 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7332 guint32 idx = mono_metadata_token_index (type_token);
7335 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7337 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7338 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7339 mono_error_cleanup (&error);
7342 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7344 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7345 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7346 case MONO_RESOLUTION_SCOPE_MODULE:
7348 return g_strdup ("");
7349 case MONO_RESOLUTION_SCOPE_MODULEREF:
7351 return g_strdup ("");
7352 case MONO_RESOLUTION_SCOPE_TYPEREF:
7354 return g_strdup ("");
7355 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7356 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7357 return mono_stringify_assembly_name (&aname);
7359 g_assert_not_reached ();
7363 case MONO_TOKEN_TYPE_SPEC:
7365 return g_strdup ("");
7367 g_assert_not_reached ();
7374 * mono_class_get_full:
7375 * @image: the image where the class resides
7376 * @type_token: the token for the class
7377 * @context: the generic context used to evaluate generic instantiations in
7378 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7380 * Returns: The MonoClass that represents @type_token in @image
7383 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7387 klass = mono_class_get_checked (image, type_token, &error);
7389 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7390 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7392 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7398 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7402 mono_error_init (error);
7403 klass = mono_class_get_checked (image, type_token, error);
7405 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7406 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7411 * mono_class_get_checked:
7412 * @image: the image where the class resides
7413 * @type_token: the token for the class
7414 * @error: error object to return any error
7416 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7419 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7421 MonoClass *klass = NULL;
7423 mono_error_init (error);
7425 if (image_is_dynamic (image)) {
7426 int table = mono_metadata_token_table (type_token);
7428 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7429 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7432 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7436 switch (type_token & 0xff000000){
7437 case MONO_TOKEN_TYPE_DEF:
7438 klass = mono_class_create_from_typedef (image, type_token, error);
7440 case MONO_TOKEN_TYPE_REF:
7441 klass = mono_class_from_typeref_checked (image, type_token, error);
7443 case MONO_TOKEN_TYPE_SPEC:
7444 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7447 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7451 /* Generic case, should be avoided for when a better error is possible. */
7452 if (!klass && mono_error_ok (error)) {
7453 char *name = mono_class_name_from_token (image, type_token);
7454 char *assembly = mono_assembly_name_from_token (image, type_token);
7455 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7463 * mono_type_get_checked:
7464 * @image: the image where the type resides
7465 * @type_token: the token for the type
7466 * @context: the generic context used to evaluate generic instantiations in
7467 * @error: Error handling context
7469 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7471 * Returns: The MonoType that represents @type_token in @image
7474 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7476 MonoType *type = NULL;
7477 gboolean inflated = FALSE;
7479 mono_error_init (error);
7481 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7482 if (image_is_dynamic (image)) {
7483 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7484 return_val_if_nok (error, NULL);
7485 return mono_class_get_type (klass);
7488 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7489 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7496 return mono_class_get_type (klass);
7499 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7506 MonoType *tmp = type;
7507 type = mono_class_get_type (mono_class_from_mono_type (type));
7508 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7509 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7510 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7512 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7514 if (type->type != tmp->type)
7517 mono_metadata_free_type (tmp);
7524 * @image: image where the class token will be looked up.
7525 * @type_token: a type token from the image
7527 * Returns the MonoClass with the given @type_token on the @image
7530 mono_class_get (MonoImage *image, guint32 type_token)
7532 return mono_class_get_full (image, type_token, NULL);
7536 * mono_image_init_name_cache:
7538 * Initializes the class name cache stored in image->name_cache.
7540 * LOCKING: Acquires the corresponding image lock.
7543 mono_image_init_name_cache (MonoImage *image)
7545 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7546 guint32 cols [MONO_TYPEDEF_SIZE];
7549 guint32 i, visib, nspace_index;
7550 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7552 if (image->name_cache)
7555 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7557 if (image_is_dynamic (image)) {
7558 mono_image_lock (image);
7559 if (image->name_cache) {
7560 /* Somebody initialized it before us */
7561 g_hash_table_destroy (the_name_cache);
7563 mono_atomic_store_release (&image->name_cache, the_name_cache);
7565 mono_image_unlock (image);
7569 /* Temporary hash table to avoid lookups in the nspace_table */
7570 name_cache2 = g_hash_table_new (NULL, NULL);
7572 for (i = 1; i <= t->rows; ++i) {
7573 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7574 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7576 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7577 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7579 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7581 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7582 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7584 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7585 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7586 if (!nspace_table) {
7587 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7588 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7589 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7592 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7595 /* Load type names from EXPORTEDTYPES table */
7597 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7598 guint32 cols [MONO_EXP_TYPE_SIZE];
7601 for (i = 0; i < t->rows; ++i) {
7602 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7604 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7605 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7609 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7610 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7612 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7613 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7614 if (!nspace_table) {
7615 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7616 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7617 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7620 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7624 g_hash_table_destroy (name_cache2);
7626 mono_image_lock (image);
7627 if (image->name_cache) {
7628 /* Somebody initialized it before us */
7629 g_hash_table_destroy (the_name_cache);
7631 mono_atomic_store_release (&image->name_cache, the_name_cache);
7633 mono_image_unlock (image);
7636 /*FIXME Only dynamic assemblies should allow this operation.*/
7638 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7639 const char *name, guint32 index)
7641 GHashTable *nspace_table;
7642 GHashTable *name_cache;
7645 mono_image_init_name_cache (image);
7646 mono_image_lock (image);
7648 name_cache = image->name_cache;
7649 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7650 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7651 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7654 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7655 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7657 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7659 mono_image_unlock (image);
7668 find_nocase (gpointer key, gpointer value, gpointer user_data)
7670 char *name = (char*)key;
7671 FindUserData *data = (FindUserData*)user_data;
7673 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7674 data->value = value;
7678 * mono_class_from_name_case:
7679 * @image: The MonoImage where the type is looked up in
7680 * @name_space: the type namespace
7681 * @name: the type short name.
7682 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7684 * Obtains a MonoClass with a given namespace and a given name which
7685 * is located in the given MonoImage. The namespace and name
7686 * lookups are case insensitive.
7689 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7692 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7693 mono_error_cleanup (&error);
7699 * mono_class_from_name_case:
7700 * @image: The MonoImage where the type is looked up in
7701 * @name_space: the type namespace
7702 * @name: the type short name.
7705 * Obtains a MonoClass with a given namespace and a given name which
7706 * is located in the given MonoImage. The namespace and name
7707 * lookups are case insensitive.
7709 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7710 * was not found. The @error object will contain information about the problem
7714 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7716 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7717 guint32 cols [MONO_TYPEDEF_SIZE];
7722 mono_error_init (error);
7724 if (image_is_dynamic (image)) {
7726 FindUserData user_data;
7728 mono_image_init_name_cache (image);
7729 mono_image_lock (image);
7731 user_data.key = name_space;
7732 user_data.value = NULL;
7733 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7735 if (user_data.value) {
7736 GHashTable *nspace_table = (GHashTable*)user_data.value;
7738 user_data.key = name;
7739 user_data.value = NULL;
7741 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7743 if (user_data.value)
7744 token = GPOINTER_TO_UINT (user_data.value);
7747 mono_image_unlock (image);
7750 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7756 /* add a cache if needed */
7757 for (i = 1; i <= t->rows; ++i) {
7758 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7759 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7761 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7762 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7764 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7766 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7767 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7768 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7769 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7775 return_nested_in (MonoClass *klass, char *nested)
7778 char *s = strchr (nested, '/');
7779 gpointer iter = NULL;
7786 while ((found = mono_class_get_nested_types (klass, &iter))) {
7787 if (strcmp (found->name, nested) == 0) {
7789 return return_nested_in (found, s);
7797 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7799 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7800 MonoImage *file_image;
7804 mono_error_init (error);
7807 * The EXPORTEDTYPES table only contains public types, so have to search the
7809 * Note: image->modules contains the contents of the MODULEREF table, while
7810 * the real module list is in the FILE table.
7812 for (i = 0; i < file_table->rows; i++) {
7813 guint32 cols [MONO_FILE_SIZE];
7814 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7815 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7818 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7820 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7821 if (klass || !is_ok (error))
7830 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7832 GHashTable *nspace_table;
7833 MonoImage *loaded_image;
7840 mono_error_init (error);
7842 // Checking visited images avoids stack overflows when cyclic references exist.
7843 if (g_hash_table_lookup (visited_images, image))
7846 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7848 if ((nested = strchr (name, '/'))) {
7849 int pos = nested - name;
7850 int len = strlen (name);
7853 memcpy (buf, name, len + 1);
7855 nested = buf + pos + 1;
7859 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7860 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7861 gboolean res = get_class_from_name (image, name_space, name, &klass);
7864 klass = search_modules (image, name_space, name, error);
7869 return klass ? return_nested_in (klass, nested) : NULL;
7875 mono_image_init_name_cache (image);
7876 mono_image_lock (image);
7878 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7881 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7883 mono_image_unlock (image);
7885 if (!token && image_is_dynamic (image) && image->modules) {
7886 /* Search modules as well */
7887 for (i = 0; i < image->module_count; ++i) {
7888 MonoImage *module = image->modules [i];
7890 klass = mono_class_from_name_checked (module, name_space, name, error);
7891 if (klass || !is_ok (error))
7897 klass = search_modules (image, name_space, name, error);
7898 if (klass || !is_ok (error))
7903 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7904 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7905 guint32 cols [MONO_EXP_TYPE_SIZE];
7908 idx = mono_metadata_token_index (token);
7910 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7912 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7913 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7914 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7917 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7919 return klass ? return_nested_in (klass, nested) : NULL;
7921 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7922 guint32 assembly_idx;
7924 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7926 mono_assembly_load_reference (image, assembly_idx - 1);
7927 g_assert (image->references [assembly_idx - 1]);
7928 if (image->references [assembly_idx - 1] == (gpointer)-1)
7930 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7932 return klass ? return_nested_in (klass, nested) : NULL;
7935 g_assert_not_reached ();
7939 token = MONO_TOKEN_TYPE_DEF | token;
7941 klass = mono_class_get_checked (image, token, error);
7943 return return_nested_in (klass, nested);
7948 * mono_class_from_name_checked:
7949 * @image: The MonoImage where the type is looked up in
7950 * @name_space: the type namespace
7951 * @name: the type short name.
7953 * Obtains a MonoClass with a given namespace and a given name which
7954 * is located in the given MonoImage.
7956 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7957 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7960 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7963 GHashTable *visited_images;
7965 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7967 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7969 g_hash_table_destroy (visited_images);
7975 * mono_class_from_name:
7976 * @image: The MonoImage where the type is looked up in
7977 * @name_space: the type namespace
7978 * @name: the type short name.
7980 * Obtains a MonoClass with a given namespace and a given name which
7981 * is located in the given MonoImage.
7983 * To reference nested classes, use the "/" character as a separator.
7984 * For example use "Foo/Bar" to reference the class Bar that is nested
7985 * inside Foo, like this: "class Foo { class Bar {} }".
7988 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7993 klass = mono_class_from_name_checked (image, name_space, name, &error);
7994 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8000 * mono_class_load_from_name:
8001 * @image: The MonoImage where the type is looked up in
8002 * @name_space: the type namespace
8003 * @name: the type short name.
8005 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8006 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8007 * If they are missing. Thing of System.Object or System.String.
8010 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8015 klass = mono_class_from_name_checked (image, name_space, name, &error);
8017 g_error ("Runtime critical type %s.%s not found", name_space, name);
8018 if (!mono_error_ok (&error))
8019 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8024 * mono_class_try_load_from_name:
8025 * @image: The MonoImage where the type is looked up in
8026 * @name_space: the type namespace
8027 * @name: the type short name.
8029 * This function tries to load a type, returning the class was found or NULL otherwise.
8030 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8032 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8033 * a type that we would otherwise assume to be available but was not due some error.
8037 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8042 klass = mono_class_from_name_checked (image, name_space, name, &error);
8043 if (!mono_error_ok (&error))
8044 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8050 * mono_class_is_subclass_of:
8051 * @klass: class to probe if it is a subclass of another one
8052 * @klassc: the class we suspect is the base class
8053 * @check_interfaces: whether we should perform interface checks
8055 * This method determines whether @klass is a subclass of @klassc.
8057 * If the @check_interfaces flag is set, then if @klassc is an interface
8058 * this method return TRUE if the @klass implements the interface or
8059 * if @klass is an interface, if one of its base classes is @klass.
8061 * If @check_interfaces is false then, then if @klass is not an interface
8062 * then it returns TRUE if the @klass is a subclass of @klassc.
8064 * if @klass is an interface and @klassc is System.Object, then this function
8069 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8070 gboolean check_interfaces)
8072 /* FIXME test for interfaces with variant generic arguments */
8073 mono_class_init (klass);
8074 mono_class_init (klassc);
8076 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8077 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8079 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8082 for (i = 0; i < klass->interface_count; i ++) {
8083 MonoClass *ic = klass->interfaces [i];
8088 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8093 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8096 if (klassc == mono_defaults.object_class)
8103 mono_type_is_generic_argument (MonoType *type)
8105 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8109 mono_class_has_variant_generic_params (MonoClass *klass)
8112 MonoGenericContainer *container;
8114 if (!klass->generic_class)
8117 container = klass->generic_class->container_class->generic_container;
8119 for (i = 0; i < container->type_argc; ++i)
8120 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8127 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8129 if (target == candidate)
8132 if (check_for_reference_conv &&
8133 mono_type_is_generic_argument (&target->byval_arg) &&
8134 mono_type_is_generic_argument (&candidate->byval_arg)) {
8135 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8136 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8138 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8141 if (!mono_class_is_assignable_from (target, candidate))
8147 * @container the generic container from the GTD
8148 * @klass: the class to be assigned to
8149 * @oklass: the source class
8151 * Both @klass and @oklass must be instances of the same generic interface.
8153 * Returns: TRUE if @klass can be assigned to a @klass variable
8156 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8159 MonoType **klass_argv, **oklass_argv;
8160 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8161 MonoGenericContainer *container = klass_gtd->generic_container;
8163 if (klass == oklass)
8166 /*Viable candidates are instances of the same generic interface*/
8167 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8170 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8171 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8173 for (j = 0; j < container->type_argc; ++j) {
8174 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8175 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8177 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8181 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8182 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8184 if (param1_class != param2_class) {
8185 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8186 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8188 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8189 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8199 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8201 MonoGenericParam *gparam, *ogparam;
8202 MonoGenericParamInfo *tinfo, *cinfo;
8203 MonoClass **candidate_class;
8204 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8207 if (target == candidate)
8209 if (target->byval_arg.type != candidate->byval_arg.type)
8212 gparam = target->byval_arg.data.generic_param;
8213 ogparam = candidate->byval_arg.data.generic_param;
8214 tinfo = mono_generic_param_info (gparam);
8215 cinfo = mono_generic_param_info (ogparam);
8217 class_constraint_satisfied = FALSE;
8218 valuetype_constraint_satisfied = FALSE;
8220 /*candidate must have a super set of target's special constraints*/
8221 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8222 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8224 if (cinfo->constraints) {
8225 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8226 MonoClass *cc = *candidate_class;
8228 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8229 class_constraint_satisfied = TRUE;
8230 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8231 valuetype_constraint_satisfied = TRUE;
8234 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8235 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8237 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8239 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8241 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8242 valuetype_constraint_satisfied)) {
8247 /*candidate type constraints must be a superset of target's*/
8248 if (tinfo->constraints) {
8249 MonoClass **target_class;
8250 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8251 MonoClass *tc = *target_class;
8254 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8255 * check it's constraints since it satisfy the constraint by itself.
8257 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8260 if (!cinfo->constraints)
8263 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8264 MonoClass *cc = *candidate_class;
8266 if (mono_class_is_assignable_from (tc, cc))
8270 * This happens when we have the following:
8272 * Bar<K> where K : IFace
8273 * Foo<T, U> where T : U where U : IFace
8275 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8278 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8279 if (mono_gparam_is_assignable_from (target, cc))
8283 if (!*candidate_class)
8288 /*candidate itself must have a constraint that satisfy target*/
8289 if (cinfo->constraints) {
8290 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8291 MonoClass *cc = *candidate_class;
8292 if (mono_class_is_assignable_from (target, cc))
8300 * mono_class_is_assignable_from:
8301 * @klass: the class to be assigned to
8302 * @oklass: the source class
8304 * Returns: TRUE if an instance of object oklass can be assigned to an
8305 * instance of object @klass
8308 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8311 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8313 mono_class_init (klass);
8315 if (!oklass->inited)
8316 mono_class_init (oklass);
8318 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8321 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8322 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8324 return mono_gparam_is_assignable_from (klass, oklass);
8327 if (MONO_CLASS_IS_INTERFACE (klass)) {
8328 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8329 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8330 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8334 for (i = 0; constraints [i]; ++i) {
8335 if (mono_class_is_assignable_from (klass, constraints [i]))
8343 /* interface_offsets might not be set for dynamic classes */
8344 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8346 * oklass might be a generic type parameter but they have
8347 * interface_offsets set.
8349 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8350 if (!is_ok (&error)) {
8351 mono_error_cleanup (&error);
8356 if (!oklass->interface_bitmap)
8357 /* Happens with generic instances of not-yet created dynamic types */
8359 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8362 if (mono_class_has_variant_generic_params (klass)) {
8364 mono_class_setup_interfaces (oklass, &error);
8365 if (!mono_error_ok (&error)) {
8366 mono_error_cleanup (&error);
8370 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8371 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8372 MonoClass *iface = oklass->interfaces_packed [i];
8374 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8379 } else if (klass->delegate) {
8380 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8382 }else if (klass->rank) {
8383 MonoClass *eclass, *eoclass;
8385 if (oklass->rank != klass->rank)
8388 /* vectors vs. one dimensional arrays */
8389 if (oklass->byval_arg.type != klass->byval_arg.type)
8392 eclass = klass->cast_class;
8393 eoclass = oklass->cast_class;
8396 * a is b does not imply a[] is b[] when a is a valuetype, and
8397 * b is a reference type.
8400 if (eoclass->valuetype) {
8401 if ((eclass == mono_defaults.enum_class) ||
8402 (eclass == mono_defaults.enum_class->parent) ||
8403 (eclass == mono_defaults.object_class))
8407 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8408 } else if (mono_class_is_nullable (klass)) {
8409 if (mono_class_is_nullable (oklass))
8410 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8412 return mono_class_is_assignable_from (klass->cast_class, oklass);
8413 } else if (klass == mono_defaults.object_class)
8416 return mono_class_has_parent (oklass, klass);
8419 /*Check if @oklass is variant compatible with @klass.*/
8421 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8424 MonoType **klass_argv, **oklass_argv;
8425 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8426 MonoGenericContainer *container = klass_gtd->generic_container;
8428 /*Viable candidates are instances of the same generic interface*/
8429 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8432 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8433 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8435 for (j = 0; j < container->type_argc; ++j) {
8436 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8437 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8439 if (param1_class->valuetype != param2_class->valuetype)
8443 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8444 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8446 if (param1_class != param2_class) {
8447 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8448 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8450 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8451 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8459 /*Check if @candidate implements the interface @target*/
8461 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8465 gboolean is_variant = mono_class_has_variant_generic_params (target);
8467 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8468 if (mono_class_is_variant_compatible_slow (target, candidate))
8473 if (candidate == target)
8476 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8477 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8478 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8480 if (tb && tb->interfaces) {
8481 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8482 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8483 MonoClass *iface_class;
8485 /* we can't realize the type here since it can do pretty much anything. */
8488 iface_class = mono_class_from_mono_type (iface->type);
8489 if (iface_class == target)
8491 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8493 if (mono_class_implement_interface_slow (target, iface_class))
8498 /*setup_interfaces don't mono_class_init anything*/
8499 /*FIXME this doesn't handle primitive type arrays.
8500 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8501 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8503 mono_class_setup_interfaces (candidate, &error);
8504 if (!mono_error_ok (&error)) {
8505 mono_error_cleanup (&error);
8509 for (i = 0; i < candidate->interface_count; ++i) {
8510 if (candidate->interfaces [i] == target)
8513 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8516 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8520 candidate = candidate->parent;
8521 } while (candidate);
8527 * Check if @oklass can be assigned to @klass.
8528 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8531 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8533 if (candidate == target)
8535 if (target == mono_defaults.object_class)
8538 if (mono_class_has_parent (candidate, target))
8541 /*If target is not an interface there is no need to check them.*/
8542 if (MONO_CLASS_IS_INTERFACE (target))
8543 return mono_class_implement_interface_slow (target, candidate);
8545 if (target->delegate && mono_class_has_variant_generic_params (target))
8546 return mono_class_is_variant_compatible (target, candidate, FALSE);
8549 MonoClass *eclass, *eoclass;
8551 if (target->rank != candidate->rank)
8554 /* vectors vs. one dimensional arrays */
8555 if (target->byval_arg.type != candidate->byval_arg.type)
8558 eclass = target->cast_class;
8559 eoclass = candidate->cast_class;
8562 * a is b does not imply a[] is b[] when a is a valuetype, and
8563 * b is a reference type.
8566 if (eoclass->valuetype) {
8567 if ((eclass == mono_defaults.enum_class) ||
8568 (eclass == mono_defaults.enum_class->parent) ||
8569 (eclass == mono_defaults.object_class))
8573 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8575 /*FIXME properly handle nullables */
8576 /*FIXME properly handle (M)VAR */
8581 * mono_class_get_cctor:
8582 * @klass: A MonoClass pointer
8584 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8587 mono_class_get_cctor (MonoClass *klass)
8589 MonoCachedClassInfo cached_info;
8591 if (image_is_dynamic (klass->image)) {
8593 * has_cctor is not set for these classes because mono_class_init () is
8596 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8599 if (!klass->has_cctor)
8602 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8604 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8605 if (!mono_error_ok (&error))
8606 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8610 if (klass->generic_class && !klass->methods)
8611 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8613 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8617 * mono_class_get_finalizer:
8618 * @klass: The MonoClass pointer
8620 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8623 mono_class_get_finalizer (MonoClass *klass)
8625 MonoCachedClassInfo cached_info;
8628 mono_class_init (klass);
8629 if (!mono_class_has_finalizer (klass))
8632 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8634 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8635 if (!mono_error_ok (&error))
8636 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8639 mono_class_setup_vtable (klass);
8640 return klass->vtable [finalize_slot];
8645 * mono_class_needs_cctor_run:
8646 * @klass: the MonoClass pointer
8647 * @caller: a MonoMethod describing the caller
8649 * Determines whenever the class has a static constructor and whenever it
8650 * needs to be called when executing CALLER.
8653 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8657 method = mono_class_get_cctor (klass);
8659 return (method == caller) ? FALSE : TRUE;
8665 * mono_class_array_element_size:
8668 * Returns: The number of bytes an element of type @klass
8669 * uses when stored into an array.
8672 mono_class_array_element_size (MonoClass *klass)
8674 MonoType *type = &klass->byval_arg;
8677 switch (type->type) {
8680 case MONO_TYPE_BOOLEAN:
8684 case MONO_TYPE_CHAR:
8693 case MONO_TYPE_CLASS:
8694 case MONO_TYPE_STRING:
8695 case MONO_TYPE_OBJECT:
8696 case MONO_TYPE_SZARRAY:
8697 case MONO_TYPE_ARRAY:
8698 return sizeof (gpointer);
8703 case MONO_TYPE_VALUETYPE:
8704 if (type->data.klass->enumtype) {
8705 type = mono_class_enum_basetype (type->data.klass);
8706 klass = klass->element_class;
8709 return mono_class_instance_size (klass) - sizeof (MonoObject);
8710 case MONO_TYPE_GENERICINST:
8711 type = &type->data.generic_class->container_class->byval_arg;
8714 case MONO_TYPE_MVAR: {
8717 return mono_type_size (type, &align);
8719 case MONO_TYPE_VOID:
8723 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8729 * mono_array_element_size:
8730 * @ac: pointer to a #MonoArrayClass
8732 * Returns: The size of single array element.
8735 mono_array_element_size (MonoClass *ac)
8737 g_assert (ac->rank);
8738 return ac->sizes.element_size;
8742 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8743 MonoGenericContext *context)
8746 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8747 g_assert (mono_error_ok (&error));
8752 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8753 MonoGenericContext *context, MonoError *error)
8755 mono_error_init (error);
8757 if (image_is_dynamic (image)) {
8758 MonoClass *tmp_handle_class;
8759 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8761 mono_error_assert_ok (error);
8762 g_assert (tmp_handle_class);
8764 *handle_class = tmp_handle_class;
8766 if (tmp_handle_class == mono_defaults.typehandle_class)
8767 return &((MonoClass*)obj)->byval_arg;
8772 switch (token & 0xff000000) {
8773 case MONO_TOKEN_TYPE_DEF:
8774 case MONO_TOKEN_TYPE_REF:
8775 case MONO_TOKEN_TYPE_SPEC: {
8778 *handle_class = mono_defaults.typehandle_class;
8779 type = mono_type_get_checked (image, token, context, error);
8783 mono_class_init (mono_class_from_mono_type (type));
8784 /* We return a MonoType* as handle */
8787 case MONO_TOKEN_FIELD_DEF: {
8789 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8791 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8795 *handle_class = mono_defaults.fieldhandle_class;
8796 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8800 mono_class_init (klass);
8801 return mono_class_get_field (klass, token);
8803 case MONO_TOKEN_METHOD_DEF:
8804 case MONO_TOKEN_METHOD_SPEC: {
8806 meth = mono_get_method_checked (image, token, NULL, context, error);
8808 *handle_class = mono_defaults.methodhandle_class;
8814 case MONO_TOKEN_MEMBER_REF: {
8815 guint32 cols [MONO_MEMBERREF_SIZE];
8817 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8818 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8819 mono_metadata_decode_blob_size (sig, &sig);
8820 if (*sig == 0x6) { /* it's a field */
8822 MonoClassField *field;
8823 field = mono_field_from_token_checked (image, token, &klass, context, error);
8825 *handle_class = mono_defaults.fieldhandle_class;
8829 meth = mono_get_method_checked (image, token, NULL, context, error);
8831 *handle_class = mono_defaults.methodhandle_class;
8836 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8842 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8844 MonoClass *handle_class;
8845 mono_error_init (error);
8846 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8850 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8852 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8855 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8858 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8860 get_cached_class_info = func;
8864 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8866 if (!get_cached_class_info)
8869 return get_cached_class_info (klass, res);
8873 mono_install_get_class_from_name (MonoGetClassFromName func)
8875 get_class_from_name = func;
8879 * mono_class_get_image:
8881 * Use this method to get the `MonoImage*` where this class came from.
8883 * Returns: The image where this class is defined.
8886 mono_class_get_image (MonoClass *klass)
8888 return klass->image;
8892 * mono_class_get_element_class:
8893 * @klass: the MonoClass to act on
8895 * Use this function to get the element class of an array.
8897 * Returns: The element class of an array.
8900 mono_class_get_element_class (MonoClass *klass)
8902 return klass->element_class;
8906 * mono_class_is_valuetype:
8907 * @klass: the MonoClass to act on
8909 * Use this method to determine if the provided `MonoClass*` represents a value type,
8910 * or a reference type.
8912 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8915 mono_class_is_valuetype (MonoClass *klass)
8917 return klass->valuetype;
8921 * mono_class_is_enum:
8922 * @klass: the MonoClass to act on
8924 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8926 * Returns: TRUE if the MonoClass represents an enumeration.
8929 mono_class_is_enum (MonoClass *klass)
8931 return klass->enumtype;
8935 * mono_class_enum_basetype:
8936 * @klass: the MonoClass to act on
8938 * Use this function to get the underlying type for an enumeration value.
8940 * Returns: The underlying type representation for an enumeration.
8943 mono_class_enum_basetype (MonoClass *klass)
8945 if (klass->element_class == klass)
8946 /* SRE or broken types */
8949 return &klass->element_class->byval_arg;
8953 * mono_class_get_parent
8954 * @klass: the MonoClass to act on
8956 * Returns: The parent class for this class.
8959 mono_class_get_parent (MonoClass *klass)
8961 return klass->parent;
8965 * mono_class_get_nesting_type:
8966 * @klass: the MonoClass to act on
8968 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8970 * If the return is NULL, this indicates that this class is not nested.
8972 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8975 mono_class_get_nesting_type (MonoClass *klass)
8977 return klass->nested_in;
8981 * mono_class_get_rank:
8982 * @klass: the MonoClass to act on
8984 * Returns: The rank for the array (the number of dimensions).
8987 mono_class_get_rank (MonoClass *klass)
8993 * mono_class_get_flags:
8994 * @klass: the MonoClass to act on
8996 * The type flags from the TypeDef table from the metadata.
8997 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
9000 * Returns: The flags from the TypeDef table.
9003 mono_class_get_flags (MonoClass *klass)
9005 return klass->flags;
9009 * mono_class_get_name
9010 * @klass: the MonoClass to act on
9012 * Returns: The name of the class.
9015 mono_class_get_name (MonoClass *klass)
9021 * mono_class_get_namespace:
9022 * @klass: the MonoClass to act on
9024 * Returns: The namespace of the class.
9027 mono_class_get_namespace (MonoClass *klass)
9029 return klass->name_space;
9033 * mono_class_get_type:
9034 * @klass: the MonoClass to act on
9036 * This method returns the internal Type representation for the class.
9038 * Returns: The MonoType from the class.
9041 mono_class_get_type (MonoClass *klass)
9043 return &klass->byval_arg;
9047 * mono_class_get_type_token:
9048 * @klass: the MonoClass to act on
9050 * This method returns type token for the class.
9052 * Returns: The type token for the class.
9055 mono_class_get_type_token (MonoClass *klass)
9057 return klass->type_token;
9061 * mono_class_get_byref_type:
9062 * @klass: the MonoClass to act on
9067 mono_class_get_byref_type (MonoClass *klass)
9069 return &klass->this_arg;
9073 * mono_class_num_fields:
9074 * @klass: the MonoClass to act on
9076 * Returns: The number of static and instance fields in the class.
9079 mono_class_num_fields (MonoClass *klass)
9081 return klass->field.count;
9085 * mono_class_num_methods:
9086 * @klass: the MonoClass to act on
9088 * Returns: The number of methods in the class.
9091 mono_class_num_methods (MonoClass *klass)
9093 return klass->method.count;
9097 * mono_class_num_properties
9098 * @klass: the MonoClass to act on
9100 * Returns: The number of properties in the class.
9103 mono_class_num_properties (MonoClass *klass)
9105 mono_class_setup_properties (klass);
9107 return klass->ext->property.count;
9111 * mono_class_num_events:
9112 * @klass: the MonoClass to act on
9114 * Returns: The number of events in the class.
9117 mono_class_num_events (MonoClass *klass)
9119 mono_class_setup_events (klass);
9121 return klass->ext->event.count;
9125 * mono_class_get_fields:
9126 * @klass: the MonoClass to act on
9128 * This routine is an iterator routine for retrieving the fields in a class.
9130 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9131 * iterate over all of the elements. When no more values are
9132 * available, the return value is NULL.
9134 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9137 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9139 MonoClassField* field;
9143 mono_class_setup_fields_locking (klass);
9144 if (mono_class_has_failure (klass))
9146 /* start from the first */
9147 if (klass->field.count) {
9148 *iter = &klass->fields [0];
9149 return &klass->fields [0];
9155 field = (MonoClassField *)*iter;
9157 if (field < &klass->fields [klass->field.count]) {
9165 * mono_class_get_methods
9166 * @klass: the MonoClass to act on
9168 * This routine is an iterator routine for retrieving the fields in a class.
9170 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9171 * iterate over all of the elements. When no more values are
9172 * available, the return value is NULL.
9174 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9177 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9179 MonoMethod** method;
9183 mono_class_setup_methods (klass);
9186 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9187 * FIXME we should better report this error to the caller
9189 if (!klass->methods)
9191 /* start from the first */
9192 if (klass->method.count) {
9193 *iter = &klass->methods [0];
9194 return klass->methods [0];
9200 method = (MonoMethod **)*iter;
9202 if (method < &klass->methods [klass->method.count]) {
9210 * mono_class_get_virtual_methods:
9212 * Iterate over the virtual methods of KLASS.
9214 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9217 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9219 MonoMethod** method;
9222 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9224 mono_class_setup_methods (klass);
9226 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9227 * FIXME we should better report this error to the caller
9229 if (!klass->methods)
9231 /* start from the first */
9232 method = &klass->methods [0];
9234 method = (MonoMethod **)*iter;
9237 while (method < &klass->methods [klass->method.count]) {
9238 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9242 if (method < &klass->methods [klass->method.count]) {
9249 /* Search directly in metadata to avoid calling setup_methods () */
9250 MonoMethod *res = NULL;
9256 start_index = GPOINTER_TO_UINT (*iter);
9259 for (i = start_index; i < klass->method.count; ++i) {
9262 /* klass->method.first points into the methodptr table */
9263 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9265 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9269 if (i < klass->method.count) {
9271 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9272 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9274 /* Add 1 here so the if (*iter) check fails */
9275 *iter = GUINT_TO_POINTER (i + 1);
9284 * mono_class_get_properties:
9285 * @klass: the MonoClass to act on
9287 * This routine is an iterator routine for retrieving the properties in a class.
9289 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9290 * iterate over all of the elements. When no more values are
9291 * available, the return value is NULL.
9293 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9296 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9298 MonoProperty* property;
9302 mono_class_setup_properties (klass);
9303 /* start from the first */
9304 if (klass->ext->property.count) {
9305 *iter = &klass->ext->properties [0];
9306 return (MonoProperty *)*iter;
9312 property = (MonoProperty *)*iter;
9314 if (property < &klass->ext->properties [klass->ext->property.count]) {
9316 return (MonoProperty *)*iter;
9322 * mono_class_get_events:
9323 * @klass: the MonoClass to act on
9325 * This routine is an iterator routine for retrieving the properties in a class.
9327 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9328 * iterate over all of the elements. When no more values are
9329 * available, the return value is NULL.
9331 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9334 mono_class_get_events (MonoClass* klass, gpointer *iter)
9340 mono_class_setup_events (klass);
9341 /* start from the first */
9342 if (klass->ext->event.count) {
9343 *iter = &klass->ext->events [0];
9344 return (MonoEvent *)*iter;
9350 event = (MonoEvent *)*iter;
9352 if (event < &klass->ext->events [klass->ext->event.count]) {
9354 return (MonoEvent *)*iter;
9360 * mono_class_get_interfaces
9361 * @klass: the MonoClass to act on
9363 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9365 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9366 * iterate over all of the elements. When no more values are
9367 * available, the return value is NULL.
9369 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9372 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9380 mono_class_init (klass);
9381 if (!klass->interfaces_inited) {
9382 mono_class_setup_interfaces (klass, &error);
9383 if (!mono_error_ok (&error)) {
9384 mono_error_cleanup (&error);
9388 /* start from the first */
9389 if (klass->interface_count) {
9390 *iter = &klass->interfaces [0];
9391 return klass->interfaces [0];
9397 iface = (MonoClass **)*iter;
9399 if (iface < &klass->interfaces [klass->interface_count]) {
9407 setup_nested_types (MonoClass *klass)
9410 GList *classes, *nested_classes, *l;
9413 if (klass->nested_classes_inited)
9416 if (!klass->type_token)
9417 klass->nested_classes_inited = TRUE;
9419 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9423 guint32 cols [MONO_NESTED_CLASS_SIZE];
9424 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9425 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9426 if (!mono_error_ok (&error)) {
9427 /*FIXME don't swallow the error message*/
9428 mono_error_cleanup (&error);
9430 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9434 classes = g_list_prepend (classes, nclass);
9436 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9439 mono_class_alloc_ext (klass);
9441 nested_classes = NULL;
9442 for (l = classes; l; l = l->next)
9443 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9444 g_list_free (classes);
9446 mono_image_lock (klass->image);
9448 mono_memory_barrier ();
9449 if (!klass->nested_classes_inited) {
9450 klass->ext->nested_classes = nested_classes;
9451 mono_memory_barrier ();
9452 klass->nested_classes_inited = TRUE;
9455 mono_image_unlock (klass->image);
9459 * mono_class_get_nested_types
9460 * @klass: the MonoClass to act on
9462 * This routine is an iterator routine for retrieving the nested types of a class.
9463 * This works only if @klass is non-generic, or a generic type definition.
9465 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9466 * iterate over all of the elements. When no more values are
9467 * available, the return value is NULL.
9469 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9472 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9478 if (!klass->nested_classes_inited)
9479 setup_nested_types (klass);
9482 /* start from the first */
9483 if (klass->ext && klass->ext->nested_classes) {
9484 *iter = klass->ext->nested_classes;
9485 return (MonoClass *)klass->ext->nested_classes->data;
9487 /* no nested types */
9491 item = (GList *)*iter;
9495 return (MonoClass *)item->data;
9502 * mono_class_is_delegate
9503 * @klass: the MonoClass to act on
9505 * Returns: TRUE if the MonoClass represents a System.Delegate.
9508 mono_class_is_delegate (MonoClass *klass)
9510 return klass->delegate;
9514 * mono_class_implements_interface
9515 * @klass: The MonoClass to act on
9516 * @interface: The interface to check if @klass implements.
9518 * Returns: TRUE if @klass implements @interface.
9521 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9523 return mono_class_is_assignable_from (iface, klass);
9527 * mono_field_get_name:
9528 * @field: the MonoClassField to act on
9530 * Returns: The name of the field.
9533 mono_field_get_name (MonoClassField *field)
9539 * mono_field_get_type:
9540 * @field: the MonoClassField to act on
9542 * Returns: MonoType of the field.
9545 mono_field_get_type (MonoClassField *field)
9548 MonoType *type = mono_field_get_type_checked (field, &error);
9549 if (!mono_error_ok (&error)) {
9550 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9551 mono_error_cleanup (&error);
9558 * mono_field_get_type_checked:
9559 * @field: the MonoClassField to act on
9560 * @error: used to return any erro found while retrieving @field type
9562 * Returns: MonoType of the field.
9565 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9567 mono_error_init (error);
9569 mono_field_resolve_type (field, error);
9574 * mono_field_get_parent:
9575 * @field: the MonoClassField to act on
9577 * Returns: MonoClass where the field was defined.
9580 mono_field_get_parent (MonoClassField *field)
9582 return field->parent;
9586 * mono_field_get_flags;
9587 * @field: the MonoClassField to act on
9589 * The metadata flags for a field are encoded using the
9590 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9592 * Returns: The flags for the field.
9595 mono_field_get_flags (MonoClassField *field)
9598 return mono_field_resolve_flags (field);
9599 return field->type->attrs;
9603 * mono_field_get_offset:
9604 * @field: the MonoClassField to act on
9606 * Returns: The field offset.
9609 mono_field_get_offset (MonoClassField *field)
9611 return field->offset;
9615 mono_field_get_rva (MonoClassField *field)
9619 MonoClass *klass = field->parent;
9620 MonoFieldDefaultValue *field_def_values;
9622 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9624 if (!klass->ext || !klass->ext->field_def_values) {
9625 mono_class_alloc_ext (klass);
9627 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9629 mono_image_lock (klass->image);
9630 if (!klass->ext->field_def_values)
9631 klass->ext->field_def_values = field_def_values;
9632 mono_image_unlock (klass->image);
9635 field_index = mono_field_get_index (field);
9637 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9638 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9640 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9641 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9644 return klass->ext->field_def_values [field_index].data;
9648 * mono_field_get_data:
9649 * @field: the MonoClassField to act on
9651 * Returns: A pointer to the metadata constant value or to the field
9652 * data if it has an RVA flag.
9655 mono_field_get_data (MonoClassField *field)
9657 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9658 MonoTypeEnum def_type;
9660 return mono_class_get_field_default_value (field, &def_type);
9661 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9662 return mono_field_get_rva (field);
9669 * mono_property_get_name:
9670 * @prop: the MonoProperty to act on
9672 * Returns: The name of the property
9675 mono_property_get_name (MonoProperty *prop)
9681 * mono_property_get_set_method
9682 * @prop: the MonoProperty to act on.
9684 * Returns: The setter method of the property (A MonoMethod)
9687 mono_property_get_set_method (MonoProperty *prop)
9693 * mono_property_get_get_method
9694 * @prop: the MonoProperty to act on.
9696 * Returns: The setter method of the property (A MonoMethod)
9699 mono_property_get_get_method (MonoProperty *prop)
9705 * mono_property_get_parent:
9706 * @prop: the MonoProperty to act on.
9708 * Returns: The MonoClass where the property was defined.
9711 mono_property_get_parent (MonoProperty *prop)
9713 return prop->parent;
9717 * mono_property_get_flags:
9718 * @prop: the MonoProperty to act on.
9720 * The metadata flags for a property are encoded using the
9721 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9723 * Returns: The flags for the property.
9726 mono_property_get_flags (MonoProperty *prop)
9732 * mono_event_get_name:
9733 * @event: the MonoEvent to act on
9735 * Returns: The name of the event.
9738 mono_event_get_name (MonoEvent *event)
9744 * mono_event_get_add_method:
9745 * @event: The MonoEvent to act on.
9747 * Returns: The @add' method for the event (a MonoMethod).
9750 mono_event_get_add_method (MonoEvent *event)
9756 * mono_event_get_remove_method:
9757 * @event: The MonoEvent to act on.
9759 * Returns: The @remove method for the event (a MonoMethod).
9762 mono_event_get_remove_method (MonoEvent *event)
9764 return event->remove;
9768 * mono_event_get_raise_method:
9769 * @event: The MonoEvent to act on.
9771 * Returns: The @raise method for the event (a MonoMethod).
9774 mono_event_get_raise_method (MonoEvent *event)
9776 return event->raise;
9780 * mono_event_get_parent:
9781 * @event: the MonoEvent to act on.
9783 * Returns: The MonoClass where the event is defined.
9786 mono_event_get_parent (MonoEvent *event)
9788 return event->parent;
9792 * mono_event_get_flags
9793 * @event: the MonoEvent to act on.
9795 * The metadata flags for an event are encoded using the
9796 * EVENT_* constants. See the tabledefs.h file for details.
9798 * Returns: The flags for the event.
9801 mono_event_get_flags (MonoEvent *event)
9803 return event->attrs;
9807 * mono_class_get_method_from_name:
9808 * @klass: where to look for the method
9809 * @name: name of the method
9810 * @param_count: number of parameters. -1 for any number.
9812 * Obtains a MonoMethod with a given name and number of parameters.
9813 * It only works if there are no multiple signatures for any given method name.
9816 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9818 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9822 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9824 MonoMethod *res = NULL;
9827 /* Search directly in the metadata to avoid calling setup_methods () */
9828 for (i = 0; i < klass->method.count; ++i) {
9830 guint32 cols [MONO_METHOD_SIZE];
9832 MonoMethodSignature *sig;
9834 /* klass->method.first points into the methodptr table */
9835 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9837 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9838 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9840 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9843 if (param_count == -1) {
9847 sig = mono_method_signature_checked (method, &error);
9849 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9852 if (sig->param_count == param_count) {
9863 * mono_class_get_method_from_name_flags:
9864 * @klass: where to look for the method
9865 * @name_space: name of the method
9866 * @param_count: number of parameters. -1 for any number.
9867 * @flags: flags which must be set in the method
9869 * Obtains a MonoMethod with a given name and number of parameters.
9870 * It only works if there are no multiple signatures for any given method name.
9873 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9875 MonoMethod *res = NULL;
9878 mono_class_init (klass);
9880 if (klass->generic_class && !klass->methods) {
9881 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9884 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9885 if (!mono_error_ok (&error))
9886 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9891 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9892 mono_class_setup_methods (klass);
9894 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9895 See mono/tests/array_load_exception.il
9896 FIXME we should better report this error to the caller
9898 if (!klass->methods)
9900 for (i = 0; i < klass->method.count; ++i) {
9901 MonoMethod *method = klass->methods [i];
9903 if (method->name[0] == name [0] &&
9904 !strcmp (name, method->name) &&
9905 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9906 ((method->flags & flags) == flags)) {
9913 res = find_method_in_metadata (klass, name, param_count, flags);
9920 * mono_class_set_failure:
9921 * @klass: class in which the failure was detected
9922 * @ex_type: the kind of exception/error to be thrown (later)
9923 * @ex_data: exception data (specific to each type of exception/error)
9925 * Keep a detected failure informations in the class for later processing.
9926 * Note that only the first failure is kept.
9928 * LOCKING: Acquires the loader lock.
9931 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9933 if (mono_class_has_failure (klass))
9936 mono_loader_lock ();
9937 klass->exception_type = ex_type;
9939 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9940 mono_loader_unlock ();
9946 * mono_class_get_exception_data:
9948 * Return the exception_data property of KLASS.
9950 * LOCKING: Acquires the loader lock.
9953 mono_class_get_exception_data (MonoClass *klass)
9955 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9959 * mono_classes_init:
9961 * Initialize the resources used by this module.
9964 mono_classes_init (void)
9966 mono_os_mutex_init (&classes_mutex);
9968 mono_counters_register ("Inflated methods size",
9969 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9970 mono_counters_register ("Inflated classes",
9971 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9972 mono_counters_register ("Inflated classes size",
9973 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9974 mono_counters_register ("MonoClass size",
9975 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9976 mono_counters_register ("MonoClassExt size",
9977 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9981 * mono_classes_cleanup:
9983 * Free the resources used by this module.
9986 mono_classes_cleanup (void)
9988 if (global_interface_bitset)
9989 mono_bitset_free (global_interface_bitset);
9990 global_interface_bitset = NULL;
9991 mono_os_mutex_destroy (&classes_mutex);
9995 * mono_class_get_exception_for_failure:
9996 * @klass: class in which the failure was detected
9998 * Return a constructed MonoException than the caller can then throw
9999 * using mono_raise_exception - or NULL if no failure is present (or
10000 * doesn't result in an exception).
10003 mono_class_get_exception_for_failure (MonoClass *klass)
10005 gpointer exception_data = mono_class_get_exception_data (klass);
10007 switch (mono_class_get_failure(klass)) {
10008 case MONO_EXCEPTION_TYPE_LOAD: {
10011 char *str = mono_type_get_full_name (klass);
10012 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
10013 name = mono_string_new (mono_domain_get (), str);
10015 ex = mono_get_exception_type_load (name, astr);
10019 case MONO_EXCEPTION_MISSING_METHOD: {
10020 char *class_name = (char *)exception_data;
10021 char *assembly_name = class_name + strlen (class_name) + 1;
10023 return mono_get_exception_missing_method (class_name, assembly_name);
10025 case MONO_EXCEPTION_MISSING_FIELD: {
10026 char *class_name = (char *)exception_data;
10027 char *member_name = class_name + strlen (class_name) + 1;
10029 return mono_get_exception_missing_field (class_name, member_name);
10031 case MONO_EXCEPTION_FILE_NOT_FOUND: {
10032 char *msg_format = (char *)exception_data;
10033 char *assembly_name = msg_format + strlen (msg_format) + 1;
10034 char *msg = g_strdup_printf (msg_format, assembly_name);
10037 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10043 case MONO_EXCEPTION_BAD_IMAGE: {
10044 return mono_get_exception_bad_image_format ((const char *)exception_data);
10046 case MONO_EXCEPTION_INVALID_PROGRAM: {
10047 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10050 /* TODO - handle other class related failures */
10051 return mono_get_exception_execution_engine ("Unknown class failure");
10057 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10059 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10060 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10062 if (outer_klass == inner_klass)
10064 inner_klass = inner_klass->nested_in;
10065 } while (inner_klass);
10070 mono_class_get_generic_type_definition (MonoClass *klass)
10072 return klass->generic_class ? klass->generic_class->container_class : klass;
10076 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10078 * Generic instantiations are ignored for all super types of @klass.
10080 * Visibility checks ignoring generic instantiations.
10083 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10086 klass = mono_class_get_generic_type_definition (klass);
10087 parent = mono_class_get_generic_type_definition (parent);
10088 mono_class_setup_supertypes (klass);
10090 for (i = 0; i < klass->idepth; ++i) {
10091 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10097 * Subtype can only access parent members with family protection if the site object
10098 * is subclass of Subtype. For example:
10099 * class A { protected int x; }
10101 * void valid_access () {
10105 * void invalid_access () {
10112 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10114 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10117 if (context_klass == NULL)
10119 /*if access_klass is not member_klass context_klass must be type compat*/
10120 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10126 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10129 if (accessing == accessed)
10131 if (!accessed || !accessing)
10134 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10135 * anywhere so untrusted friends are not safe to access platform's code internals */
10136 if (mono_security_core_clr_enabled ()) {
10137 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10141 mono_assembly_load_friends (accessed);
10142 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10143 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10144 /* Be conservative with checks */
10145 if (!friend_->name)
10147 if (strcmp (accessing->aname.name, friend_->name))
10149 if (friend_->public_key_token [0]) {
10150 if (!accessing->aname.public_key_token [0])
10152 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10161 * If klass is a generic type or if it is derived from a generic type, return the
10162 * MonoClass of the generic definition
10163 * Returns NULL if not found
10166 get_generic_definition_class (MonoClass *klass)
10169 if (klass->generic_class && klass->generic_class->container_class)
10170 return klass->generic_class->container_class;
10171 klass = klass->parent;
10177 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10180 for (i = 0; i < ginst->type_argc; ++i) {
10181 MonoType *type = ginst->type_argv[i];
10182 switch (type->type) {
10183 case MONO_TYPE_SZARRAY:
10184 if (!can_access_type (access_klass, type->data.klass))
10187 case MONO_TYPE_ARRAY:
10188 if (!can_access_type (access_klass, type->data.array->eklass))
10191 case MONO_TYPE_PTR:
10192 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10195 case MONO_TYPE_CLASS:
10196 case MONO_TYPE_VALUETYPE:
10197 case MONO_TYPE_GENERICINST:
10198 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10208 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10212 if (access_klass == member_klass)
10215 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10218 if (access_klass->element_class && !access_klass->enumtype)
10219 access_klass = access_klass->element_class;
10221 if (member_klass->element_class && !member_klass->enumtype)
10222 member_klass = member_klass->element_class;
10224 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10226 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10229 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10232 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10235 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10238 /*Non nested type with nested visibility. We just fail it.*/
10239 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10242 switch (access_level) {
10243 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10244 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10246 case TYPE_ATTRIBUTE_PUBLIC:
10249 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10252 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10253 return is_nesting_type (member_klass, access_klass);
10255 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10256 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10258 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10259 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10261 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10262 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10263 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10265 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10266 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10267 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10272 /* FIXME: check visibility of type, too */
10274 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10276 MonoClass *member_generic_def;
10277 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10280 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10281 access_klass->generic_container) &&
10282 (member_generic_def = get_generic_definition_class (member_klass))) {
10283 MonoClass *access_container;
10285 if (access_klass->generic_container)
10286 access_container = access_klass;
10288 access_container = access_klass->generic_class->container_class;
10290 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10294 /* Partition I 8.5.3.2 */
10295 /* the access level values are the same for fields and methods */
10296 switch (access_level) {
10297 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10298 /* same compilation unit */
10299 return access_klass->image == member_klass->image;
10300 case FIELD_ATTRIBUTE_PRIVATE:
10301 return access_klass == member_klass;
10302 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10303 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10304 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10307 case FIELD_ATTRIBUTE_ASSEMBLY:
10308 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10309 case FIELD_ATTRIBUTE_FAMILY:
10310 if (is_valid_family_access (access_klass, member_klass, context_klass))
10313 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10314 if (is_valid_family_access (access_klass, member_klass, context_klass))
10316 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10317 case FIELD_ATTRIBUTE_PUBLIC:
10324 * mono_method_can_access_field:
10325 * @method: Method that will attempt to access the field
10326 * @field: the field to access
10328 * Used to determine if a method is allowed to access the specified field.
10330 * Returns: TRUE if the given @method is allowed to access the @field while following
10331 * the accessibility rules of the CLI.
10334 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10336 /* FIXME: check all overlapping fields */
10337 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10339 MonoClass *nested = method->klass->nested_in;
10341 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10344 nested = nested->nested_in;
10351 * mono_method_can_access_method:
10352 * @method: Method that will attempt to access the other method
10353 * @called: the method that we want to probe for accessibility.
10355 * Used to determine if the @method is allowed to access the specified @called method.
10357 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10358 * the accessibility rules of the CLI.
10361 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10363 method = mono_method_get_method_definition (method);
10364 called = mono_method_get_method_definition (called);
10365 return mono_method_can_access_method_full (method, called, NULL);
10369 * mono_method_can_access_method_full:
10370 * @method: The caller method
10371 * @called: The called method
10372 * @context_klass: The static type on stack of the owner @called object used
10374 * This function must be used with instance calls, as they have more strict family accessibility.
10375 * It can be used with static methods, but context_klass should be NULL.
10377 * Returns: TRUE if caller have proper visibility and acessibility to @called
10380 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10382 /* Wrappers are except from access checks */
10383 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10386 MonoClass *access_class = method->klass;
10387 MonoClass *member_class = called->klass;
10388 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10390 MonoClass *nested = access_class->nested_in;
10392 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10395 nested = nested->nested_in;
10402 can = can_access_type (access_class, member_class);
10404 MonoClass *nested = access_class->nested_in;
10406 can = can_access_type (nested, member_class);
10409 nested = nested->nested_in;
10416 if (called->is_inflated) {
10417 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10418 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10427 * mono_method_can_access_field_full:
10428 * @method: The caller method
10429 * @field: The accessed field
10430 * @context_klass: The static type on stack of the owner @field object used
10432 * This function must be used with instance fields, as they have more strict family accessibility.
10433 * It can be used with static fields, but context_klass should be NULL.
10435 * Returns: TRUE if caller have proper visibility and acessibility to @field
10438 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10440 MonoClass *access_class = method->klass;
10441 MonoClass *member_class = field->parent;
10442 /* FIXME: check all overlapping fields */
10443 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10445 MonoClass *nested = access_class->nested_in;
10447 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10450 nested = nested->nested_in;
10457 can = can_access_type (access_class, member_class);
10459 MonoClass *nested = access_class->nested_in;
10461 can = can_access_type (nested, member_class);
10464 nested = nested->nested_in;
10474 * mono_class_can_access_class:
10475 * @source_class: The source class
10476 * @target_class: The accessed class
10478 * This function returns is @target_class is visible to @source_class
10480 * Returns: TRUE if source have proper visibility and acessibility to target
10483 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10485 return can_access_type (source_class, target_class);
10489 * mono_type_is_valid_enum_basetype:
10490 * @type: The MonoType to check
10492 * Returns: TRUE if the type can be used as the basetype of an enum
10494 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10495 switch (type->type) {
10498 case MONO_TYPE_BOOLEAN:
10501 case MONO_TYPE_CHAR:
10515 * mono_class_is_valid_enum:
10516 * @klass: An enum class to be validated
10518 * This method verify the required properties an enum should have.
10520 * Returns: TRUE if the informed enum class is valid
10522 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10523 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10524 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10526 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10527 MonoClassField * field;
10528 gpointer iter = NULL;
10529 gboolean found_base_field = FALSE;
10531 g_assert (klass->enumtype);
10532 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10533 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10537 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10540 while ((field = mono_class_get_fields (klass, &iter))) {
10541 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10542 if (found_base_field)
10544 found_base_field = TRUE;
10545 if (!mono_type_is_valid_enum_basetype (field->type))
10550 if (!found_base_field)
10553 if (klass->method.count > 0)
10560 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10562 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10566 * mono_class_setup_interface_id:
10568 * Initializes MonoClass::interface_id if required.
10570 * LOCKING: Acquires the loader lock.
10573 mono_class_setup_interface_id (MonoClass *klass)
10575 mono_loader_lock ();
10576 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10577 klass->interface_id = mono_get_unique_iid (klass);
10578 mono_loader_unlock ();
10582 * mono_class_alloc_ext:
10584 * Allocate klass->ext if not already done.
10587 mono_class_alloc_ext (MonoClass *klass)
10594 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10595 mono_image_lock (klass->image);
10596 mono_memory_barrier ();
10599 class_ext_size += sizeof (MonoClassExt);
10600 mono_image_unlock (klass->image);
10604 * mono_class_setup_interfaces:
10606 * Initialize klass->interfaces/interfaces_count.
10607 * LOCKING: Acquires the loader lock.
10608 * This function can fail the type.
10611 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10613 int i, interface_count;
10614 MonoClass **interfaces;
10616 mono_error_init (error);
10618 if (klass->interfaces_inited)
10621 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10622 MonoType *args [1];
10624 /* generic IList, ICollection, IEnumerable */
10625 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10626 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10628 args [0] = &klass->element_class->byval_arg;
10629 interfaces [0] = mono_class_bind_generic_parameters (
10630 mono_defaults.generic_ilist_class, 1, args, FALSE);
10631 if (interface_count > 1)
10632 interfaces [1] = mono_class_bind_generic_parameters (
10633 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10634 } else if (klass->generic_class) {
10635 MonoClass *gklass = klass->generic_class->container_class;
10637 mono_class_setup_interfaces (gklass, error);
10638 if (!mono_error_ok (error)) {
10639 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10643 interface_count = gklass->interface_count;
10644 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10645 for (i = 0; i < interface_count; i++) {
10646 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10647 if (!mono_error_ok (error)) {
10648 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10653 interface_count = 0;
10657 mono_image_lock (klass->image);
10659 if (!klass->interfaces_inited) {
10660 klass->interface_count = interface_count;
10661 klass->interfaces = interfaces;
10663 mono_memory_barrier ();
10665 klass->interfaces_inited = TRUE;
10668 mono_image_unlock (klass->image);
10672 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10674 MonoClass *klass = field->parent;
10675 MonoImage *image = klass->image;
10676 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10677 int field_idx = field - klass->fields;
10679 mono_error_init (error);
10682 MonoClassField *gfield = >d->fields [field_idx];
10683 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10684 if (!mono_error_ok (error)) {
10685 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10686 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10689 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10690 if (!mono_error_ok (error)) {
10691 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10692 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10696 guint32 cols [MONO_FIELD_SIZE];
10697 MonoGenericContainer *container = NULL;
10698 int idx = klass->field.first + field_idx;
10700 /*FIXME, in theory we do not lazy load SRE fields*/
10701 g_assert (!image_is_dynamic (image));
10703 if (klass->generic_container) {
10704 container = klass->generic_container;
10706 container = gtd->generic_container;
10707 g_assert (container);
10710 /* klass->field.first and idx points into the fieldptr table */
10711 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10713 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10714 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10715 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10719 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10721 mono_metadata_decode_value (sig, &sig);
10722 /* FIELD signature == 0x06 */
10723 g_assert (*sig == 0x06);
10725 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10726 if (!field->type) {
10727 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10728 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10734 mono_field_resolve_flags (MonoClassField *field)
10736 MonoClass *klass = field->parent;
10737 MonoImage *image = klass->image;
10738 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10739 int field_idx = field - klass->fields;
10743 MonoClassField *gfield = >d->fields [field_idx];
10744 return mono_field_get_flags (gfield);
10746 int idx = klass->field.first + field_idx;
10748 /*FIXME, in theory we do not lazy load SRE fields*/
10749 g_assert (!image_is_dynamic (image));
10751 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10756 * mono_class_setup_basic_field_info:
10757 * @class: The class to initialize
10759 * Initializes the klass->fields array of fields.
10760 * Aquires the loader lock.
10763 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10765 mono_loader_lock ();
10766 mono_class_setup_basic_field_info (klass);
10767 mono_loader_unlock ();
10771 * mono_class_get_fields_lazy:
10772 * @klass: the MonoClass to act on
10774 * This routine is an iterator routine for retrieving the fields in a class.
10775 * Only minimal information about fields are loaded. Accessors must be used
10776 * for all MonoClassField returned.
10778 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10779 * iterate over all of the elements. When no more values are
10780 * available, the return value is NULL.
10782 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10785 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10787 MonoClassField* field;
10791 mono_class_setup_basic_field_info_locking (klass);
10792 if (!klass->fields)
10794 /* start from the first */
10795 if (klass->field.count) {
10796 *iter = &klass->fields [0];
10797 return (MonoClassField *)*iter;
10803 field = (MonoClassField *)*iter;
10805 if (field < &klass->fields [klass->field.count]) {
10807 return (MonoClassField *)*iter;
10813 mono_class_full_name (MonoClass *klass)
10815 return mono_type_full_name (&klass->byval_arg);
10818 /* Declare all shared lazy type lookup functions */
10819 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)