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)
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/profiler-private.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/reflection.h>
32 #include <mono/metadata/exception.h>
33 #include <mono/metadata/security-manager.h>
34 #include <mono/metadata/security-core-clr.h>
35 #include <mono/metadata/attrdefs.h>
36 #include <mono/metadata/gc-internals.h>
37 #include <mono/metadata/verify-internals.h>
38 #include <mono/metadata/mono-debug.h>
39 #include <mono/utils/mono-counters.h>
40 #include <mono/utils/mono-string.h>
41 #include <mono/utils/mono-error-internals.h>
42 #include <mono/utils/mono-logger-internals.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
46 #include <mono/utils/checked-build.h>
50 gboolean mono_print_vtable = FALSE;
51 gboolean mono_align_small_structs = FALSE;
54 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
55 guint32 classes_size, class_ext_size;
57 /* Low level lock which protects data structures in this module */
58 static mono_mutex_t classes_mutex;
60 /* Function supplied by the runtime to find classes by name using information from the AOT file */
61 static MonoGetClassFromName get_class_from_name = NULL;
63 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
64 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
65 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
66 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
67 static int generic_array_methods (MonoClass *klass);
68 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
70 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
71 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
72 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
73 static guint32 mono_field_resolve_flags (MonoClassField *field);
74 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
75 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
78 We use gclass recording to allow recursive system f types to be referenced by a parent.
80 Given the following type hierarchy:
82 class TextBox : TextBoxBase<TextBox> {}
83 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
84 class TextInput<T> : Input<T> where T: TextInput<T> {}
87 The runtime tries to load TextBoxBase<>.
88 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
89 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
90 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
92 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
93 at this point, iow, both are registered in the type map and both and a NULL parent. This means
94 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
96 To fix that what we do is to record all generic instantes created while resolving the parent of
97 any generic type definition and, after resolved, correct the parent field if needed.
100 static int record_gclass_instantiation;
101 static GSList *gclass_recorded_list;
102 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
107 mono_locks_os_acquire (&classes_mutex, ClassesLock);
111 classes_unlock (void)
113 mono_locks_os_release (&classes_mutex, ClassesLock);
117 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
120 enable_gclass_recording (void)
122 ++record_gclass_instantiation;
126 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
129 disable_gclass_recording (gclass_record_func func, void *user_data)
131 GSList **head = &gclass_recorded_list;
133 g_assert (record_gclass_instantiation > 0);
134 --record_gclass_instantiation;
137 GSList *node = *head;
138 if (func ((MonoClass*)node->data, user_data)) {
140 g_slist_free_1 (node);
146 /* We automatically discard all recorded gclasses when disabled. */
147 if (!record_gclass_instantiation && gclass_recorded_list) {
148 g_slist_free (gclass_recorded_list);
149 gclass_recorded_list = NULL;
154 * mono_class_from_typeref:
155 * @image: a MonoImage
156 * @type_token: a TypeRef token
158 * Creates the MonoClass* structure representing the type defined by
159 * the typeref token valid inside @image.
160 * Returns: the MonoClass* representing the typeref token, NULL ifcould
164 mono_class_from_typeref (MonoImage *image, guint32 type_token)
167 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
168 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
173 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
175 guint32 cols [MONO_TYPEREF_SIZE];
176 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
178 const char *name, *nspace;
179 MonoClass *res = NULL;
182 mono_error_init (error);
184 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
187 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
189 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
190 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
192 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
193 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
194 case MONO_RESOLUTION_SCOPE_MODULE:
196 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
197 This is not the observed behavior of existing implementations.
198 The defacto behavior is that it's just a typedef in disguise.
200 /* a typedef in disguise */
201 res = mono_class_from_name_checked (image, nspace, name, error);
204 case MONO_RESOLUTION_SCOPE_MODULEREF:
205 module = mono_image_load_module (image, idx);
207 res = mono_class_from_name_checked (module, nspace, name, error);
210 case MONO_RESOLUTION_SCOPE_TYPEREF: {
211 MonoClass *enclosing;
214 if (idx == mono_metadata_token_index (type_token)) {
215 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
219 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
220 if (!mono_error_ok (error))
223 if (enclosing->nested_classes_inited && enclosing->ext) {
224 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
225 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
226 res = (MonoClass *)tmp->data;
227 if (strcmp (res->name, name) == 0)
231 /* Don't call mono_class_init as we might've been called by it recursively */
232 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
234 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
235 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
236 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
238 if (strcmp (nname, name) == 0)
239 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
241 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
244 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
247 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
251 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
252 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
256 if (!image->references || !image->references [idx - 1])
257 mono_assembly_load_reference (image, idx - 1);
258 g_assert (image->references [idx - 1]);
260 /* If the assembly did not load, register this as a type load exception */
261 if (image->references [idx - 1] == REFERENCE_MISSING){
262 MonoAssemblyName aname;
265 mono_assembly_get_assemblyref (image, idx - 1, &aname);
266 human_name = mono_stringify_assembly_name (&aname);
267 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
271 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
274 /* Generic case, should be avoided for when a better error is possible. */
275 if (!res && mono_error_ok (error)) {
276 if (mono_loader_get_last_error ()) { /*FIXME plug the above to not leak errors*/
277 mono_error_set_from_loader_error (error);
279 char *name = mono_class_name_from_token (image, type_token);
280 char *assembly = mono_assembly_name_from_token (image, type_token);
281 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
284 mono_loader_assert_no_error ();
290 mono_image_memdup (MonoImage *image, void *data, guint size)
292 void *res = mono_image_alloc (image, size);
293 memcpy (res, data, size);
297 /* Copy everything mono_metadata_free_array free. */
299 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
302 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
304 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
306 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
308 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
310 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
312 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
317 /* Copy everything mono_metadata_free_method_signature free. */
319 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
323 sig = mono_metadata_signature_dup_full (image, sig);
325 sig->ret = mono_metadata_type_dup (image, sig->ret);
326 for (i = 0; i < sig->param_count; ++i)
327 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
333 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
335 MonoAssembly *ta = klass->image->assembly;
338 name = mono_stringify_assembly_name (&ta->aname);
339 g_string_append_printf (str, ", %s", name);
344 mono_type_name_check_byref (MonoType *type, GString *str)
347 g_string_append_c (str, '&');
351 * mono_identifier_escape_type_name_chars:
352 * @str: a destination string
353 * @identifier: an IDENTIFIER in internal form
357 * The displayed form of the identifier is appended to str.
359 * The displayed form of an identifier has the characters ,+&*[]\
360 * that have special meaning in type names escaped with a preceeding
361 * backslash (\) character.
364 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
370 // reserve space for common case: there will be no escaped characters.
371 g_string_set_size(str, n + strlen(identifier));
372 g_string_set_size(str, n);
374 for (const char* s = identifier; *s != 0 ; s++) {
383 g_string_append_c (str, '\\');
384 g_string_append_c (str, *s);
387 g_string_append_c (str, *s);
395 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
396 MonoTypeNameFormat format)
400 switch (type->type) {
401 case MONO_TYPE_ARRAY: {
402 int i, rank = type->data.array->rank;
403 MonoTypeNameFormat nested_format;
405 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
406 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
408 mono_type_get_name_recurse (
409 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
410 g_string_append_c (str, '[');
412 g_string_append_c (str, '*');
413 for (i = 1; i < rank; i++)
414 g_string_append_c (str, ',');
415 g_string_append_c (str, ']');
417 mono_type_name_check_byref (type, str);
419 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
420 _mono_type_get_assembly_name (type->data.array->eklass, str);
423 case MONO_TYPE_SZARRAY: {
424 MonoTypeNameFormat nested_format;
426 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
427 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
429 mono_type_get_name_recurse (
430 &type->data.klass->byval_arg, str, FALSE, nested_format);
431 g_string_append (str, "[]");
433 mono_type_name_check_byref (type, str);
435 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
436 _mono_type_get_assembly_name (type->data.klass, str);
439 case MONO_TYPE_PTR: {
440 MonoTypeNameFormat nested_format;
442 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
443 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
445 mono_type_get_name_recurse (
446 type->data.type, str, FALSE, nested_format);
447 g_string_append_c (str, '*');
449 mono_type_name_check_byref (type, str);
451 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
452 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
457 if (!mono_generic_param_info (type->data.generic_param))
458 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
460 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
462 mono_type_name_check_byref (type, str);
466 klass = mono_class_from_mono_type (type);
467 if (klass->nested_in) {
468 mono_type_get_name_recurse (
469 &klass->nested_in->byval_arg, str, TRUE, format);
470 if (format == MONO_TYPE_NAME_FORMAT_IL)
471 g_string_append_c (str, '.');
473 g_string_append_c (str, '+');
474 } else if (*klass->name_space) {
475 if (format == MONO_TYPE_NAME_FORMAT_IL)
476 g_string_append (str, klass->name_space);
478 mono_identifier_escape_type_name_chars (str, klass->name_space);
479 g_string_append_c (str, '.');
481 if (format == MONO_TYPE_NAME_FORMAT_IL) {
482 char *s = strchr (klass->name, '`');
483 int len = s ? s - klass->name : strlen (klass->name);
484 g_string_append_len (str, klass->name, len);
486 mono_identifier_escape_type_name_chars (str, klass->name);
490 if (klass->generic_class) {
491 MonoGenericClass *gclass = klass->generic_class;
492 MonoGenericInst *inst = gclass->context.class_inst;
493 MonoTypeNameFormat nested_format;
496 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
497 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
499 if (format == MONO_TYPE_NAME_FORMAT_IL)
500 g_string_append_c (str, '<');
502 g_string_append_c (str, '[');
503 for (i = 0; i < inst->type_argc; i++) {
504 MonoType *t = inst->type_argv [i];
507 g_string_append_c (str, ',');
508 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
509 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
510 g_string_append_c (str, '[');
511 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
512 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
513 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
514 g_string_append_c (str, ']');
516 if (format == MONO_TYPE_NAME_FORMAT_IL)
517 g_string_append_c (str, '>');
519 g_string_append_c (str, ']');
520 } else if (klass->generic_container &&
521 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
522 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
525 if (format == MONO_TYPE_NAME_FORMAT_IL)
526 g_string_append_c (str, '<');
528 g_string_append_c (str, '[');
529 for (i = 0; i < klass->generic_container->type_argc; i++) {
531 g_string_append_c (str, ',');
532 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
534 if (format == MONO_TYPE_NAME_FORMAT_IL)
535 g_string_append_c (str, '>');
537 g_string_append_c (str, ']');
540 mono_type_name_check_byref (type, str);
542 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
543 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
544 _mono_type_get_assembly_name (klass, str);
550 * mono_type_get_name_full:
552 * @format: the format for the return string.
555 * Returns: the string representation in a number of formats:
557 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
558 * returned in the formatrequired by System.Reflection, this is the
559 * inverse of mono_reflection_parse_type ().
561 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
562 * be used by the IL assembler.
564 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
566 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
569 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
573 result = g_string_new ("");
575 mono_type_get_name_recurse (type, result, FALSE, format);
577 return g_string_free (result, FALSE);
581 * mono_type_get_full_name:
584 * Returns: the string representation for type as required by System.Reflection.
585 * The inverse of mono_reflection_parse_type ().
588 mono_type_get_full_name (MonoClass *klass)
590 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
594 * mono_type_get_name:
597 * Returns: the string representation for type as it would be represented in IL code.
600 mono_type_get_name (MonoType *type)
602 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
606 * mono_type_get_underlying_type:
609 * Returns: the MonoType for the underlying integer type if @type
610 * is an enum and byref is false, otherwise the type itself.
613 mono_type_get_underlying_type (MonoType *type)
615 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
616 return mono_class_enum_basetype (type->data.klass);
617 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
618 return mono_class_enum_basetype (type->data.generic_class->container_class);
623 * mono_class_is_open_constructed_type:
626 * Returns TRUE if type represents a generics open constructed type.
627 * IOW, not all type parameters required for the instantiation have
628 * been provided or it's a generic type definition.
630 * An open constructed type means it's a non realizable type. Not to
631 * be mixed up with an abstract type - we can't cast or dispatch to
632 * an open type, for example.
635 mono_class_is_open_constructed_type (MonoType *t)
641 case MONO_TYPE_SZARRAY:
642 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
643 case MONO_TYPE_ARRAY:
644 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
646 return mono_class_is_open_constructed_type (t->data.type);
647 case MONO_TYPE_GENERICINST:
648 return t->data.generic_class->context.class_inst->is_open;
649 case MONO_TYPE_CLASS:
650 case MONO_TYPE_VALUETYPE:
651 return t->data.klass->generic_container != NULL;
658 This is a simple function to catch the most common bad instances of generic types.
659 Specially those that might lead to further failures in the runtime.
662 is_valid_generic_argument (MonoType *type)
664 switch (type->type) {
666 //case MONO_TYPE_TYPEDBYREF:
674 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
676 mono_error_init (error);
678 switch (type->type) {
679 case MONO_TYPE_MVAR: {
681 int num = mono_type_get_generic_param_num (type);
682 MonoGenericInst *inst = context->method_inst;
685 if (num >= inst->type_argc) {
686 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
687 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
688 num, info ? info->name : "", inst->type_argc);
692 if (!is_valid_generic_argument (inst->type_argv [num])) {
693 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
694 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
695 num, info ? info->name : "", inst->type_argv [num]->type);
699 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
700 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
701 * ->byref and ->attrs from @type are propagated to the returned type.
703 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
704 nt->byref = type->byref;
705 nt->attrs = type->attrs;
708 case MONO_TYPE_VAR: {
710 int num = mono_type_get_generic_param_num (type);
711 MonoGenericInst *inst = context->class_inst;
714 if (num >= inst->type_argc) {
715 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
716 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
717 num, info ? info->name : "", inst->type_argc);
720 if (!is_valid_generic_argument (inst->type_argv [num])) {
721 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
722 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
723 num, info ? info->name : "", inst->type_argv [num]->type);
726 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
727 nt->byref = type->byref;
728 nt->attrs = type->attrs;
731 case MONO_TYPE_SZARRAY: {
732 MonoClass *eclass = type->data.klass;
733 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
734 if (!inflated || !mono_error_ok (error))
736 nt = mono_metadata_type_dup (image, type);
737 nt->data.klass = mono_class_from_mono_type (inflated);
738 mono_metadata_free_type (inflated);
741 case MONO_TYPE_ARRAY: {
742 MonoClass *eclass = type->data.array->eklass;
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.array->eklass = mono_class_from_mono_type (inflated);
748 mono_metadata_free_type (inflated);
751 case MONO_TYPE_GENERICINST: {
752 MonoGenericClass *gclass = type->data.generic_class;
753 MonoGenericInst *inst;
755 if (!gclass->context.class_inst->is_open)
758 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
759 if (!mono_error_ok (error))
761 if (inst != gclass->context.class_inst)
762 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
764 if (gclass == type->data.generic_class)
767 nt = mono_metadata_type_dup (image, type);
768 nt->data.generic_class = gclass;
771 case MONO_TYPE_CLASS:
772 case MONO_TYPE_VALUETYPE: {
773 MonoClass *klass = type->data.klass;
774 MonoGenericContainer *container = klass->generic_container;
775 MonoGenericInst *inst;
776 MonoGenericClass *gclass = NULL;
782 /* We can't use context->class_inst directly, since it can have more elements */
783 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
784 if (!mono_error_ok (error))
786 if (inst == container->context.class_inst)
789 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
791 nt = mono_metadata_type_dup (image, type);
792 nt->type = MONO_TYPE_GENERICINST;
793 nt->data.generic_class = gclass;
803 mono_generic_class_get_context (MonoGenericClass *gclass)
805 return &gclass->context;
809 mono_class_get_context (MonoClass *klass)
811 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
815 * mono_class_get_generic_container:
817 * Return the generic container of KLASS which should be a generic type definition.
819 MonoGenericContainer*
820 mono_class_get_generic_container (MonoClass *klass)
822 g_assert (klass->is_generic);
824 return klass->generic_container;
828 * mono_class_get_generic_class:
830 * Return the MonoGenericClass of KLASS, which should be a generic instance.
833 mono_class_get_generic_class (MonoClass *klass)
835 g_assert (klass->is_inflated);
837 return klass->generic_class;
841 * mono_class_inflate_generic_type_with_mempool:
842 * @mempool: a mempool
844 * @context: a generics context
845 * @error: error context
847 * The same as mono_class_inflate_generic_type, but allocates the MonoType
848 * from mempool if it is non-NULL. If it is NULL, the MonoType is
849 * allocated on the heap and is owned by the caller.
850 * The returned type can potentially be the same as TYPE, so it should not be
851 * modified by the caller, and it should be freed using mono_metadata_free_type ().
854 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
856 MonoType *inflated = NULL;
857 mono_error_init (error);
860 inflated = inflate_generic_type (image, type, context, error);
861 if (!mono_error_ok (error))
865 MonoType *shared = mono_metadata_get_shared_type (type);
870 return mono_metadata_type_dup (image, type);
874 mono_stats.inflated_type_count++;
879 * mono_class_inflate_generic_type:
881 * @context: a generics context
883 * If @type is a generic type and @context is not NULL, instantiate it using the
884 * generics context @context.
886 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
887 * on the heap and is owned by the caller. Returns NULL on error.
889 * @deprecated Please use mono_class_inflate_generic_type_checked instead
892 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
896 result = mono_class_inflate_generic_type_checked (type, context, &error);
898 if (!mono_error_ok (&error)) {
899 mono_error_cleanup (&error);
906 * mono_class_inflate_generic_type:
908 * @context: a generics context
909 * @error: error context to use
911 * If @type is a generic type and @context is not NULL, instantiate it using the
912 * generics context @context.
914 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
915 * on the heap and is owned by the caller.
918 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
920 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
924 * mono_class_inflate_generic_type_no_copy:
926 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
930 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
932 MonoType *inflated = NULL;
934 mono_error_init (error);
936 inflated = inflate_generic_type (image, type, context, error);
937 if (!mono_error_ok (error))
944 mono_stats.inflated_type_count++;
949 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
954 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
955 if (!mono_error_ok (error))
958 res = mono_class_from_mono_type (inflated);
959 mono_metadata_free_type (inflated);
964 * mono_class_inflate_generic_class:
966 * Inflate the class GKLASS with CONTEXT.
969 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
974 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
975 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
982 static MonoGenericContext
983 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
985 MonoGenericInst *class_inst = NULL;
986 MonoGenericInst *method_inst = NULL;
987 MonoGenericContext res = { NULL, NULL };
989 mono_error_init (error);
991 if (context->class_inst) {
992 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
993 if (!mono_error_ok (error))
997 if (context->method_inst) {
998 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
999 if (!mono_error_ok (error))
1003 res.class_inst = class_inst;
1004 res.method_inst = method_inst;
1010 * mono_class_inflate_generic_method:
1011 * @method: a generic method
1012 * @context: a generics context
1014 * Instantiate the generic method @method using the generics context @context.
1016 * Returns: the new instantiated method
1019 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1021 return mono_class_inflate_generic_method_full (method, NULL, context);
1025 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1027 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1031 * mono_class_inflate_generic_method_full:
1033 * Instantiate method @method with the generic context @context.
1034 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1035 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1038 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1041 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1042 if (!mono_error_ok (&error))
1043 /*FIXME do proper error handling - on this case, kill this function. */
1044 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1050 * mono_class_inflate_generic_method_full_checked:
1051 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1054 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1057 MonoMethodInflated *iresult, *cached;
1058 MonoMethodSignature *sig;
1059 MonoGenericContext tmp_context;
1061 mono_error_init (error);
1063 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1064 while (method->is_inflated) {
1065 MonoGenericContext *method_context = mono_method_get_context (method);
1066 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1068 tmp_context = inflate_generic_context (method_context, context, error);
1069 if (!mono_error_ok (error))
1071 context = &tmp_context;
1073 if (mono_metadata_generic_context_equal (method_context, context))
1076 method = imethod->declaring;
1080 * A method only needs to be inflated if the context has argument for which it is
1083 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1084 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1087 if (!((method->is_generic && context->method_inst) ||
1088 (method->klass->generic_container && context->class_inst)))
1091 iresult = g_new0 (MonoMethodInflated, 1);
1092 iresult->context = *context;
1093 iresult->declaring = method;
1095 if (!context->method_inst && method->is_generic)
1096 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1098 if (!context->class_inst) {
1099 g_assert (!iresult->declaring->klass->generic_class);
1100 if (iresult->declaring->klass->generic_container)
1101 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1102 else if (iresult->declaring->klass->generic_class)
1103 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1105 /* This can happen with some callers like mono_object_get_virtual_method () */
1106 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1107 iresult->context.class_inst = NULL;
1109 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1112 mono_image_set_lock (set);
1113 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1114 mono_image_set_unlock (set);
1118 return (MonoMethod*)cached;
1121 mono_stats.inflated_method_count++;
1123 inflated_methods_size += sizeof (MonoMethodInflated);
1125 sig = mono_method_signature (method);
1127 char *name = mono_type_get_full_name (method->klass);
1128 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1134 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1136 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1139 result = (MonoMethod *) iresult;
1140 result->is_inflated = TRUE;
1141 result->is_generic = FALSE;
1142 result->sre_method = FALSE;
1143 result->signature = NULL;
1145 if (!context->method_inst) {
1146 /* Set the generic_container of the result to the generic_container of method */
1147 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1149 if (generic_container) {
1150 result->is_generic = 1;
1151 mono_method_set_generic_container (result, generic_container);
1155 if (!klass_hint || !klass_hint->generic_class ||
1156 klass_hint->generic_class->container_class != method->klass ||
1157 klass_hint->generic_class->context.class_inst != context->class_inst)
1160 if (method->klass->generic_container)
1161 result->klass = klass_hint;
1163 if (!result->klass) {
1164 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1165 if (!mono_error_ok (error))
1168 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1170 mono_metadata_free_type (inflated);
1174 * FIXME: This should hold, but it doesn't:
1176 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1177 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1178 * g_assert (result->is_generic);
1181 * Fixing this here causes other things to break, hence a very
1182 * ugly hack in mini-trampolines.c - see
1183 * is_generic_method_definition().
1187 mono_image_set_lock (set);
1188 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1190 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1191 iresult->owner = set;
1194 mono_image_set_unlock (set);
1196 return (MonoMethod*)cached;
1204 * mono_get_inflated_method:
1206 * Obsolete. We keep it around since it's mentioned in the public API.
1209 mono_get_inflated_method (MonoMethod *method)
1215 * mono_method_get_context_general:
1217 * @uninflated: handle uninflated methods?
1219 * Returns the generic context of a method or NULL if it doesn't have
1220 * one. For an inflated method that's the context stored in the
1221 * method. Otherwise it's in the method's generic container or in the
1222 * generic container of the method's class.
1225 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1227 if (method->is_inflated) {
1228 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1229 return &imethod->context;
1233 if (method->is_generic)
1234 return &(mono_method_get_generic_container (method)->context);
1235 if (method->klass->generic_container)
1236 return &method->klass->generic_container->context;
1241 * mono_method_get_context:
1244 * Returns the generic context for method if it's inflated, otherwise
1248 mono_method_get_context (MonoMethod *method)
1250 return mono_method_get_context_general (method, FALSE);
1254 * mono_method_get_generic_container:
1256 * Returns the generic container of METHOD, which should be a generic method definition.
1257 * Returns NULL if METHOD is not a generic method definition.
1258 * LOCKING: Acquires the loader lock.
1260 MonoGenericContainer*
1261 mono_method_get_generic_container (MonoMethod *method)
1263 MonoGenericContainer *container;
1265 if (!method->is_generic)
1268 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1269 g_assert (container);
1275 * mono_method_set_generic_container:
1277 * Sets the generic container of METHOD to CONTAINER.
1278 * LOCKING: Acquires the image lock.
1281 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1283 g_assert (method->is_generic);
1285 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1289 * mono_class_find_enum_basetype:
1290 * @class: The enum class
1292 * Determine the basetype of an enum by iterating through its fields. We do this
1293 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1296 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1298 MonoGenericContainer *container = NULL;
1299 MonoImage *m = klass->image;
1300 const int top = klass->field.count;
1303 g_assert (klass->enumtype);
1305 mono_error_init (error);
1307 if (klass->generic_container)
1308 container = klass->generic_container;
1309 else if (klass->generic_class) {
1310 MonoClass *gklass = klass->generic_class->container_class;
1312 container = gklass->generic_container;
1313 g_assert (container);
1317 * Fetch all the field information.
1319 for (i = 0; i < top; i++){
1321 guint32 cols [MONO_FIELD_SIZE];
1322 int idx = klass->field.first + i;
1325 /* klass->field.first and idx points into the fieldptr table */
1326 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1328 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1331 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1332 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1336 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1337 mono_metadata_decode_value (sig, &sig);
1338 /* FIELD signature == 0x06 */
1340 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1344 ftype = mono_metadata_parse_type_full (m, container, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1346 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1347 mono_error_set_from_loader_error (error);
1349 mono_error_set_bad_image (error, klass->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1352 if (klass->generic_class) {
1353 //FIXME do we leak here?
1354 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1355 if (!mono_error_ok (error))
1357 ftype->attrs = cols [MONO_FIELD_FLAGS];
1362 mono_error_set_type_load_class (error, klass, "Could not find base type");
1365 mono_loader_assert_no_error ();
1370 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1373 mono_type_has_exceptions (MonoType *type)
1375 switch (type->type) {
1376 case MONO_TYPE_CLASS:
1377 case MONO_TYPE_VALUETYPE:
1378 case MONO_TYPE_SZARRAY:
1379 return type->data.klass->exception_type;
1380 case MONO_TYPE_ARRAY:
1381 return type->data.array->eklass->exception_type;
1382 case MONO_TYPE_GENERICINST:
1383 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1392 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1396 mono_class_alloc (MonoClass *klass, int size)
1398 if (klass->generic_class)
1399 return mono_image_set_alloc (klass->generic_class->owner, size);
1401 return mono_image_alloc (klass->image, size);
1405 mono_class_alloc0 (MonoClass *klass, int size)
1409 res = mono_class_alloc (klass, size);
1410 memset (res, 0, size);
1414 #define mono_class_new0(klass,struct_type, n_structs) \
1415 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1418 * mono_class_setup_basic_field_info:
1419 * @class: The class to initialize
1421 * Initializes the klass->fields.
1422 * LOCKING: Assumes the loader lock is held.
1425 mono_class_setup_basic_field_info (MonoClass *klass)
1427 MonoClassField *field;
1435 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1436 image = klass->image;
1437 top = klass->field.count;
1439 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1441 * This happens when a generic instance of an unfinished generic typebuilder
1442 * is used as an element type for creating an array type. We can't initialize
1443 * the fields of this class using the fields of gklass, since gklass is not
1444 * finished yet, fields could be added to it later.
1450 mono_class_setup_basic_field_info (gtd);
1452 top = gtd->field.count;
1453 klass->field.first = gtd->field.first;
1454 klass->field.count = gtd->field.count;
1457 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1460 * Fetch all the field information.
1462 for (i = 0; i < top; i++){
1463 field = &klass->fields [i];
1464 field->parent = klass;
1467 field->name = mono_field_get_name (>d->fields [i]);
1469 int idx = klass->field.first + i;
1470 /* klass->field.first and idx points into the fieldptr table */
1471 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1472 /* The name is needed for fieldrefs */
1473 field->name = mono_metadata_string_heap (image, name_idx);
1479 * mono_class_setup_fields:
1480 * @class: The class to initialize
1482 * Initializes the klass->fields.
1483 * LOCKING: Assumes the loader lock is held.
1486 mono_class_setup_fields (MonoClass *klass)
1489 MonoImage *m = klass->image;
1491 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1492 int i, blittable = TRUE;
1493 guint32 real_size = 0;
1494 guint32 packing_size = 0;
1495 gboolean explicit_size;
1496 MonoClassField *field;
1497 MonoGenericContainer *container = NULL;
1498 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1501 * FIXME: We have a race condition here. It's possible that this function returns
1502 * to its caller with `instance_size` set to `0` instead of the actual size. This
1503 * is not a problem when the function is called recursively on the same class,
1504 * because the size will be initialized by the outer invocation. What follows is a
1505 * description of how it can occur in other cases, too. There it is a problem,
1506 * because it can lead to the GC being asked to allocate an object of size `0`,
1507 * which SGen chokes on. The race condition is triggered infrequently by
1508 * `tests/sgen-suspend.cs`.
1510 * This function is called for a class whenever one of its subclasses is inited.
1511 * For example, it's called for every subclass of Object. What it does is this:
1513 * if (klass->setup_fields_called)
1516 * klass->instance_size = 0;
1518 * klass->setup_fields_called = 1;
1519 * ... critical point
1520 * klass->instance_size = actual_instance_size;
1522 * The last two steps are sometimes reversed, but that only changes the way in which
1523 * the race condition works.
1525 * Assume thread A goes through this function and makes it to the critical point.
1526 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1527 * immediately, but `instance_size` is incorrect.
1529 * The other case looks like this:
1531 * if (klass->setup_fields_called)
1533 * ... critical point X
1534 * klass->instance_size = 0;
1535 * ... critical point Y
1536 * klass->instance_size = actual_instance_size;
1538 * klass->setup_fields_called = 1;
1540 * Assume thread A goes through the function and makes it to critical point X. Now
1541 * thread B runs through the whole of the function, returning, assuming
1542 * `instance_size` is set. At that point thread A gets to run and makes it to
1543 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1546 if (klass->setup_fields_called)
1549 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1551 * This happens when a generic instance of an unfinished generic typebuilder
1552 * is used as an element type for creating an array type. We can't initialize
1553 * the fields of this class using the fields of gklass, since gklass is not
1554 * finished yet, fields could be added to it later.
1559 mono_class_setup_basic_field_info (klass);
1560 top = klass->field.count;
1563 mono_class_setup_fields (gtd);
1564 if (gtd->exception_type) {
1565 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1570 klass->instance_size = 0;
1572 klass->sizes.class_size = 0;
1574 if (klass->parent) {
1575 /* For generic instances, klass->parent might not have been initialized */
1576 mono_class_init (klass->parent);
1577 if (!klass->parent->size_inited) {
1578 mono_class_setup_fields (klass->parent);
1579 if (klass->parent->exception_type) {
1580 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1584 klass->instance_size += klass->parent->instance_size;
1585 klass->min_align = klass->parent->min_align;
1586 /* we use |= since it may have been set already */
1587 klass->has_references |= klass->parent->has_references;
1588 blittable = klass->parent->blittable;
1590 klass->instance_size = sizeof (MonoObject);
1591 klass->min_align = 1;
1594 /* We can't really enable 16 bytes alignment until the GC supports it.
1595 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1596 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1597 Bug #506144 is an example of this issue.
1599 if (klass->simd_type)
1600 klass->min_align = 16;
1602 /* Get the real size */
1603 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1605 if (explicit_size) {
1606 if ((packing_size & 0xffffff00) != 0) {
1607 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1608 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1611 klass->packing_size = packing_size;
1612 real_size += klass->instance_size;
1616 if (explicit_size && real_size) {
1617 klass->instance_size = MAX (real_size, klass->instance_size);
1619 klass->blittable = blittable;
1620 mono_memory_barrier ();
1621 klass->size_inited = 1;
1622 klass->fields_inited = 1;
1623 klass->setup_fields_called = 1;
1627 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1630 /* Prevent infinite loops if the class references itself */
1631 klass->setup_fields_called = 1;
1633 if (klass->generic_container) {
1634 container = klass->generic_container;
1636 container = gtd->generic_container;
1637 g_assert (container);
1641 * Fetch all the field information.
1643 for (i = 0; i < top; i++){
1644 int idx = klass->field.first + i;
1645 field = &klass->fields [i];
1647 field->parent = klass;
1650 mono_field_resolve_type (field, &error);
1651 if (!mono_error_ok (&error)) {
1652 /*mono_field_resolve_type already failed class*/
1653 mono_error_cleanup (&error);
1657 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1658 g_assert (field->type);
1661 if (mono_field_is_deleted (field))
1664 MonoClassField *gfield = >d->fields [i];
1665 field->offset = gfield->offset;
1667 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1669 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1670 field->offset = offset;
1672 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1673 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1676 if (field->offset < -1) { /*-1 is used to encode special static fields */
1677 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1680 if (klass->generic_container) {
1681 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1687 /* Only do these checks if we still think this type is blittable */
1688 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1689 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1692 MonoClass *field_class = mono_class_from_mono_type (field->type);
1694 mono_class_setup_fields (field_class);
1695 if (field_class->exception_type) {
1696 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1700 if (!field_class || !field_class->blittable)
1705 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1706 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1707 blittable = klass->element_class->blittable;
1710 if (mono_type_has_exceptions (field->type)) {
1711 char *class_name = mono_type_get_full_name (klass);
1712 char *type_name = mono_type_full_name (field->type);
1714 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1715 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1716 g_free (class_name);
1720 /* The def_value of fields is compute lazily during vtable creation */
1723 if (klass == mono_defaults.string_class)
1726 klass->blittable = blittable;
1728 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1729 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1732 if (explicit_size && real_size) {
1733 klass->instance_size = MAX (real_size, klass->instance_size);
1736 if (klass->exception_type)
1738 mono_class_layout_fields (klass);
1740 /*valuetypes can't be neither bigger than 1Mb or empty. */
1741 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1742 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1744 mono_memory_barrier ();
1745 klass->fields_inited = 1;
1749 * mono_class_setup_fields_locking:
1750 * @class: The class to initialize
1752 * Initializes the klass->fields array of fields.
1753 * Aquires the loader lock.
1756 mono_class_setup_fields_locking (MonoClass *klass)
1758 /* This can be checked without locks */
1759 if (klass->fields_inited)
1761 mono_loader_lock ();
1762 mono_class_setup_fields (klass);
1763 mono_loader_unlock ();
1767 * mono_class_has_references:
1769 * Returns whenever @klass->has_references is set, initializing it if needed.
1770 * Aquires the loader lock.
1773 mono_class_has_references (MonoClass *klass)
1775 if (klass->init_pending) {
1776 /* Be conservative */
1779 mono_class_init (klass);
1781 return klass->has_references;
1786 * mono_type_get_basic_type_from_generic:
1789 * Returns a closed type corresponding to the possibly open type
1793 mono_type_get_basic_type_from_generic (MonoType *type)
1795 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1796 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1797 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1798 return &mono_defaults.object_class->byval_arg;
1803 type_has_references (MonoClass *klass, MonoType *ftype)
1805 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)))))
1807 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1808 MonoGenericParam *gparam = ftype->data.generic_param;
1810 if (gparam->gshared_constraint)
1811 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1817 * mono_class_layout_fields:
1820 * Compute the placement of fields inside an object or struct, according to
1821 * the layout rules and set the following fields in @class:
1822 * - has_references (if the class contains instance references firled or structs that contain references)
1823 * - has_static_refs (same, but for static fields)
1824 * - instance_size (size of the object in memory)
1825 * - class_size (size needed for the static fields)
1826 * - size_inited (flag set when the instance_size is set)
1828 * LOCKING: this is supposed to be called with the loader lock held.
1831 mono_class_layout_fields (MonoClass *klass)
1834 const int top = klass->field.count;
1835 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1836 guint32 pass, passes, real_size;
1837 gboolean gc_aware_layout = FALSE;
1838 gboolean has_static_fields = FALSE;
1839 MonoClassField *field;
1842 * When we do generic sharing we need to have layout
1843 * information for open generic classes (either with a generic
1844 * context containing type variables or with a generic
1845 * container), so we don't return in that case anymore.
1849 * Enable GC aware auto layout: in this mode, reference
1850 * fields are grouped together inside objects, increasing collector
1852 * Requires that all classes whose layout is known to native code be annotated
1853 * with [StructLayout (LayoutKind.Sequential)]
1854 * Value types have gc_aware_layout disabled by default, as per
1855 * what the default is for other runtimes.
1857 /* corlib is missing [StructLayout] directives in many places */
1858 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1859 if (!klass->valuetype)
1860 gc_aware_layout = TRUE;
1863 /* Compute klass->has_references */
1865 * Process non-static fields first, since static fields might recursively
1866 * refer to the class itself.
1868 for (i = 0; i < top; i++) {
1871 field = &klass->fields [i];
1873 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1874 ftype = mono_type_get_underlying_type (field->type);
1875 ftype = mono_type_get_basic_type_from_generic (ftype);
1876 if (type_has_references (klass, ftype))
1877 klass->has_references = TRUE;
1881 for (i = 0; i < top; i++) {
1884 field = &klass->fields [i];
1886 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1887 ftype = mono_type_get_underlying_type (field->type);
1888 ftype = mono_type_get_basic_type_from_generic (ftype);
1889 if (type_has_references (klass, ftype))
1890 klass->has_static_refs = TRUE;
1894 for (i = 0; i < top; i++) {
1897 field = &klass->fields [i];
1899 ftype = mono_type_get_underlying_type (field->type);
1900 ftype = mono_type_get_basic_type_from_generic (ftype);
1901 if (type_has_references (klass, ftype)) {
1902 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1903 klass->has_static_refs = TRUE;
1905 klass->has_references = TRUE;
1910 * Compute field layout and total size (not considering static fields)
1914 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1915 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1917 if (gc_aware_layout)
1922 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1925 if (klass->parent) {
1926 mono_class_setup_fields (klass->parent);
1927 if (klass->parent->exception_type) {
1928 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1931 real_size = klass->parent->instance_size;
1933 real_size = sizeof (MonoObject);
1936 for (pass = 0; pass < passes; ++pass) {
1937 for (i = 0; i < top; i++){
1942 field = &klass->fields [i];
1944 if (mono_field_is_deleted (field))
1946 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1949 ftype = mono_type_get_underlying_type (field->type);
1950 ftype = mono_type_get_basic_type_from_generic (ftype);
1951 if (gc_aware_layout) {
1952 if (type_has_references (klass, ftype)) {
1961 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1962 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1963 /* This field is a hack inserted by MCS to empty structures */
1967 size = mono_type_size (field->type, &align);
1969 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1970 align = klass->packing_size ? MIN (klass->packing_size, align): align;
1971 /* if the field has managed references, we need to force-align it
1974 if (type_has_references (klass, ftype))
1975 align = MAX (align, sizeof (gpointer));
1977 klass->min_align = MAX (align, klass->min_align);
1978 field->offset = real_size;
1980 field->offset += align - 1;
1981 field->offset &= ~(align - 1);
1983 /*TypeBuilders produce all sort of weird things*/
1984 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
1985 real_size = field->offset + size;
1988 klass->instance_size = MAX (real_size, klass->instance_size);
1990 if (klass->instance_size & (klass->min_align - 1)) {
1991 klass->instance_size += klass->min_align - 1;
1992 klass->instance_size &= ~(klass->min_align - 1);
1996 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
2000 for (i = 0; i < top; i++) {
2005 field = &klass->fields [i];
2008 * There must be info about all the fields in a type if it
2009 * uses explicit layout.
2011 if (mono_field_is_deleted (field))
2013 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2016 size = mono_type_size (field->type, &align);
2017 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2018 klass->min_align = MAX (align, klass->min_align);
2021 * When we get here, field->offset is already set by the
2022 * loader (for either runtime fields or fields loaded from metadata).
2023 * The offset is from the start of the object: this works for both
2024 * classes and valuetypes.
2026 field->offset += sizeof (MonoObject);
2027 ftype = mono_type_get_underlying_type (field->type);
2028 ftype = mono_type_get_basic_type_from_generic (ftype);
2029 if (type_has_references (klass, ftype)) {
2030 if (field->offset % sizeof (gpointer)) {
2031 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2038 real_size = MAX (real_size, size + field->offset);
2041 if (klass->has_references) {
2042 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2044 /* Check for overlapping reference and non-reference fields */
2045 for (i = 0; i < top; i++) {
2048 field = &klass->fields [i];
2050 if (mono_field_is_deleted (field))
2052 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2054 ftype = mono_type_get_underlying_type (field->type);
2055 if (MONO_TYPE_IS_REFERENCE (ftype))
2056 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2058 for (i = 0; i < top; i++) {
2059 field = &klass->fields [i];
2061 if (mono_field_is_deleted (field))
2063 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2066 // FIXME: Too much code does this
2068 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2069 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);
2070 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2074 g_free (ref_bitmap);
2077 klass->instance_size = MAX (real_size, klass->instance_size);
2078 if (klass->instance_size & (klass->min_align - 1)) {
2079 klass->instance_size += klass->min_align - 1;
2080 klass->instance_size &= ~(klass->min_align - 1);
2086 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2088 * This leads to all kinds of problems with nested structs, so only
2089 * enable it when a MONO_DEBUG property is set.
2091 * For small structs, set min_align to at least the struct size to improve
2092 * performance, and since the JIT memset/memcpy code assumes this and generates
2093 * unaligned accesses otherwise. See #78990 for a testcase.
2095 if (mono_align_small_structs) {
2096 if (klass->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2097 klass->min_align = MAX (klass->min_align, klass->instance_size - sizeof (MonoObject));
2101 mono_memory_barrier ();
2102 klass->size_inited = 1;
2105 * Compute static field layout and size
2107 for (i = 0; i < top; i++){
2111 field = &klass->fields [i];
2113 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2115 if (mono_field_is_deleted (field))
2118 if (mono_type_has_exceptions (field->type)) {
2119 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2123 has_static_fields = TRUE;
2125 size = mono_type_size (field->type, &align);
2126 field->offset = klass->sizes.class_size;
2127 /*align is always non-zero here*/
2128 field->offset += align - 1;
2129 field->offset &= ~(align - 1);
2130 klass->sizes.class_size = field->offset + size;
2133 if (has_static_fields && klass->sizes.class_size == 0)
2134 /* Simplify code which depends on class_size != 0 if the class has static fields */
2135 klass->sizes.class_size = 8;
2139 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2143 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2144 method->klass = klass;
2145 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2146 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2147 method->signature = sig;
2148 method->name = name;
2151 if (name [0] == '.') {
2152 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2154 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2160 * mono_class_setup_methods:
2163 * Initializes the 'methods' array in CLASS.
2164 * Calling this method should be avoided if possible since it allocates a lot
2165 * of long-living MonoMethod structures.
2166 * Methods belonging to an interface are assigned a sequential slot starting
2169 * On failure this function sets klass->exception_type
2172 mono_class_setup_methods (MonoClass *klass)
2175 MonoMethod **methods;
2180 if (klass->generic_class) {
2182 MonoClass *gklass = klass->generic_class->container_class;
2184 mono_class_init (gklass);
2185 if (!gklass->exception_type)
2186 mono_class_setup_methods (gklass);
2187 if (gklass->exception_type) {
2188 /* FIXME make exception_data less opaque so it's possible to dup it here */
2189 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2193 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2194 count = gklass->method.count;
2195 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2197 for (i = 0; i < count; i++) {
2198 methods [i] = mono_class_inflate_generic_method_full_checked (
2199 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2200 if (!mono_error_ok (&error)) {
2201 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2202 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)));
2205 mono_error_cleanup (&error);
2209 } else if (klass->rank) {
2211 MonoMethod *amethod;
2212 MonoMethodSignature *sig;
2213 int count_generic = 0, first_generic = 0;
2215 gboolean jagged_ctor = FALSE;
2217 count = 3 + (klass->rank > 1? 2: 1);
2219 mono_class_setup_interfaces (klass, &error);
2220 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2222 if (klass->rank == 1 && klass->element_class->rank) {
2224 klass->method.count ++;
2227 if (klass->interface_count) {
2228 count_generic = generic_array_methods (klass);
2229 first_generic = count;
2230 count += klass->interface_count * count_generic;
2233 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2235 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2236 sig->ret = &mono_defaults.void_class->byval_arg;
2237 sig->pinvoke = TRUE;
2238 sig->hasthis = TRUE;
2239 for (i = 0; i < klass->rank; ++i)
2240 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2242 amethod = create_array_method (klass, ".ctor", sig);
2243 methods [method_num++] = amethod;
2244 if (klass->rank > 1) {
2245 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2246 sig->ret = &mono_defaults.void_class->byval_arg;
2247 sig->pinvoke = TRUE;
2248 sig->hasthis = TRUE;
2249 for (i = 0; i < klass->rank * 2; ++i)
2250 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2252 amethod = create_array_method (klass, ".ctor", sig);
2253 methods [method_num++] = amethod;
2257 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2258 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2259 sig->ret = &mono_defaults.void_class->byval_arg;
2260 sig->pinvoke = TRUE;
2261 sig->hasthis = TRUE;
2262 for (i = 0; i < klass->rank + 1; ++i)
2263 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2264 amethod = create_array_method (klass, ".ctor", sig);
2265 methods [method_num++] = amethod;
2268 /* element Get (idx11, [idx2, ...]) */
2269 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2270 sig->ret = &klass->element_class->byval_arg;
2271 sig->pinvoke = TRUE;
2272 sig->hasthis = TRUE;
2273 for (i = 0; i < klass->rank; ++i)
2274 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2275 amethod = create_array_method (klass, "Get", sig);
2276 methods [method_num++] = amethod;
2277 /* element& Address (idx11, [idx2, ...]) */
2278 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2279 sig->ret = &klass->element_class->this_arg;
2280 sig->pinvoke = TRUE;
2281 sig->hasthis = TRUE;
2282 for (i = 0; i < klass->rank; ++i)
2283 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2284 amethod = create_array_method (klass, "Address", sig);
2285 methods [method_num++] = amethod;
2286 /* void Set (idx11, [idx2, ...], element) */
2287 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2288 sig->ret = &mono_defaults.void_class->byval_arg;
2289 sig->pinvoke = TRUE;
2290 sig->hasthis = TRUE;
2291 for (i = 0; i < klass->rank; ++i)
2292 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2293 sig->params [i] = &klass->element_class->byval_arg;
2294 amethod = create_array_method (klass, "Set", sig);
2295 methods [method_num++] = amethod;
2297 for (i = 0; i < klass->interface_count; i++)
2298 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2302 count = klass->method.count;
2303 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2304 for (i = 0; i < count; ++i) {
2305 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2306 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2308 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)));
2309 mono_error_cleanup (&error);
2314 if (MONO_CLASS_IS_INTERFACE (klass)) {
2316 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2317 for (i = 0; i < count; ++i) {
2318 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2319 methods [i]->slot = slot++;
2323 mono_image_lock (klass->image);
2325 if (!klass->methods) {
2326 klass->method.count = count;
2328 /* Needed because of the double-checking locking pattern */
2329 mono_memory_barrier ();
2331 klass->methods = methods;
2334 mono_image_unlock (klass->image);
2338 * mono_class_get_method_by_index:
2340 * Returns klass->methods [index], initializing klass->methods if neccesary.
2342 * LOCKING: Acquires the loader lock.
2345 mono_class_get_method_by_index (MonoClass *klass, int index)
2348 /* Avoid calling setup_methods () if possible */
2349 if (klass->generic_class && !klass->methods) {
2350 MonoClass *gklass = klass->generic_class->container_class;
2353 m = mono_class_inflate_generic_method_full_checked (
2354 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2355 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2357 * If setup_methods () is called later for this class, no duplicates are created,
2358 * since inflate_generic_method guarantees that only one instance of a method
2359 * is created for each context.
2362 mono_class_setup_methods (klass);
2363 g_assert (m == klass->methods [index]);
2367 mono_class_setup_methods (klass);
2368 if (klass->exception_type) /*FIXME do proper error handling*/
2370 g_assert (index >= 0 && index < klass->method.count);
2371 return klass->methods [index];
2376 * mono_class_get_inflated_method:
2378 * Given an inflated class CLASS and a method METHOD which should be a method of
2379 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2382 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2384 MonoClass *gklass = klass->generic_class->container_class;
2387 g_assert (method->klass == gklass);
2389 mono_class_setup_methods (gklass);
2390 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2392 for (i = 0; i < gklass->method.count; ++i) {
2393 if (gklass->methods [i] == method) {
2394 if (klass->methods) {
2395 return klass->methods [i];
2398 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2399 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2409 * mono_class_get_vtable_entry:
2411 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2412 * LOCKING: Acquires the loader lock.
2415 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2419 if (klass->rank == 1) {
2421 * szarrays do not overwrite any methods of Array, so we can avoid
2422 * initializing their vtables in some cases.
2424 mono_class_setup_vtable (klass->parent);
2425 if (offset < klass->parent->vtable_size)
2426 return klass->parent->vtable [offset];
2429 if (klass->generic_class) {
2431 MonoClass *gklass = klass->generic_class->container_class;
2432 mono_class_setup_vtable (gklass);
2433 m = gklass->vtable [offset];
2435 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2436 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2438 mono_class_setup_vtable (klass);
2439 if (klass->exception_type)
2441 m = klass->vtable [offset];
2448 * mono_class_get_vtable_size:
2450 * Return the vtable size for KLASS.
2453 mono_class_get_vtable_size (MonoClass *klass)
2455 mono_class_setup_vtable (klass);
2457 return klass->vtable_size;
2461 * mono_class_setup_properties:
2463 * Initialize klass->ext.property and klass->ext.properties.
2465 * This method can fail the class.
2468 mono_class_setup_properties (MonoClass *klass)
2470 guint startm, endm, i, j;
2471 guint32 cols [MONO_PROPERTY_SIZE];
2472 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2473 MonoProperty *properties;
2477 if (klass->ext && klass->ext->properties)
2480 if (klass->generic_class) {
2481 MonoClass *gklass = klass->generic_class->container_class;
2483 mono_class_init (gklass);
2484 mono_class_setup_properties (gklass);
2485 if (gklass->exception_type) {
2486 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2490 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2492 for (i = 0; i < gklass->ext->property.count; i++) {
2494 MonoProperty *prop = &properties [i];
2496 *prop = gklass->ext->properties [i];
2499 prop->get = mono_class_inflate_generic_method_full_checked (
2500 prop->get, klass, mono_class_get_context (klass), &error);
2502 prop->set = mono_class_inflate_generic_method_full_checked (
2503 prop->set, klass, mono_class_get_context (klass), &error);
2505 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2506 prop->parent = klass;
2509 first = gklass->ext->property.first;
2510 count = gklass->ext->property.count;
2512 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2513 count = last - first;
2516 mono_class_setup_methods (klass);
2517 if (klass->exception_type)
2521 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2522 for (i = first; i < last; ++i) {
2523 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2524 properties [i - first].parent = klass;
2525 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2526 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2528 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2529 for (j = startm; j < endm; ++j) {
2532 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2534 if (klass->image->uncompressed_metadata) {
2536 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2537 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2538 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2540 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2543 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2544 case METHOD_SEMANTIC_SETTER:
2545 properties [i - first].set = method;
2547 case METHOD_SEMANTIC_GETTER:
2548 properties [i - first].get = method;
2557 mono_class_alloc_ext (klass);
2559 mono_image_lock (klass->image);
2561 if (klass->ext->properties) {
2562 /* We leak 'properties' which was allocated from the image mempool */
2563 mono_image_unlock (klass->image);
2567 klass->ext->property.first = first;
2568 klass->ext->property.count = count;
2570 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2571 mono_memory_barrier ();
2573 /* Leave this assignment as the last op in the function */
2574 klass->ext->properties = properties;
2576 mono_image_unlock (klass->image);
2580 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2582 MonoMethod **om, **retval;
2585 for (om = methods, count = 0; *om; ++om, ++count)
2588 retval = g_new0 (MonoMethod*, count + 1);
2590 for (om = methods, count = 0; *om; ++om, ++count) {
2592 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2593 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2599 /*This method can fail the class.*/
2601 mono_class_setup_events (MonoClass *klass)
2604 guint startm, endm, i, j;
2605 guint32 cols [MONO_EVENT_SIZE];
2606 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2610 if (klass->ext && klass->ext->events)
2613 if (klass->generic_class) {
2614 MonoClass *gklass = klass->generic_class->container_class;
2615 MonoGenericContext *context = NULL;
2617 mono_class_setup_events (gklass);
2618 if (gklass->exception_type) {
2619 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2623 first = gklass->ext->event.first;
2624 count = gklass->ext->event.count;
2626 events = mono_class_new0 (klass, MonoEvent, count);
2629 context = mono_class_get_context (klass);
2631 for (i = 0; i < count; i++) {
2633 MonoEvent *event = &events [i];
2634 MonoEvent *gevent = &gklass->ext->events [i];
2636 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2638 event->parent = klass;
2639 event->name = gevent->name;
2640 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2641 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2642 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2643 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2644 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2645 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2647 #ifndef MONO_SMALL_CONFIG
2648 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2650 event->attrs = gevent->attrs;
2653 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2654 count = last - first;
2657 mono_class_setup_methods (klass);
2658 if (klass->exception_type) {
2659 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2664 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2665 for (i = first; i < last; ++i) {
2666 MonoEvent *event = &events [i - first];
2668 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2669 event->parent = klass;
2670 event->attrs = cols [MONO_EVENT_FLAGS];
2671 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2673 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2674 for (j = startm; j < endm; ++j) {
2677 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2679 if (klass->image->uncompressed_metadata) {
2681 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2682 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2683 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2685 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2688 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2689 case METHOD_SEMANTIC_ADD_ON:
2690 event->add = method;
2692 case METHOD_SEMANTIC_REMOVE_ON:
2693 event->remove = method;
2695 case METHOD_SEMANTIC_FIRE:
2696 event->raise = method;
2698 case METHOD_SEMANTIC_OTHER: {
2699 #ifndef MONO_SMALL_CONFIG
2702 if (event->other == NULL) {
2703 event->other = g_new0 (MonoMethod*, 2);
2705 while (event->other [n])
2707 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2709 event->other [n] = method;
2710 /* NULL terminated */
2711 event->other [n + 1] = NULL;
2722 mono_class_alloc_ext (klass);
2724 mono_image_lock (klass->image);
2726 if (klass->ext->events) {
2727 mono_image_unlock (klass->image);
2731 klass->ext->event.first = first;
2732 klass->ext->event.count = count;
2734 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2735 mono_memory_barrier ();
2737 /* Leave this assignment as the last op in the function */
2738 klass->ext->events = events;
2740 mono_image_unlock (klass->image);
2744 * Global pool of interface IDs, represented as a bitset.
2745 * LOCKING: Protected by the classes lock.
2747 static MonoBitSet *global_interface_bitset = NULL;
2750 * mono_unload_interface_ids:
2751 * @bitset: bit set of interface IDs
2753 * When an image is unloaded, the interface IDs associated with
2754 * the image are put back in the global pool of IDs so the numbers
2758 mono_unload_interface_ids (MonoBitSet *bitset)
2761 mono_bitset_sub (global_interface_bitset, bitset);
2766 mono_unload_interface_id (MonoClass *klass)
2768 if (global_interface_bitset && klass->interface_id) {
2770 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2776 * mono_get_unique_iid:
2779 * Assign a unique integer ID to the interface represented by @class.
2780 * The ID will positive and as small as possible.
2781 * LOCKING: Acquires the classes lock.
2782 * Returns: the new ID.
2785 mono_get_unique_iid (MonoClass *klass)
2789 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2793 if (!global_interface_bitset) {
2794 global_interface_bitset = mono_bitset_new (128, 0);
2797 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2799 int old_size = mono_bitset_size (global_interface_bitset);
2800 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2801 mono_bitset_free (global_interface_bitset);
2802 global_interface_bitset = new_set;
2805 mono_bitset_set (global_interface_bitset, iid);
2806 /* set the bit also in the per-image set */
2807 if (!klass->generic_class) {
2808 if (klass->image->interface_bitset) {
2809 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2810 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2811 mono_bitset_free (klass->image->interface_bitset);
2812 klass->image->interface_bitset = new_set;
2815 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2817 mono_bitset_set (klass->image->interface_bitset, iid);
2822 #ifndef MONO_SMALL_CONFIG
2823 if (mono_print_vtable) {
2825 char *type_name = mono_type_full_name (&klass->byval_arg);
2826 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2827 generic_id = klass->generic_class->context.class_inst->id;
2828 g_assert (generic_id != 0);
2832 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2837 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2838 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2839 g_assert (iid < INT_MAX);
2844 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2849 mono_class_setup_interfaces (klass, error);
2850 if (!mono_error_ok (error))
2853 for (i = 0; i < klass->interface_count; i++) {
2854 ic = klass->interfaces [i];
2857 *res = g_ptr_array_new ();
2858 g_ptr_array_add (*res, ic);
2859 mono_class_init (ic);
2860 if (ic->exception_type) {
2861 mono_error_set_type_load_class (error, ic, "Error Loading class");
2865 collect_implemented_interfaces_aux (ic, res, error);
2866 if (!mono_error_ok (error))
2872 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2874 GPtrArray *res = NULL;
2876 collect_implemented_interfaces_aux (klass, &res, error);
2877 if (!mono_error_ok (error)) {
2879 g_ptr_array_free (res, TRUE);
2886 compare_interface_ids (const void *p_key, const void *p_element) {
2887 const MonoClass *key = (const MonoClass *)p_key;
2888 const MonoClass *element = *(const MonoClass **)p_element;
2890 return (key->interface_id - element->interface_id);
2893 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2895 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2896 MonoClass **result = (MonoClass **)mono_binary_search (
2898 klass->interfaces_packed,
2899 klass->interface_offsets_count,
2900 sizeof (MonoClass *),
2901 compare_interface_ids);
2903 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2910 * mono_class_interface_offset_with_variance:
2912 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2913 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2915 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2917 * FIXME figure out MS disambiguation rules and fix this function.
2920 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2921 int i = mono_class_interface_offset (klass, itf);
2922 *non_exact_match = FALSE;
2926 if (!mono_class_has_variant_generic_params (itf))
2929 for (i = 0; i < klass->interface_offsets_count; i++) {
2930 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2931 *non_exact_match = TRUE;
2932 return klass->interface_offsets_packed [i];
2940 print_implemented_interfaces (MonoClass *klass) {
2943 GPtrArray *ifaces = NULL;
2945 int ancestor_level = 0;
2947 name = mono_type_get_full_name (klass);
2948 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2951 for (i = 0; i < klass->interface_offsets_count; i++)
2952 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2953 klass->interfaces_packed [i]->interface_id,
2954 klass->interface_offsets_packed [i],
2955 klass->interfaces_packed [i]->method.count,
2956 klass->interfaces_packed [i]->name_space,
2957 klass->interfaces_packed [i]->name );
2958 printf ("Interface flags: ");
2959 for (i = 0; i <= klass->max_interface_id; i++)
2960 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2961 printf ("(%d,T)", i);
2963 printf ("(%d,F)", i);
2965 printf ("Dump interface flags:");
2966 #ifdef COMPRESSED_INTERFACE_BITMAP
2968 const uint8_t* p = klass->interface_bitmap;
2969 i = klass->max_interface_id;
2971 printf (" %d x 00 %02X", p [0], p [1]);
2977 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2978 printf (" %02X", klass->interface_bitmap [i]);
2981 while (klass != NULL) {
2982 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2983 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2984 if (!mono_error_ok (&error)) {
2985 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2986 mono_error_cleanup (&error);
2987 } else if (ifaces) {
2988 for (i = 0; i < ifaces->len; i++) {
2989 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
2990 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2991 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2993 mono_class_interface_offset (klass, ic),
2998 g_ptr_array_free (ifaces, TRUE);
3001 klass = klass->parent;
3006 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3009 args [0] = &arg0->byval_arg;
3011 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3015 array_class_get_if_rank (MonoClass *klass, guint rank)
3017 return rank ? mono_array_class_get (klass, rank) : klass;
3021 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3023 valuetype_types [0] = eclass;
3024 if (eclass == mono_defaults.int16_class)
3025 valuetype_types [1] = mono_defaults.uint16_class;
3026 else if (eclass == mono_defaults.uint16_class)
3027 valuetype_types [1] = mono_defaults.int16_class;
3028 else if (eclass == mono_defaults.int32_class)
3029 valuetype_types [1] = mono_defaults.uint32_class;
3030 else if (eclass == mono_defaults.uint32_class)
3031 valuetype_types [1] = mono_defaults.int32_class;
3032 else if (eclass == mono_defaults.int64_class)
3033 valuetype_types [1] = mono_defaults.uint64_class;
3034 else if (eclass == mono_defaults.uint64_class)
3035 valuetype_types [1] = mono_defaults.int64_class;
3036 else if (eclass == mono_defaults.byte_class)
3037 valuetype_types [1] = mono_defaults.sbyte_class;
3038 else if (eclass == mono_defaults.sbyte_class)
3039 valuetype_types [1] = mono_defaults.byte_class;
3040 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3041 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3044 /* this won't be needed once bug #325495 is completely fixed
3045 * though we'll need something similar to know which interfaces to allow
3046 * in arrays when they'll be lazyly created
3048 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3049 * MS returns diferrent types based on which instance is called. For example:
3050 * object obj = new byte[10][];
3051 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3052 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3055 * Fixing this should kill quite some code, save some bits and improve compatibility.
3058 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3060 MonoClass *eclass = klass->element_class;
3061 static MonoClass* generic_icollection_class = NULL;
3062 static MonoClass* generic_ienumerable_class = NULL;
3063 static MonoClass* generic_ienumerator_class = NULL;
3064 static MonoClass* generic_ireadonlylist_class = NULL;
3065 static MonoClass* generic_ireadonlycollection_class = NULL;
3066 MonoClass *valuetype_types[2] = { NULL, NULL };
3067 MonoClass **interfaces = NULL;
3068 int i, nifaces, interface_count, real_count, original_rank;
3070 gboolean internal_enumerator;
3071 gboolean eclass_is_valuetype;
3073 if (!mono_defaults.generic_ilist_class) {
3077 internal_enumerator = FALSE;
3078 eclass_is_valuetype = FALSE;
3079 original_rank = eclass->rank;
3080 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3081 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3083 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3085 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3086 original_rank = eclass->rank;
3088 eclass = eclass->element_class;
3089 internal_enumerator = TRUE;
3090 *is_enumerator = TRUE;
3098 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3099 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3101 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3103 if (!generic_icollection_class) {
3104 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3105 "System.Collections.Generic", "ICollection`1");
3106 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3107 "System.Collections.Generic", "IEnumerable`1");
3108 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3109 "System.Collections.Generic", "IEnumerator`1");
3110 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3111 "System.Collections.Generic", "IReadOnlyList`1");
3112 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3113 "System.Collections.Generic", "IReadOnlyCollection`1");
3116 mono_class_init (eclass);
3119 * Arrays in 2.0 need to implement a number of generic interfaces
3120 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3121 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3122 * We collect the types needed to build the
3123 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3124 * the generic interfaces needed to implement.
3126 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3127 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3129 if (eclass->valuetype) {
3130 nifaces = generic_ireadonlylist_class ? 5 : 3;
3131 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3133 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3134 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3135 if (internal_enumerator) {
3137 if (valuetype_types [1])
3141 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3142 interfaces [0] = valuetype_types [0];
3143 if (valuetype_types [1])
3144 interfaces [nifaces] = valuetype_types [1];
3146 eclass_is_valuetype = TRUE;
3149 int idepth = eclass->idepth;
3150 if (!internal_enumerator)
3152 nifaces = generic_ireadonlylist_class ? 2 : 3;
3154 // FIXME: This doesn't seem to work/required for generic params
3155 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3156 mono_class_setup_interface_offsets (eclass);
3158 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3159 /* we add object for interfaces and the supertypes for the other
3160 * types. The last of the supertypes is the element class itself which we
3161 * already created the explicit interfaces for (so we include it for IEnumerator
3162 * and exclude it for arrays).
3164 if (MONO_CLASS_IS_INTERFACE (eclass))
3167 interface_count += idepth;
3168 if (eclass->rank && eclass->element_class->valuetype) {
3169 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3170 if (valuetype_types [1])
3173 /* IList, ICollection, IEnumerable, IReadOnlyList */
3174 interface_count *= nifaces;
3175 real_count = interface_count;
3176 if (internal_enumerator) {
3177 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3178 if (valuetype_types [1])
3181 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3182 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3183 interfaces [0] = mono_defaults.object_class;
3187 for (i = 0; i < idepth; i++) {
3188 mono_class_init (eclass->supertypes [i]);
3189 interfaces [j] = eclass->supertypes [i];
3193 if (all_interfaces) {
3194 for (i = 0; i < eclass->interface_offsets_count; i++) {
3195 interfaces [j] = eclass->interfaces_packed [i];
3199 for (i = 0; i < eclass->interface_count; i++) {
3200 interfaces [j] = eclass->interfaces [i];
3204 if (valuetype_types [1]) {
3205 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3210 /* instantiate the generic interfaces */
3211 for (i = 0; i < interface_count; i += nifaces) {
3212 MonoClass *iface = interfaces [i];
3214 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3215 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3217 if (eclass->valuetype) {
3218 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3219 if (generic_ireadonlylist_class) {
3220 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3221 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3224 if (!generic_ireadonlylist_class)
3225 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3228 if (internal_enumerator) {
3230 /* instantiate IEnumerator<iface> */
3231 for (i = 0; i < interface_count; i++) {
3232 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3234 j = interface_count;
3235 if (!eclass_is_valuetype) {
3236 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3237 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3240 for (i = 0; i < eclass->idepth; i++) {
3241 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3245 for (i = 0; i < eclass->interface_offsets_count; i++) {
3246 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3250 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3252 if (valuetype_types [1])
3253 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3257 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3258 for (i = 0; i < real_count; ++i) {
3259 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3260 g_print ("%s implements %s\n", type_name, name);
3271 find_array_interface (MonoClass *klass, const char *name)
3274 for (i = 0; i < klass->interface_count; ++i) {
3275 if (strcmp (klass->interfaces [i]->name, name) == 0)
3282 * Return the number of virtual methods.
3283 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3284 * Return -1 on failure.
3285 * FIXME It would be nice if this information could be cached somewhere.
3288 count_virtual_methods (MonoClass *klass)
3292 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3294 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3295 mono_class_setup_methods (klass);
3296 if (klass->exception_type)
3299 for (i = 0; i < klass->method.count; ++i) {
3300 flags = klass->methods [i]->flags;
3301 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3305 for (i = 0; i < klass->method.count; ++i) {
3306 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3308 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3316 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3324 m = (l + num_ifaces) / 2;
3325 if (interfaces_full [m] == ic)
3327 if (l == num_ifaces)
3329 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3338 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3340 int i = find_interface (num_ifaces, interfaces_full, ic);
3342 return interface_offsets_full [i];
3347 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3349 int i = find_interface (num_ifaces, interfaces_full, ic);
3353 interface_offsets_full [i] = offset;
3356 for (i = 0; i < num_ifaces; ++i) {
3357 if (interfaces_full [i]) {
3359 if (interfaces_full [i]->interface_id < ic->interface_id)
3362 while (end < num_ifaces && interfaces_full [end]) end++;
3363 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3364 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3366 interfaces_full [i] = ic;
3367 interface_offsets_full [i] = offset;
3373 #ifdef COMPRESSED_INTERFACE_BITMAP
3376 * Compressed interface bitmap design.
3378 * Interface bitmaps take a large amount of memory, because their size is
3379 * linear with the maximum interface id assigned in the process (each interface
3380 * is assigned a unique id as it is loaded). The number of interface classes
3381 * is high because of the many implicit interfaces implemented by arrays (we'll
3382 * need to lazy-load them in the future).
3383 * Most classes implement a very small number of interfaces, so the bitmap is
3384 * sparse. This bitmap needs to be checked by interface casts, so access to the
3385 * needed bit must be fast and doable with few jit instructions.
3387 * The current compression format is as follows:
3388 * *) it is a sequence of one or more two-byte elements
3389 * *) the first byte in the element is the count of empty bitmap bytes
3390 * at the current bitmap position
3391 * *) the second byte in the element is an actual bitmap byte at the current
3394 * As an example, the following compressed bitmap bytes:
3395 * 0x07 0x01 0x00 0x7
3396 * correspond to the following bitmap:
3397 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3399 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3400 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3401 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3405 * mono_compress_bitmap:
3406 * @dest: destination buffer
3407 * @bitmap: bitmap buffer
3408 * @size: size of @bitmap in bytes
3410 * This is a mono internal function.
3411 * The @bitmap data is compressed into a format that is small but
3412 * still searchable in few instructions by the JIT and runtime.
3413 * The compressed data is stored in the buffer pointed to by the
3414 * @dest array. Passing a #NULL value for @dest allows to just compute
3415 * the size of the buffer.
3416 * This compression algorithm assumes the bits set in the bitmap are
3417 * few and far between, like in interface bitmaps.
3418 * Returns: the size of the compressed bitmap in bytes.
3421 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3425 const uint8_t *end = bitmap + size;
3426 while (bitmap < end) {
3427 if (*bitmap || numz == 255) {
3451 * mono_class_interface_match:
3452 * @bitmap: a compressed bitmap buffer
3453 * @id: the index to check in the bitmap
3455 * This is a mono internal function.
3456 * Checks if a bit is set in a compressed interface bitmap. @id must
3457 * be already checked for being smaller than the maximum id encoded in the
3460 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3464 mono_class_interface_match (const uint8_t *bitmap, int id)
3467 id -= bitmap [0] * 8;
3471 return bitmap [1] & (1 << id);
3480 * LOCKING: this is supposed to be called with the loader lock held.
3481 * Return -1 on failure and set exception_type
3484 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3488 int i, j, num_ifaces;
3490 MonoClass **interfaces_full = NULL;
3491 int *interface_offsets_full = NULL;
3493 GPtrArray **ifaces_array = NULL;
3494 int interface_offsets_count;
3495 MonoClass **array_interfaces = NULL;
3496 int num_array_interfaces;
3497 int is_enumerator = FALSE;
3499 mono_class_setup_supertypes (klass);
3501 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3502 * implicit interfaces have the property that they are assigned the same slot in the
3503 * vtables for compatible interfaces
3505 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3507 /* compute maximum number of slots and maximum interface id */
3509 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3510 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3511 for (j = 0; j < klass->idepth; j++) {
3512 k = klass->supertypes [j];
3513 num_ifaces += k->interface_count;
3514 for (i = 0; i < k->interface_count; i++) {
3515 ic = k->interfaces [i];
3518 mono_class_init (ic);
3520 if (max_iid < ic->interface_id)
3521 max_iid = ic->interface_id;
3523 ifaces = mono_class_get_implemented_interfaces (k, &error);
3524 if (!mono_error_ok (&error)) {
3525 char *name = mono_type_get_full_name (k);
3526 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)));
3528 mono_error_cleanup (&error);
3533 num_ifaces += ifaces->len;
3534 for (i = 0; i < ifaces->len; ++i) {
3535 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3536 if (max_iid < ic->interface_id)
3537 max_iid = ic->interface_id;
3539 ifaces_array [j] = ifaces;
3543 for (i = 0; i < num_array_interfaces; ++i) {
3544 ic = array_interfaces [i];
3545 mono_class_init (ic);
3546 if (max_iid < ic->interface_id)
3547 max_iid = ic->interface_id;
3550 if (MONO_CLASS_IS_INTERFACE (klass)) {
3552 if (max_iid < klass->interface_id)
3553 max_iid = klass->interface_id;
3555 klass->max_interface_id = max_iid;
3556 /* compute vtable offset for interfaces */
3557 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3558 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3560 for (i = 0; i < num_ifaces; i++) {
3561 interface_offsets_full [i] = -1;
3564 /* skip the current class */
3565 for (j = 0; j < klass->idepth - 1; j++) {
3566 k = klass->supertypes [j];
3567 ifaces = ifaces_array [j];
3570 for (i = 0; i < ifaces->len; ++i) {
3572 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3574 /*Force the sharing of interface offsets between parent and subtypes.*/
3575 io = mono_class_interface_offset (k, ic);
3577 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3582 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3583 ifaces = ifaces_array [klass->idepth - 1];
3585 for (i = 0; i < ifaces->len; ++i) {
3587 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3588 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3590 count = count_virtual_methods (ic);
3592 char *name = mono_type_get_full_name (ic);
3593 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3602 if (MONO_CLASS_IS_INTERFACE (klass))
3603 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3605 if (num_array_interfaces) {
3606 if (is_enumerator) {
3607 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3608 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3609 g_assert (ienumerator_offset >= 0);
3610 for (i = 0; i < num_array_interfaces; ++i) {
3611 ic = array_interfaces [i];
3612 if (strcmp (ic->name, "IEnumerator`1") == 0)
3613 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3615 g_assert_not_reached ();
3616 /*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);*/
3619 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3620 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3621 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3622 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3623 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3624 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3625 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3626 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3627 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3628 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3629 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3630 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3631 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3632 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3633 for (i = 0; i < num_array_interfaces; ++i) {
3635 ic = array_interfaces [i];
3636 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3637 offset = ilist_offset;
3638 else if (strcmp (ic->name, "ICollection`1") == 0)
3639 offset = icollection_offset;
3640 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3641 offset = ienumerable_offset;
3642 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3643 offset = ireadonlylist_offset;
3644 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3645 offset = ireadonlycollection_offset;
3647 g_assert_not_reached ();
3648 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3649 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3654 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3655 if (interface_offsets_full [i] != -1) {
3656 interface_offsets_count ++;
3661 * We might get called multiple times:
3662 * - mono_class_init ()
3663 * - mono_class_setup_vtable ().
3664 * - mono_class_setup_interface_offsets ().
3665 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3666 * means we have to overwrite those when called from other places (#4440).
3668 if (klass->interfaces_packed) {
3670 g_assert (klass->interface_offsets_count == interface_offsets_count);
3674 klass->interface_offsets_count = interface_offsets_count;
3675 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3676 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3677 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3678 #ifdef COMPRESSED_INTERFACE_BITMAP
3679 bitmap = g_malloc0 (bsize);
3681 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3683 for (i = 0; i < interface_offsets_count; i++) {
3684 guint32 id = interfaces_full [i]->interface_id;
3685 bitmap [id >> 3] |= (1 << (id & 7));
3686 klass->interfaces_packed [i] = interfaces_full [i];
3687 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3688 /*if (num_array_interfaces)
3689 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]);*/
3691 #ifdef COMPRESSED_INTERFACE_BITMAP
3692 i = mono_compress_bitmap (NULL, bitmap, bsize);
3693 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3694 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3697 klass->interface_bitmap = bitmap;
3702 g_free (interfaces_full);
3703 g_free (interface_offsets_full);
3704 g_free (array_interfaces);
3705 for (i = 0; i < klass->idepth; i++) {
3706 ifaces = ifaces_array [i];
3708 g_ptr_array_free (ifaces, TRUE);
3710 g_free (ifaces_array);
3712 //printf ("JUST DONE: ");
3713 //print_implemented_interfaces (klass);
3719 * Setup interface offsets for interfaces.
3721 * - klass->max_interface_id
3722 * - klass->interface_offsets_count
3723 * - klass->interfaces_packed
3724 * - klass->interface_offsets_packed
3725 * - klass->interface_bitmap
3727 * This function can fail @class.
3730 mono_class_setup_interface_offsets (MonoClass *klass)
3732 mono_loader_lock ();
3734 setup_interface_offsets (klass, 0, FALSE);
3736 mono_loader_unlock ();
3739 /*Checks if @klass has @parent as one of it's parents type gtd
3743 * Bar<T> : Foo<Bar<Bar<T>>>
3747 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3749 klass = mono_class_get_generic_type_definition (klass);
3750 parent = mono_class_get_generic_type_definition (parent);
3751 mono_class_setup_supertypes (klass);
3752 mono_class_setup_supertypes (parent);
3754 return klass->idepth >= parent->idepth &&
3755 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3759 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3761 MonoGenericInst *ginst;
3763 if (!klass->generic_class) {
3764 mono_class_setup_vtable_full (klass, in_setup);
3765 return klass->exception_type == 0;
3768 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3769 if (klass->generic_class->container_class->exception_type) {
3770 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3774 ginst = klass->generic_class->context.class_inst;
3775 for (i = 0; i < ginst->type_argc; ++i) {
3777 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3779 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3780 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3781 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3783 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3784 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3792 * mono_class_setup_vtable:
3794 * Creates the generic vtable of CLASS.
3795 * Initializes the following fields in MonoClass:
3798 * Plus all the fields initialized by setup_interface_offsets ().
3799 * If there is an error during vtable construction, klass->exception_type is set.
3801 * LOCKING: Acquires the loader lock.
3804 mono_class_setup_vtable (MonoClass *klass)
3806 mono_class_setup_vtable_full (klass, NULL);
3810 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3812 MonoMethod **overrides;
3813 MonoGenericContext *context;
3821 if (MONO_CLASS_IS_INTERFACE (klass)) {
3822 /* This sets method->slot for all methods if this is an interface */
3823 mono_class_setup_methods (klass);
3827 if (klass->exception_type)
3830 if (g_list_find (in_setup, klass))
3833 mono_loader_lock ();
3835 if (klass->vtable) {
3836 mono_loader_unlock ();
3840 mono_stats.generic_vtable_count ++;
3841 in_setup = g_list_prepend (in_setup, klass);
3843 if (klass->generic_class) {
3844 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3845 mono_loader_unlock ();
3846 g_list_remove (in_setup, klass);
3850 context = mono_class_get_context (klass);
3851 type_token = klass->generic_class->container_class->type_token;
3853 context = (MonoGenericContext *) klass->generic_container;
3854 type_token = klass->type_token;
3857 if (image_is_dynamic (klass->image)) {
3858 /* Generic instances can have zero method overrides without causing any harm.
3859 * This is true since we don't do layout all over again for them, we simply inflate
3860 * the layout of the parent.
3862 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum);
3864 /* The following call fails if there are missing methods in the type */
3865 /* FIXME it's probably a good idea to avoid this for generic instances. */
3866 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3870 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3872 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3876 mono_loader_unlock ();
3877 g_list_remove (in_setup, klass);
3882 #define DEBUG_INTERFACE_VTABLE_CODE 0
3883 #define TRACE_INTERFACE_VTABLE_CODE 0
3884 #define VERIFY_INTERFACE_VTABLE_CODE 0
3885 #define VTABLE_SELECTOR (1)
3887 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3888 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3889 if (!(VTABLE_SELECTOR)) break; \
3893 #define DEBUG_INTERFACE_VTABLE(stmt)
3896 #if TRACE_INTERFACE_VTABLE_CODE
3897 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3898 if (!(VTABLE_SELECTOR)) break; \
3902 #define TRACE_INTERFACE_VTABLE(stmt)
3905 #if VERIFY_INTERFACE_VTABLE_CODE
3906 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3907 if (!(VTABLE_SELECTOR)) break; \
3911 #define VERIFY_INTERFACE_VTABLE(stmt)
3915 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3917 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3921 GString *res = g_string_new ("");
3923 g_string_append_c (res, '(');
3924 for (i = 0; i < sig->param_count; ++i) {
3926 g_string_append_c (res, ',');
3927 mono_type_get_desc (res, sig->params [i], include_namespace);
3929 g_string_append (res, ")=>");
3930 if (sig->ret != NULL) {
3931 mono_type_get_desc (res, sig->ret, include_namespace);
3933 g_string_append (res, "NULL");
3936 g_string_free (res, FALSE);
3940 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3941 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3942 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3943 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3951 is_wcf_hack_disabled (void)
3953 static gboolean disabled;
3954 static gboolean inited = FALSE;
3956 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3963 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3965 MonoMethodSignature *cmsig, *imsig;
3966 if (strcmp (im->name, cm->name) == 0) {
3967 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3968 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3971 if (! slot_is_empty) {
3972 if (require_newslot) {
3973 if (! interface_is_explicitly_implemented_by_class) {
3974 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3977 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3978 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3982 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3985 cmsig = mono_method_signature (cm);
3986 imsig = mono_method_signature (im);
3987 if (!cmsig || !imsig) {
3988 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3992 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3993 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3994 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3995 TRACE_INTERFACE_VTABLE (printf ("]"));
3998 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3999 if (mono_security_core_clr_enabled ())
4000 mono_security_core_clr_check_override (klass, cm, im);
4002 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4003 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4004 char *body_name = mono_method_full_name (cm, TRUE);
4005 char *decl_name = mono_method_full_name (im, TRUE);
4006 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));
4014 MonoClass *ic = im->klass;
4015 const char *ic_name_space = ic->name_space;
4016 const char *ic_name = ic->name;
4019 if (! require_newslot) {
4020 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4023 if (cm->klass->rank == 0) {
4024 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4027 cmsig = mono_method_signature (cm);
4028 imsig = mono_method_signature (im);
4029 if (!cmsig || !imsig) {
4030 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4034 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4035 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4036 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4037 TRACE_INTERFACE_VTABLE (printf ("]"));
4040 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4041 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4044 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4045 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4048 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))) {
4049 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4053 subname = strstr (cm->name, ic_name_space);
4054 if (subname != cm->name) {
4055 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4058 subname += strlen (ic_name_space);
4059 if (subname [0] != '.') {
4060 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4064 if (strstr (subname, ic_name) != subname) {
4065 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4068 subname += strlen (ic_name);
4069 if (subname [0] != '.') {
4070 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4074 if (strcmp (subname, im->name) != 0) {
4075 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4079 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4080 if (mono_security_core_clr_enabled ())
4081 mono_security_core_clr_check_override (klass, cm, im);
4083 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4084 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4085 char *body_name = mono_method_full_name (cm, TRUE);
4086 char *decl_name = mono_method_full_name (im, TRUE);
4087 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));
4097 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4099 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4100 MonoMethod *method = key;
4101 MonoMethod *override = value;
4102 MonoClass *method_class = mono_method_get_class (method);
4103 MonoClass *override_class = mono_method_get_class (override);
4105 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4106 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4107 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4110 print_overrides (GHashTable *override_map, const char *message) {
4112 printf ("Override map \"%s\" START:\n", message);
4113 g_hash_table_foreach (override_map, foreach_override, NULL);
4114 printf ("Override map \"%s\" END.\n", message);
4116 printf ("Override map \"%s\" EMPTY.\n", message);
4120 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4121 char *full_name = mono_type_full_name (&klass->byval_arg);
4125 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4127 if (print_interfaces) {
4128 print_implemented_interfaces (klass);
4129 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4132 if (klass->parent) {
4133 parent_size = klass->parent->vtable_size;
4137 for (i = 0; i < size; ++i) {
4138 MonoMethod *cm = vtable [i];
4139 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4140 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4142 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4150 #if VERIFY_INTERFACE_VTABLE_CODE
4152 mono_method_try_get_vtable_index (MonoMethod *method)
4154 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4155 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4156 if (imethod->declaring->is_generic)
4157 return imethod->declaring->slot;
4159 return method->slot;
4163 mono_class_verify_vtable (MonoClass *klass)
4166 char *full_name = mono_type_full_name (&klass->byval_arg);
4168 printf ("*** Verifying VTable of class '%s' \n", full_name);
4172 if (!klass->methods)
4175 for (i = 0; i < klass->method.count; ++i) {
4176 MonoMethod *cm = klass->methods [i];
4179 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4183 full_name = mono_method_full_name (cm, TRUE);
4185 slot = mono_method_try_get_vtable_index (cm);
4187 if (slot >= klass->vtable_size) {
4188 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4192 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4193 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4194 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4195 g_free (other_name);
4198 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4205 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4207 char *method_signature;
4210 for (index = 0; index < onum; ++index) {
4211 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4212 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4214 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4215 type_name = mono_type_full_name (&klass->byval_arg);
4216 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4217 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4218 g_free (method_signature);
4220 mono_class_setup_methods (klass);
4221 if (klass->exception_type) {
4222 char *name = mono_type_get_full_name (klass);
4223 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4227 for (index = 0; index < klass->method.count; ++index) {
4228 MonoMethod *cm = klass->methods [index];
4229 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4231 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4232 g_free (method_signature);
4237 mono_method_get_method_definition (MonoMethod *method)
4239 while (method->is_inflated)
4240 method = ((MonoMethodInflated*)method)->declaring;
4245 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4249 for (i = 0; i < onum; ++i) {
4250 MonoMethod *decl = overrides [i * 2];
4251 MonoMethod *body = overrides [i * 2 + 1];
4253 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4254 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4258 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4259 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4260 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4262 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4266 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4267 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4268 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4270 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4274 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4275 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"));
4279 body = mono_method_get_method_definition (body);
4280 decl = mono_method_get_method_definition (decl);
4282 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4283 char *body_name = mono_method_full_name (body, TRUE);
4284 char *decl_name = mono_method_full_name (decl, TRUE);
4285 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));
4295 mono_class_need_stelemref_method (MonoClass *klass)
4297 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4301 * LOCKING: this is supposed to be called with the loader lock held.
4304 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4308 MonoMethod **vtable;
4309 int i, max_vtsize = 0, cur_slot = 0;
4311 GPtrArray *ifaces = NULL;
4312 GHashTable *override_map = NULL;
4314 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4315 int first_non_interface_slot;
4317 GSList *virt_methods = NULL, *l;
4318 int stelemref_slot = 0;
4323 if (overrides && !verify_class_overrides (klass, overrides, onum))
4326 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4327 if (!mono_error_ok (&error)) {
4328 char *name = mono_type_get_full_name (klass);
4329 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)));
4331 mono_error_cleanup (&error);
4333 } else if (ifaces) {
4334 for (i = 0; i < ifaces->len; i++) {
4335 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4336 max_vtsize += ic->method.count;
4338 g_ptr_array_free (ifaces, TRUE);
4342 if (klass->parent) {
4343 mono_class_init (klass->parent);
4344 mono_class_setup_vtable_full (klass->parent, in_setup);
4346 if (klass->parent->exception_type) {
4347 char *name = mono_type_get_full_name (klass->parent);
4348 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4353 max_vtsize += klass->parent->vtable_size;
4354 cur_slot = klass->parent->vtable_size;
4357 max_vtsize += klass->method.count;
4359 /*Array have a slot for stelemref*/
4360 if (mono_class_need_stelemref_method (klass)) {
4361 stelemref_slot = cur_slot;
4366 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4367 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4369 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4371 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4372 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4375 max_iid = klass->max_interface_id;
4376 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4378 /* Optimized version for generic instances */
4379 if (klass->generic_class) {
4381 MonoClass *gklass = klass->generic_class->container_class;
4384 mono_class_setup_vtable_full (gklass, in_setup);
4385 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4386 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4390 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4391 klass->vtable_size = gklass->vtable_size;
4392 for (i = 0; i < gklass->vtable_size; ++i)
4393 if (gklass->vtable [i]) {
4394 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4395 if (!mono_error_ok (&error)) {
4396 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4397 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4399 mono_error_cleanup (&error);
4403 tmp [i]->slot = gklass->vtable [i]->slot;
4405 mono_memory_barrier ();
4406 klass->vtable = tmp;
4408 /* Have to set method->slot for abstract virtual methods */
4409 if (klass->methods && gklass->methods) {
4410 for (i = 0; i < klass->method.count; ++i)
4411 if (klass->methods [i]->slot == -1)
4412 klass->methods [i]->slot = gklass->methods [i]->slot;
4418 if (klass->parent && klass->parent->vtable_size) {
4419 MonoClass *parent = klass->parent;
4422 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4424 // Also inherit parent interface vtables, just as a starting point.
4425 // This is needed otherwise bug-77127.exe fails when the property methods
4426 // have different names in the iterface and the class, because for child
4427 // classes the ".override" information is not used anymore.
4428 for (i = 0; i < parent->interface_offsets_count; i++) {
4429 MonoClass *parent_interface = parent->interfaces_packed [i];
4430 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4431 /*FIXME this is now dead code as this condition will never hold true.
4432 Since interface offsets are inherited then the offset of an interface implemented
4433 by a parent will never be the out of it's vtable boundary.
4435 if (interface_offset >= parent->vtable_size) {
4436 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4439 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4440 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4441 for (j = 0; j < parent_interface->method.count && !klass->exception_type; j++) {
4442 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4443 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4444 parent_interface_offset + j, parent_interface_offset, j,
4445 interface_offset + j, interface_offset, j));
4452 /*Array have a slot for stelemref*/
4453 if (mono_class_need_stelemref_method (klass)) {
4454 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4456 method->slot = stelemref_slot;
4458 g_assert (method->slot == stelemref_slot);
4460 vtable [stelemref_slot] = method;
4463 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4464 /* override interface methods */
4465 for (i = 0; i < onum; i++) {
4466 MonoMethod *decl = overrides [i*2];
4467 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4469 dslot = mono_method_get_vtable_slot (decl);
4471 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4475 dslot += mono_class_interface_offset (klass, decl->klass);
4476 vtable [dslot] = overrides [i*2 + 1];
4477 vtable [dslot]->slot = dslot;
4479 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4481 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4483 if (mono_security_core_clr_enabled ())
4484 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4487 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4488 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4491 * Create a list of virtual methods to avoid calling
4492 * mono_class_get_virtual_methods () which is slow because of the metadata
4496 gpointer iter = NULL;
4499 virt_methods = NULL;
4500 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4501 virt_methods = g_slist_prepend (virt_methods, cm);
4503 if (klass->exception_type)
4507 // Loop on all implemented interfaces...
4508 for (i = 0; i < klass->interface_offsets_count; i++) {
4509 MonoClass *parent = klass->parent;
4511 gboolean interface_is_explicitly_implemented_by_class;
4514 ic = klass->interfaces_packed [i];
4515 ic_offset = mono_class_interface_offset (klass, ic);
4517 mono_class_setup_methods (ic);
4518 if (ic->exception_type)
4521 // Check if this interface is explicitly implemented (instead of just inherited)
4522 if (parent != NULL) {
4523 int implemented_interfaces_index;
4524 interface_is_explicitly_implemented_by_class = FALSE;
4525 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4526 if (ic == klass->interfaces [implemented_interfaces_index]) {
4527 interface_is_explicitly_implemented_by_class = TRUE;
4532 interface_is_explicitly_implemented_by_class = TRUE;
4535 // Loop on all interface methods...
4536 for (im_index = 0; im_index < ic->method.count; im_index++) {
4537 MonoMethod *im = ic->methods [im_index];
4538 int im_slot = ic_offset + im->slot;
4539 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4541 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4544 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4546 // If there is an explicit implementation, just use it right away,
4547 // otherwise look for a matching method
4548 if (override_im == NULL) {
4552 // First look for a suitable method among the class methods
4553 for (l = virt_methods; l; l = l->next) {
4554 cm = (MonoMethod *)l->data;
4555 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)));
4556 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4557 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4558 vtable [im_slot] = cm;
4559 /* Why do we need this? */
4564 TRACE_INTERFACE_VTABLE (printf ("\n"));
4565 if (klass->exception_type) /*Might be set by check_interface_method_override*/
4569 // If the slot is still empty, look in all the inherited virtual methods...
4570 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4571 MonoClass *parent = klass->parent;
4572 // Reverse order, so that last added methods are preferred
4573 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4574 MonoMethod *cm = parent->vtable [cm_index];
4576 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));
4577 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4578 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4579 vtable [im_slot] = cm;
4580 /* Why do we need this? */
4586 if (klass->exception_type) /*Might be set by check_interface_method_override*/
4588 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4592 g_assert (vtable [im_slot] == override_im);
4597 // If the class is not abstract, check that all its interface slots are full.
4598 // The check is done here and not directly at the end of the loop above because
4599 // it can happen (for injected generic array interfaces) that the same slot is
4600 // processed multiple times (those interfaces have overlapping slots), and it
4601 // will not always be the first pass the one that fills the slot.
4602 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4603 for (i = 0; i < klass->interface_offsets_count; i++) {
4607 ic = klass->interfaces_packed [i];
4608 ic_offset = mono_class_interface_offset (klass, ic);
4610 for (im_index = 0; im_index < ic->method.count; im_index++) {
4611 MonoMethod *im = ic->methods [im_index];
4612 int im_slot = ic_offset + im->slot;
4614 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4617 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4618 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4619 if (vtable [im_slot] == NULL) {
4620 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4627 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4628 for (l = virt_methods; l; l = l->next) {
4629 cm = (MonoMethod *)l->data;
4631 * If the method is REUSE_SLOT, we must check in the
4632 * base class for a method to override.
4634 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4636 for (k = klass->parent; k ; k = k->parent) {
4641 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4642 MonoMethodSignature *cmsig, *m1sig;
4644 cmsig = mono_method_signature (cm);
4645 m1sig = mono_method_signature (m1);
4647 if (!cmsig || !m1sig) {
4648 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4652 if (!strcmp(cm->name, m1->name) &&
4653 mono_metadata_signature_equal (cmsig, m1sig)) {
4655 if (mono_security_core_clr_enabled ())
4656 mono_security_core_clr_check_override (klass, cm, m1);
4658 slot = mono_method_get_vtable_slot (m1);
4662 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4663 char *body_name = mono_method_full_name (cm, TRUE);
4664 char *decl_name = mono_method_full_name (m1, TRUE);
4665 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));
4671 g_assert (cm->slot < max_vtsize);
4673 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4674 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4675 mono_method_full_name (m1, 1), m1,
4676 mono_method_full_name (cm, 1), cm));
4677 g_hash_table_insert (override_map, m1, cm);
4681 if (k->exception_type)
4691 /*Non final newslot methods must be given a non-interface vtable slot*/
4692 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4696 cm->slot = cur_slot++;
4698 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4699 vtable [cm->slot] = cm;
4702 /* override non interface methods */
4703 for (i = 0; i < onum; i++) {
4704 MonoMethod *decl = overrides [i*2];
4705 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4706 g_assert (decl->slot != -1);
4707 vtable [decl->slot] = overrides [i*2 + 1];
4708 overrides [i * 2 + 1]->slot = decl->slot;
4710 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4711 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4712 mono_method_full_name (decl, 1), decl,
4713 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4714 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4716 if (mono_security_core_clr_enabled ())
4717 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4722 * If a method occupies more than one place in the vtable, and it is
4723 * overriden, then change the other occurances too.
4728 for (i = 0; i < max_vtsize; ++i)
4730 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4732 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4737 g_hash_table_destroy (override_map);
4738 override_map = NULL;
4741 g_slist_free (virt_methods);
4742 virt_methods = NULL;
4744 /* Ensure that all vtable slots are filled with concrete instance methods */
4745 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4746 for (i = 0; i < cur_slot; ++i) {
4747 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4748 char *type_name = mono_type_get_full_name (klass);
4749 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4750 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));
4752 g_free (method_name);
4758 if (klass->generic_class) {
4759 MonoClass *gklass = klass->generic_class->container_class;
4761 mono_class_init (gklass);
4763 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4765 /* Check that the vtable_size value computed in mono_class_init () is correct */
4766 if (klass->vtable_size)
4767 g_assert (cur_slot == klass->vtable_size);
4768 klass->vtable_size = cur_slot;
4771 /* Try to share the vtable with our parent. */
4772 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4773 mono_memory_barrier ();
4774 klass->vtable = klass->parent->vtable;
4776 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4777 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4778 mono_memory_barrier ();
4779 klass->vtable = tmp;
4782 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4783 if (mono_print_vtable) {
4786 print_implemented_interfaces (klass);
4788 for (i = 0; i <= max_iid; i++)
4789 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4792 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4793 klass->vtable_size, icount);
4795 for (i = 0; i < cur_slot; ++i) {
4800 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4801 mono_method_full_name (cm, TRUE));
4807 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4808 klass->name, max_iid);
4810 for (i = 0; i < klass->interface_count; i++) {
4811 ic = klass->interfaces [i];
4812 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4813 mono_class_interface_offset (klass, ic),
4814 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4817 for (k = klass->parent; k ; k = k->parent) {
4818 for (i = 0; i < k->interface_count; i++) {
4819 ic = k->interfaces [i];
4820 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4821 mono_class_interface_offset (klass, ic),
4822 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4828 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4833 char *name = mono_type_get_full_name (klass);
4834 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4837 g_hash_table_destroy (override_map);
4839 g_slist_free (virt_methods);
4844 * mono_method_get_vtable_slot:
4846 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4847 * LOCKING: Acquires the loader lock.
4849 * FIXME Use proper MonoError machinery here.
4852 mono_method_get_vtable_slot (MonoMethod *method)
4854 if (method->slot == -1) {
4855 mono_class_setup_vtable (method->klass);
4856 if (method->klass->exception_type)
4858 if (method->slot == -1) {
4862 if (!method->klass->generic_class) {
4863 g_assert (method->is_inflated);
4864 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4867 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4868 g_assert (method->klass->generic_class);
4869 gklass = method->klass->generic_class->container_class;
4870 mono_class_setup_methods (method->klass);
4871 g_assert (method->klass->methods);
4872 for (i = 0; i < method->klass->method.count; ++i) {
4873 if (method->klass->methods [i] == method)
4876 g_assert (i < method->klass->method.count);
4877 g_assert (gklass->methods);
4878 method->slot = gklass->methods [i]->slot;
4880 g_assert (method->slot != -1);
4882 return method->slot;
4886 * mono_method_get_vtable_index:
4889 * Returns the index into the runtime vtable to access the method or,
4890 * in the case of a virtual generic method, the virtual generic method
4891 * thunk. Returns -1 on failure.
4893 * FIXME Use proper MonoError machinery here.
4896 mono_method_get_vtable_index (MonoMethod *method)
4898 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4899 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4900 if (imethod->declaring->is_generic)
4901 return mono_method_get_vtable_slot (imethod->declaring);
4903 return mono_method_get_vtable_slot (method);
4906 static MonoMethod *default_ghc = NULL;
4907 static MonoMethod *default_finalize = NULL;
4908 static int finalize_slot = -1;
4909 static int ghc_slot = -1;
4912 initialize_object_slots (MonoClass *klass)
4917 if (klass == mono_defaults.object_class) {
4918 mono_class_setup_vtable (klass);
4919 for (i = 0; i < klass->vtable_size; ++i) {
4920 MonoMethod *cm = klass->vtable [i];
4922 if (!strcmp (cm->name, "GetHashCode"))
4924 else if (!strcmp (cm->name, "Finalize"))
4928 g_assert (ghc_slot > 0);
4929 default_ghc = klass->vtable [ghc_slot];
4931 g_assert (finalize_slot > 0);
4932 default_finalize = klass->vtable [finalize_slot];
4937 MonoMethod *array_method;
4939 } GenericArrayMethodInfo;
4941 static int generic_array_method_num = 0;
4942 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4945 generic_array_methods (MonoClass *klass)
4947 int i, count_generic = 0;
4948 GList *list = NULL, *tmp;
4949 if (generic_array_method_num)
4950 return generic_array_method_num;
4951 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4952 g_assert (!klass->parent->exception_type); /*So hitting this assert is a huge problem*/
4953 for (i = 0; i < klass->parent->method.count; i++) {
4954 MonoMethod *m = klass->parent->methods [i];
4955 if (!strncmp (m->name, "InternalArray__", 15)) {
4957 list = g_list_prepend (list, m);
4960 list = g_list_reverse (list);
4961 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4963 for (tmp = list; tmp; tmp = tmp->next) {
4964 const char *mname, *iname;
4966 MonoMethod *m = (MonoMethod *)tmp->data;
4967 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4968 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4970 generic_array_method_info [i].array_method = m;
4971 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4972 iname = "System.Collections.Generic.ICollection`1.";
4973 mname = m->name + 27;
4974 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4975 iname = "System.Collections.Generic.IEnumerable`1.";
4976 mname = m->name + 27;
4977 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4978 iname = "System.Collections.Generic.IReadOnlyList`1.";
4979 mname = m->name + strlen (ireadonlylist_prefix);
4980 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4981 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4982 mname = m->name + strlen (ireadonlycollection_prefix);
4983 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4984 iname = "System.Collections.Generic.IList`1.";
4985 mname = m->name + 15;
4987 g_assert_not_reached ();
4990 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4991 strcpy (name, iname);
4992 strcpy (name + strlen (iname), mname);
4993 generic_array_method_info [i].name = name;
4996 /*g_print ("array generic methods: %d\n", count_generic);*/
4998 generic_array_method_num = count_generic;
5000 return generic_array_method_num;
5004 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5006 MonoGenericContext tmp_context;
5009 tmp_context.class_inst = NULL;
5010 tmp_context.method_inst = iface->generic_class->context.class_inst;
5011 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5013 for (i = 0; i < generic_array_method_num; i++) {
5015 MonoMethod *m = generic_array_method_info [i].array_method;
5016 MonoMethod *inflated;
5018 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5019 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5020 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5025 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5027 int null_length = strlen ("(null)");
5028 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5029 char *s = (char *)mono_image_alloc (image, len);
5032 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5033 g_assert (result == len - 1);
5039 set_failure_from_loader_error (MonoClass *klass, MonoLoaderError *error)
5041 gpointer exception_data = NULL;
5043 switch (error->exception_type) {
5044 case MONO_EXCEPTION_TYPE_LOAD:
5045 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->assembly_name);
5048 case MONO_EXCEPTION_MISSING_METHOD:
5049 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->member_name);
5052 case MONO_EXCEPTION_MISSING_FIELD: {
5053 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5054 const char *class_name;
5057 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5059 class_name = error->klass->name;
5061 exception_data = concat_two_strings_with_zero (klass->image, class_name, error->member_name);
5064 g_free ((void*)class_name);
5068 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5071 if (error->ref_only)
5072 msg = "Cannot resolve dependency to assembly '%s' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.";
5074 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5076 exception_data = concat_two_strings_with_zero (klass->image, msg, error->assembly_name);
5080 case MONO_EXCEPTION_BAD_IMAGE:
5081 exception_data = error->msg;
5085 g_assert_not_reached ();
5088 mono_class_set_failure (klass, error->exception_type, exception_data);
5093 * @class: the class to initialize
5095 * Compute the instance_size, class_size and other infos that cannot be
5096 * computed at mono_class_get() time. Also compute vtable_size if possible.
5097 * Returns TRUE on success or FALSE if there was a problem in loading
5098 * the type (incorrect assemblies, missing assemblies, methods, etc).
5100 * LOCKING: Acquires the loader lock.
5103 mono_class_init (MonoClass *klass)
5106 MonoCachedClassInfo cached_info;
5107 gboolean has_cached_info;
5111 /* Double-checking locking pattern */
5112 if (klass->inited || klass->exception_type)
5113 return klass->exception_type == MONO_EXCEPTION_NONE;
5115 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5117 /* We do everything inside the lock to prevent races */
5118 mono_loader_lock ();
5120 if (klass->inited || klass->exception_type) {
5121 mono_loader_unlock ();
5122 /* Somebody might have gotten in before us */
5123 return klass->exception_type == MONO_EXCEPTION_NONE;
5126 if (klass->init_pending) {
5127 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5131 klass->init_pending = 1;
5133 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5134 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5139 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5140 MonoClass *element_class = klass->element_class;
5141 if (!element_class->inited)
5142 mono_class_init (element_class);
5143 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5144 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5149 mono_stats.initialized_class_count++;
5151 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5152 MonoClass *gklass = klass->generic_class->container_class;
5154 mono_stats.generic_class_count++;
5156 klass->method = gklass->method;
5157 klass->field = gklass->field;
5159 mono_class_init (gklass);
5160 // FIXME: Why is this needed ?
5161 if (!gklass->exception_type)
5162 mono_class_setup_methods (gklass);
5163 if (gklass->exception_type) {
5164 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5168 if (MONO_CLASS_IS_INTERFACE (klass))
5169 klass->interface_id = mono_get_unique_iid (klass);
5172 if (klass->parent && !klass->parent->inited)
5173 mono_class_init (klass->parent);
5175 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5177 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5178 klass->nested_classes_inited = TRUE;
5181 * Computes the size used by the fields, and their locations
5183 if (has_cached_info) {
5184 klass->instance_size = cached_info.instance_size;
5185 klass->sizes.class_size = cached_info.class_size;
5186 klass->packing_size = cached_info.packing_size;
5187 klass->min_align = cached_info.min_align;
5188 klass->blittable = cached_info.blittable;
5189 klass->has_references = cached_info.has_references;
5190 klass->has_static_refs = cached_info.has_static_refs;
5191 klass->no_special_static_fields = cached_info.no_special_static_fields;
5194 if (!klass->size_inited){
5195 mono_class_setup_fields (klass);
5196 if (klass->exception_type || mono_loader_get_last_error ())
5200 /* Initialize arrays */
5202 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5204 if (klass->interface_count) {
5205 int count_generic = generic_array_methods (klass);
5206 klass->method.count += klass->interface_count * count_generic;
5210 mono_class_setup_supertypes (klass);
5213 initialize_object_slots (klass);
5216 * Initialize the rest of the data without creating a generic vtable if possible.
5217 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5218 * also avoid computing a generic vtable.
5220 if (has_cached_info) {
5222 klass->vtable_size = cached_info.vtable_size;
5223 klass->has_finalize = cached_info.has_finalize;
5224 klass->has_finalize_inited = TRUE;
5225 klass->ghcimpl = cached_info.ghcimpl;
5226 klass->has_cctor = cached_info.has_cctor;
5227 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5228 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5229 * The first slot if for array with.
5231 static int szarray_vtable_size[2] = { 0 };
5233 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5236 if (!szarray_vtable_size [slot]) {
5237 mono_class_setup_vtable (klass);
5238 szarray_vtable_size [slot] = klass->vtable_size;
5240 klass->vtable_size = szarray_vtable_size[slot];
5242 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5243 MonoClass *gklass = klass->generic_class->container_class;
5245 /* Generic instance case */
5246 klass->ghcimpl = gklass->ghcimpl;
5247 klass->has_cctor = gklass->has_cctor;
5249 mono_class_setup_vtable (gklass);
5250 if (gklass->exception_type) {
5251 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5255 klass->vtable_size = gklass->vtable_size;
5259 /* ghcimpl is not currently used
5261 if (klass->parent) {
5262 MonoMethod *cmethod = klass->vtable [ghc_slot];
5263 if (cmethod->is_inflated)
5264 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5265 if (cmethod == default_ghc) {
5271 /* C# doesn't allow interfaces to have cctors */
5272 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5273 MonoMethod *cmethod = NULL;
5275 if (klass->type_token && !image_is_dynamic(klass->image)) {
5276 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5277 /* The find_method function ignores the 'flags' argument */
5278 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5279 klass->has_cctor = 1;
5281 mono_class_setup_methods (klass);
5282 if (klass->exception_type)
5285 for (i = 0; i < klass->method.count; ++i) {
5286 MonoMethod *method = klass->methods [i];
5287 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5288 (strcmp (".cctor", method->name) == 0)) {
5289 klass->has_cctor = 1;
5297 if (klass->parent) {
5298 int first_iface_slot;
5299 /* This will compute klass->parent->vtable_size for some classes */
5300 mono_class_init (klass->parent);
5301 if (klass->parent->exception_type) {
5302 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5305 if (mono_loader_get_last_error ())
5307 if (!klass->parent->vtable_size) {
5308 /* FIXME: Get rid of this somehow */
5309 mono_class_setup_vtable (klass->parent);
5310 if (klass->parent->exception_type) {
5311 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5314 if (mono_loader_get_last_error ())
5317 first_iface_slot = klass->parent->vtable_size;
5318 if (mono_class_need_stelemref_method (klass))
5320 setup_interface_offsets (klass, first_iface_slot, TRUE);
5322 setup_interface_offsets (klass, 0, TRUE);
5325 if (mono_security_core_clr_enabled ())
5326 mono_security_core_clr_check_inheritance (klass);
5328 if (mono_loader_get_last_error ()) {
5329 if (klass->exception_type == MONO_EXCEPTION_NONE) {
5330 set_failure_from_loader_error (klass, mono_loader_get_last_error ());
5332 mono_loader_clear_error ();
5335 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5336 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5341 /* Because of the double-checking locking pattern */
5342 mono_memory_barrier ();
5344 klass->init_pending = 0;
5346 mono_loader_unlock ();
5348 return klass->exception_type == MONO_EXCEPTION_NONE;
5352 * mono_class_has_finalizer:
5354 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5358 mono_class_has_finalizer (MonoClass *klass)
5360 gboolean has_finalize = FALSE;
5362 if (klass->has_finalize_inited)
5363 return klass->has_finalize;
5365 /* Interfaces and valuetypes are not supposed to have finalizers */
5366 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5367 MonoMethod *cmethod = NULL;
5369 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5370 } else if (klass->generic_class) {
5371 MonoClass *gklass = klass->generic_class->container_class;
5373 has_finalize = mono_class_has_finalizer (gklass);
5374 } else if (klass->parent && klass->parent->has_finalize) {
5375 has_finalize = TRUE;
5377 if (klass->parent) {
5379 * Can't search in metadata for a method named Finalize, because that
5380 * ignores overrides.
5382 mono_class_setup_vtable (klass);
5383 if (klass->exception_type || mono_loader_get_last_error ())
5386 cmethod = klass->vtable [finalize_slot];
5390 g_assert (klass->vtable_size > finalize_slot);
5392 if (klass->parent) {
5393 if (cmethod->is_inflated)
5394 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5395 if (cmethod != default_finalize)
5396 has_finalize = TRUE;
5402 mono_image_lock (klass->image);
5404 if (!klass->has_finalize_inited) {
5405 klass->has_finalize = has_finalize ? 1 : 0;
5407 mono_memory_barrier ();
5408 klass->has_finalize_inited = TRUE;
5411 mono_image_unlock (klass->image);
5413 return klass->has_finalize;
5417 mono_is_corlib_image (MonoImage *image)
5419 /* FIXME: allow the dynamic case for our compilers and with full trust */
5420 if (image_is_dynamic (image))
5421 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5423 return image == mono_defaults.corlib;
5427 * LOCKING: this assumes the loader lock is held
5430 mono_class_setup_mono_type (MonoClass *klass)
5432 const char *name = klass->name;
5433 const char *nspace = klass->name_space;
5434 gboolean is_corlib = mono_is_corlib_image (klass->image);
5436 klass->this_arg.byref = 1;
5437 klass->this_arg.data.klass = klass;
5438 klass->this_arg.type = MONO_TYPE_CLASS;
5439 klass->byval_arg.data.klass = klass;
5440 klass->byval_arg.type = MONO_TYPE_CLASS;
5442 if (is_corlib && !strcmp (nspace, "System")) {
5443 if (!strcmp (name, "ValueType")) {
5445 * do not set the valuetype bit for System.ValueType.
5446 * klass->valuetype = 1;
5448 klass->blittable = TRUE;
5449 } else if (!strcmp (name, "Enum")) {
5451 * do not set the valuetype bit for System.Enum.
5452 * klass->valuetype = 1;
5454 klass->valuetype = 0;
5455 klass->enumtype = 0;
5456 } else if (!strcmp (name, "Object")) {
5457 klass->byval_arg.type = MONO_TYPE_OBJECT;
5458 klass->this_arg.type = MONO_TYPE_OBJECT;
5459 } else if (!strcmp (name, "String")) {
5460 klass->byval_arg.type = MONO_TYPE_STRING;
5461 klass->this_arg.type = MONO_TYPE_STRING;
5462 } else if (!strcmp (name, "TypedReference")) {
5463 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5464 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5468 if (klass->valuetype) {
5469 int t = MONO_TYPE_VALUETYPE;
5471 if (is_corlib && !strcmp (nspace, "System")) {
5474 if (!strcmp (name, "Boolean")) {
5475 t = MONO_TYPE_BOOLEAN;
5476 } else if (!strcmp(name, "Byte")) {
5478 klass->blittable = TRUE;
5482 if (!strcmp (name, "Char")) {
5487 if (!strcmp (name, "Double")) {
5489 klass->blittable = TRUE;
5493 if (!strcmp (name, "Int32")) {
5495 klass->blittable = TRUE;
5496 } else if (!strcmp(name, "Int16")) {
5498 klass->blittable = TRUE;
5499 } else if (!strcmp(name, "Int64")) {
5501 klass->blittable = TRUE;
5502 } else if (!strcmp(name, "IntPtr")) {
5504 klass->blittable = TRUE;
5508 if (!strcmp (name, "Single")) {
5510 klass->blittable = TRUE;
5511 } else if (!strcmp(name, "SByte")) {
5513 klass->blittable = TRUE;
5517 if (!strcmp (name, "UInt32")) {
5519 klass->blittable = TRUE;
5520 } else if (!strcmp(name, "UInt16")) {
5522 klass->blittable = TRUE;
5523 } else if (!strcmp(name, "UInt64")) {
5525 klass->blittable = TRUE;
5526 } else if (!strcmp(name, "UIntPtr")) {
5528 klass->blittable = TRUE;
5532 if (!strcmp (name, "TypedReference")) {
5533 t = MONO_TYPE_TYPEDBYREF;
5534 klass->blittable = TRUE;
5538 if (!strcmp (name, "Void")) {
5546 klass->byval_arg.type = (MonoTypeEnum)t;
5547 klass->this_arg.type = (MonoTypeEnum)t;
5550 if (MONO_CLASS_IS_INTERFACE (klass))
5551 klass->interface_id = mono_get_unique_iid (klass);
5557 * COM initialization is delayed until needed.
5558 * However when a [ComImport] attribute is present on a type it will trigger
5559 * the initialization. This is not a problem unless the BCL being executed
5560 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5563 init_com_from_comimport (MonoClass *klass)
5565 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5566 if (mono_security_core_clr_enabled ()) {
5567 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5568 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5569 /* but it can not be made available for application (i.e. user code) since all COM calls
5570 * are considered native calls. In this case we fail with a TypeLoadException (just like
5571 * Silverlight 2 does */
5572 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5577 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5579 #endif /*DISABLE_COM*/
5582 * LOCKING: this assumes the loader lock is held
5585 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5587 gboolean system_namespace;
5588 gboolean is_corlib = mono_is_corlib_image (klass->image);
5590 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5592 /* if root of the hierarchy */
5593 if (system_namespace && !strcmp (klass->name, "Object")) {
5594 klass->parent = NULL;
5595 klass->instance_size = sizeof (MonoObject);
5598 if (!strcmp (klass->name, "<Module>")) {
5599 klass->parent = NULL;
5600 klass->instance_size = 0;
5604 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5605 /* Imported COM Objects always derive from __ComObject. */
5607 if (MONO_CLASS_IS_IMPORT (klass)) {
5608 init_com_from_comimport (klass);
5609 if (parent == mono_defaults.object_class)
5610 parent = mono_class_get_com_object_class ();
5614 /* set the parent to something useful and safe, but mark the type as broken */
5615 parent = mono_defaults.object_class;
5616 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5619 klass->parent = parent;
5621 if (parent->generic_class && !parent->name) {
5623 * If the parent is a generic instance, we may get
5624 * called before it is fully initialized, especially
5625 * before it has its name.
5630 #ifndef DISABLE_REMOTING
5631 klass->marshalbyref = parent->marshalbyref;
5632 klass->contextbound = parent->contextbound;
5635 klass->delegate = parent->delegate;
5637 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5638 mono_class_set_is_com_object (klass);
5640 if (system_namespace) {
5641 #ifndef DISABLE_REMOTING
5642 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5643 klass->marshalbyref = 1;
5645 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5646 klass->contextbound = 1;
5648 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5649 klass->delegate = 1;
5652 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5653 (strcmp (klass->parent->name_space, "System") == 0)))
5654 klass->valuetype = 1;
5655 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5656 klass->valuetype = klass->enumtype = 1;
5658 /*klass->enumtype = klass->parent->enumtype; */
5660 /* initialize com types if COM interfaces are present */
5662 if (MONO_CLASS_IS_IMPORT (klass))
5663 init_com_from_comimport (klass);
5665 klass->parent = NULL;
5671 * mono_class_setup_supertypes:
5674 * Build the data structure needed to make fast type checks work.
5675 * This currently sets two fields in @class:
5676 * - idepth: distance between @class and System.Object in the type
5678 * - supertypes: array of classes: each element has a class in the hierarchy
5679 * starting from @class up to System.Object
5681 * LOCKING: This function is atomic, in case of contention we waste memory.
5684 mono_class_setup_supertypes (MonoClass *klass)
5687 MonoClass **supertypes;
5689 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5693 if (klass->parent && !klass->parent->supertypes)
5694 mono_class_setup_supertypes (klass->parent);
5696 klass->idepth = klass->parent->idepth + 1;
5700 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5701 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5703 if (klass->parent) {
5704 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5707 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5708 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5710 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5713 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5717 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5719 MonoClass *gtd = (MonoClass*)user_data;
5720 /* Only try to fix generic instances of @gtd */
5721 if (gclass->generic_class->container_class != gtd)
5724 /* Check if the generic instance has no parent. */
5725 if (gtd->parent && !gclass->parent)
5726 mono_generic_class_setup_parent (gclass, gtd);
5732 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5734 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5735 mono_error_set_type_load_class (error, klass, msg);
5739 mono_class_set_failure_from_loader_error (MonoClass *klass, MonoError *error, char *msg)
5741 MonoLoaderError *lerror = mono_loader_get_last_error ();
5744 set_failure_from_loader_error (klass, lerror);
5745 mono_error_set_from_loader_error (error);
5749 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, msg);
5750 mono_error_set_type_load_class (error, klass, msg);
5755 * mono_class_create_from_typedef:
5756 * @image: image where the token is valid
5757 * @type_token: typedef token
5758 * @error: used to return any error found while creating the type
5760 * Create the MonoClass* representing the specified type token.
5761 * @type_token must be a TypeDef token.
5763 * FIXME: don't return NULL on failure, just the the caller figure it out.
5766 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5768 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5769 MonoClass *klass, *parent = NULL;
5770 guint32 cols [MONO_TYPEDEF_SIZE];
5771 guint32 cols_next [MONO_TYPEDEF_SIZE];
5772 guint tidx = mono_metadata_token_index (type_token);
5773 MonoGenericContext *context = NULL;
5774 const char *name, *nspace;
5776 MonoClass **interfaces;
5777 guint32 field_last, method_last;
5778 guint32 nesting_tokeen;
5780 mono_error_init (error);
5782 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5783 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5784 mono_loader_assert_no_error ();
5788 mono_loader_lock ();
5790 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5791 mono_loader_unlock ();
5792 mono_loader_assert_no_error ();
5796 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5798 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5799 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5801 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5804 klass->name_space = nspace;
5806 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5808 klass->image = image;
5809 klass->type_token = type_token;
5810 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5812 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5814 classes_size += sizeof (MonoClass);
5817 * Check whether we're a generic type definition.
5819 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5820 if (klass->generic_container) {
5821 klass->is_generic = 1;
5822 klass->generic_container->owner.klass = klass;
5823 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5824 context = &klass->generic_container->context;
5827 if (klass->generic_container)
5828 enable_gclass_recording ();
5830 if (cols [MONO_TYPEDEF_EXTENDS]) {
5832 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5834 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5835 /*WARNING: this must satisfy mono_metadata_type_hash*/
5836 klass->this_arg.byref = 1;
5837 klass->this_arg.data.klass = klass;
5838 klass->this_arg.type = MONO_TYPE_CLASS;
5839 klass->byval_arg.data.klass = klass;
5840 klass->byval_arg.type = MONO_TYPE_CLASS;
5842 parent = mono_class_get_checked (image, parent_token, error);
5843 if (parent && context) /* Always inflate */
5844 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5846 if (parent == NULL) {
5847 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5848 goto parent_failure;
5851 for (tmp = parent; tmp; tmp = tmp->parent) {
5853 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5854 goto parent_failure;
5856 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5857 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5858 goto parent_failure;
5863 mono_class_setup_parent (klass, parent);
5865 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5866 mono_class_setup_mono_type (klass);
5868 if (klass->generic_container)
5869 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5872 * This might access klass->byval_arg for recursion generated by generic constraints,
5873 * so it has to come after setup_mono_type ().
5875 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5876 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5877 if (!mono_error_ok (error)) {
5878 /*FIXME implement a mono_class_set_failure_from_mono_error */
5879 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5880 mono_loader_unlock ();
5881 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5882 mono_loader_assert_no_error ();
5887 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5891 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5895 klass->cast_class = klass->element_class = klass;
5897 if (!klass->enumtype) {
5898 if (!mono_metadata_interfaces_from_typedef_full (
5899 image, type_token, &interfaces, &icount, FALSE, context, error)){
5901 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5902 mono_loader_unlock ();
5903 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5907 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5908 g_assert(icount <= 65535);
5910 klass->interfaces = interfaces;
5911 klass->interface_count = icount;
5912 klass->interfaces_inited = 1;
5915 /*g_print ("Load class %s\n", name);*/
5918 * Compute the field and method lists
5920 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5921 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5923 if (tt->rows > tidx){
5924 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5925 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5926 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5928 field_last = image->tables [MONO_TABLE_FIELD].rows;
5929 method_last = image->tables [MONO_TABLE_METHOD].rows;
5932 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5933 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5934 klass->field.count = field_last - klass->field.first;
5936 klass->field.count = 0;
5938 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5939 klass->method.count = method_last - klass->method.first;
5941 klass->method.count = 0;
5943 /* reserve space to store vector pointer in arrays */
5944 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5945 klass->instance_size += 2 * sizeof (gpointer);
5946 g_assert (klass->field.count == 0);
5949 if (klass->enumtype) {
5950 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5951 if (!enum_basetype) {
5952 /*set it to a default value as the whole runtime can't handle this to be null*/
5953 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5954 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5955 mono_loader_unlock ();
5956 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5957 mono_loader_assert_no_error ();
5960 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5964 * If we're a generic type definition, load the constraints.
5965 * We must do this after the class has been constructed to make certain recursive scenarios
5968 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5969 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)));
5970 mono_loader_unlock ();
5971 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5972 mono_loader_assert_no_error ();
5976 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5977 if (!strncmp (name, "Vector", 6))
5978 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");
5981 mono_loader_unlock ();
5983 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5984 mono_loader_assert_no_error ();
5989 mono_class_setup_mono_type (klass);
5990 mono_loader_unlock ();
5991 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5992 mono_loader_assert_no_error ();
5996 /** Is klass a Nullable<T> ginst? */
5998 mono_class_is_nullable (MonoClass *klass)
6000 return klass->generic_class != NULL &&
6001 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
6005 /** if klass is T? return T */
6007 mono_class_get_nullable_param (MonoClass *klass)
6009 g_assert (mono_class_is_nullable (klass));
6010 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
6014 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
6018 MonoGenericClass *gclass = klass->generic_class;
6020 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
6021 if (!mono_error_ok (&error)) {
6022 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6023 klass->parent = mono_defaults.object_class;
6024 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6025 mono_error_cleanup (&error);
6029 mono_class_setup_parent (klass, klass->parent);
6031 if (klass->enumtype) {
6032 klass->cast_class = gtd->cast_class;
6033 klass->element_class = gtd->element_class;
6039 * Create the `MonoClass' for an instantiation of a generic type.
6040 * We only do this if we actually need it.
6043 mono_generic_class_get_class (MonoGenericClass *gclass)
6045 MonoClass *klass, *gklass;
6047 if (gclass->cached_class)
6048 return gclass->cached_class;
6050 mono_loader_lock ();
6051 if (gclass->cached_class) {
6052 mono_loader_unlock ();
6053 return gclass->cached_class;
6056 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6058 gklass = gclass->container_class;
6060 if (record_gclass_instantiation > 0)
6061 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6063 if (gklass->nested_in) {
6064 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6065 klass->nested_in = gklass->nested_in;
6068 klass->name = gklass->name;
6069 klass->name_space = gklass->name_space;
6071 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6073 klass->image = gklass->image;
6074 klass->flags = gklass->flags;
6075 klass->type_token = gklass->type_token;
6076 klass->field.count = gklass->field.count;
6078 klass->is_inflated = 1;
6079 klass->generic_class = gclass;
6081 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6082 klass->this_arg.type = klass->byval_arg.type;
6083 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6084 klass->this_arg.byref = TRUE;
6085 klass->enumtype = gklass->enumtype;
6086 klass->valuetype = gklass->valuetype;
6088 klass->cast_class = klass->element_class = klass;
6090 if (mono_class_is_nullable (klass))
6091 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6094 * We're not interested in the nested classes of a generic instance.
6095 * We use the generic type definition to look for nested classes.
6098 mono_generic_class_setup_parent (klass, gklass);
6100 if (gclass->is_dynamic) {
6102 * 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.
6103 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6104 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6106 if (!gklass->wastypebuilder)
6109 mono_class_setup_supertypes (klass);
6111 if (klass->enumtype) {
6113 * For enums, gklass->fields might not been set, but instance_size etc. is
6114 * already set in mono_reflection_create_internal_class (). For non-enums,
6115 * these will be computed normally in mono_class_layout_fields ().
6117 klass->instance_size = gklass->instance_size;
6118 klass->sizes.class_size = gklass->sizes.class_size;
6119 mono_memory_barrier ();
6120 klass->size_inited = 1;
6124 mono_memory_barrier ();
6125 gclass->cached_class = klass;
6127 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6129 inflated_classes ++;
6130 inflated_classes_size += sizeof (MonoClass);
6132 mono_loader_unlock ();
6138 get_image_for_container (MonoGenericContainer *container)
6141 if (container->is_anonymous) {
6142 result = container->owner.image;
6145 if (container->is_method) {
6146 MonoMethod *method = container->owner.method;
6147 g_assert_checked (method);
6148 klass = method->klass;
6150 klass = container->owner.klass;
6152 g_assert_checked (klass);
6153 result = klass->image;
6160 get_image_for_generic_param (MonoGenericParam *param)
6162 MonoGenericContainer *container = mono_generic_param_owner (param);
6163 g_assert_checked (container);
6164 return get_image_for_container (container);
6167 // Make a string in the designated image consisting of a single integer.
6168 #define INT_STRING_SIZE 16
6170 make_generic_name_string (MonoImage *image, int num)
6172 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6173 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6177 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6178 // pinfo is derived from param by the caller for us.
6180 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6182 MonoClass *klass, **ptr;
6184 MonoGenericContainer *container = mono_generic_param_owner (param);
6185 g_assert_checked (container);
6187 MonoImage *image = get_image_for_container (container);
6188 gboolean is_mvar = container->is_method;
6189 gboolean is_anonymous = container->is_anonymous;
6191 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6192 classes_size += sizeof (MonoClass);
6195 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6197 int n = mono_generic_param_num (param);
6198 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6202 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6203 } else if (is_mvar) {
6204 MonoMethod *omethod = container->owner.method;
6205 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6207 MonoClass *oklass = container->owner.klass;
6208 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6211 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6213 // Count non-NULL items in pinfo->constraints
6216 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6220 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6221 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6223 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6224 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_from_name (mono_defaults.corlib, "System", "ValueType") );
6226 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6229 if (count - pos > 0) {
6230 klass->interface_count = count - pos;
6231 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6232 klass->interfaces_inited = TRUE;
6233 for (i = pos; i < count; i++)
6234 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6237 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6239 klass->inited = TRUE;
6240 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6241 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6242 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6244 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6245 klass->this_arg.type = klass->byval_arg.type;
6246 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6247 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6248 klass->this_arg.byref = TRUE;
6250 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6251 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6253 /*Init these fields to sane values*/
6254 klass->min_align = 1;
6256 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6257 * constrained to, the JIT depends on this.
6259 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6260 mono_memory_barrier ();
6261 klass->size_inited = 1;
6262 klass->setup_fields_called = 1;
6264 mono_class_setup_supertypes (klass);
6266 if (count - pos > 0) {
6267 mono_class_setup_vtable (klass->parent);
6268 if (klass->parent->exception_type)
6269 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6271 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6277 #define FAST_CACHE_SIZE 16
6280 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6281 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6282 * we cache the MonoClasses.
6283 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6284 * LOCKING: Takes the image lock depending on @take_lock.
6287 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6289 int n = mono_generic_param_num (param);
6290 MonoImage *image = get_image_for_generic_param (param);
6291 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6292 MonoClass *klass = NULL;
6297 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6298 // For high numbers or constraints we have to use pointer hashes.
6299 if (param->gshared_constraint) {
6300 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6303 mono_image_lock (image);
6304 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6306 mono_image_unlock (image);
6311 if (n < FAST_CACHE_SIZE) {
6313 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6315 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6317 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6320 mono_image_lock (image);
6321 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6323 mono_image_unlock (image);
6330 * LOCKING: Image lock (param->image) must be held
6333 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6335 int n = mono_generic_param_num (param);
6336 MonoImage *image = get_image_for_generic_param (param);
6337 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6341 if (param->gshared_constraint) {
6342 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6344 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6345 mono_memory_barrier ();
6347 image->mvar_cache_constrained = ht;
6349 image->var_cache_constrained = ht;
6351 g_hash_table_insert (ht, param, klass);
6352 } else if (n < FAST_CACHE_SIZE) {
6354 /* Requires locking to avoid droping an already published class */
6355 if (!image->mvar_cache_fast)
6356 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6357 image->mvar_cache_fast [n] = klass;
6359 if (!image->var_cache_fast)
6360 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6361 image->var_cache_fast [n] = klass;
6364 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6366 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6368 ht = g_hash_table_new (NULL, NULL);
6369 mono_memory_barrier ();
6371 image->mvar_cache_slow = ht;
6373 image->var_cache_slow = ht;
6376 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6381 * LOCKING: Acquires the image lock (@image).
6384 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6386 MonoImage *image = get_image_for_generic_param (param);
6387 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6388 MonoClass *klass, *klass2;
6390 // If a klass already exists for this object and is cached, return it.
6391 if (pinfo) // Non-anonymous
6392 klass = pinfo->pklass;
6394 klass = get_anon_gparam_class (param, TRUE);
6399 // Create a new klass
6400 klass = make_generic_param_class (param, pinfo);
6402 // Now we need to cache the klass we created.
6403 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6404 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6405 // and allow our newly-created klass object to just leak.
6406 mono_memory_barrier ();
6408 mono_image_lock (image);
6410 // Here "klass2" refers to the klass potentially created by the other thread.
6411 if (pinfo) // Repeat check from above
6412 klass2 = pinfo->pklass;
6414 klass2 = get_anon_gparam_class (param, FALSE);
6421 pinfo->pklass = klass;
6423 set_anon_gparam_class (param, klass);
6425 mono_image_unlock (image);
6427 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6429 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6431 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6437 * mono_class_from_generic_parameter:
6438 * @param: Parameter to find/construct a class for.
6439 * @arg2: Is ignored.
6440 * @arg3: Is ignored.
6443 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6445 return mono_class_from_generic_parameter_internal (param);
6450 mono_ptr_class_get (MonoType *type)
6453 MonoClass *el_class;
6457 el_class = mono_class_from_mono_type (type);
6458 image = el_class->image;
6460 mono_image_lock (image);
6461 if (image->ptr_cache) {
6462 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6463 mono_image_unlock (image);
6467 mono_image_unlock (image);
6469 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6471 classes_size += sizeof (MonoClass);
6473 result->parent = NULL; /* no parent for PTR types */
6474 result->name_space = el_class->name_space;
6475 name = g_strdup_printf ("%s*", el_class->name);
6476 result->name = mono_image_strdup (image, name);
6479 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6481 result->image = el_class->image;
6482 result->inited = TRUE;
6483 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6484 /* Can pointers get boxed? */
6485 result->instance_size = sizeof (gpointer);
6486 result->cast_class = result->element_class = el_class;
6487 result->blittable = TRUE;
6489 result->byval_arg.type = MONO_TYPE_PTR;
6490 result->this_arg.type = result->byval_arg.type;
6491 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6492 result->this_arg.byref = TRUE;
6494 mono_class_setup_supertypes (result);
6496 mono_image_lock (image);
6497 if (image->ptr_cache) {
6499 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6500 mono_image_unlock (image);
6501 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6505 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6507 g_hash_table_insert (image->ptr_cache, el_class, result);
6508 mono_image_unlock (image);
6510 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6516 mono_fnptr_class_get (MonoMethodSignature *sig)
6519 static GHashTable *ptr_hash = NULL;
6521 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6523 mono_loader_lock ();
6526 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6528 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6529 mono_loader_unlock ();
6532 result = g_new0 (MonoClass, 1);
6534 result->parent = NULL; /* no parent for PTR types */
6535 result->name_space = "System";
6536 result->name = "MonoFNPtrFakeClass";
6538 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6540 result->image = mono_defaults.corlib; /* need to fix... */
6541 result->inited = TRUE;
6542 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6543 /* Can pointers get boxed? */
6544 result->instance_size = sizeof (gpointer);
6545 result->cast_class = result->element_class = result;
6546 result->blittable = TRUE;
6548 result->byval_arg.type = MONO_TYPE_FNPTR;
6549 result->this_arg.type = result->byval_arg.type;
6550 result->this_arg.data.method = result->byval_arg.data.method = sig;
6551 result->this_arg.byref = TRUE;
6552 result->blittable = TRUE;
6554 mono_class_setup_supertypes (result);
6556 g_hash_table_insert (ptr_hash, sig, result);
6558 mono_loader_unlock ();
6560 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6566 mono_class_from_mono_type (MonoType *type)
6568 switch (type->type) {
6569 case MONO_TYPE_OBJECT:
6570 return type->data.klass? type->data.klass: mono_defaults.object_class;
6571 case MONO_TYPE_VOID:
6572 return type->data.klass? type->data.klass: mono_defaults.void_class;
6573 case MONO_TYPE_BOOLEAN:
6574 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6575 case MONO_TYPE_CHAR:
6576 return type->data.klass? type->data.klass: mono_defaults.char_class;
6578 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6580 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6582 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6584 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6586 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6588 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6590 return type->data.klass? type->data.klass: mono_defaults.int_class;
6592 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6594 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6596 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6598 return type->data.klass? type->data.klass: mono_defaults.single_class;
6600 return type->data.klass? type->data.klass: mono_defaults.double_class;
6601 case MONO_TYPE_STRING:
6602 return type->data.klass? type->data.klass: mono_defaults.string_class;
6603 case MONO_TYPE_TYPEDBYREF:
6604 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6605 case MONO_TYPE_ARRAY:
6606 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6608 return mono_ptr_class_get (type->data.type);
6609 case MONO_TYPE_FNPTR:
6610 return mono_fnptr_class_get (type->data.method);
6611 case MONO_TYPE_SZARRAY:
6612 return mono_array_class_get (type->data.klass, 1);
6613 case MONO_TYPE_CLASS:
6614 case MONO_TYPE_VALUETYPE:
6615 return type->data.klass;
6616 case MONO_TYPE_GENERICINST:
6617 return mono_generic_class_get_class (type->data.generic_class);
6618 case MONO_TYPE_MVAR:
6620 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6622 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6623 g_assert_not_reached ();
6630 * mono_type_retrieve_from_typespec
6631 * @image: context where the image is created
6632 * @type_spec: typespec token
6633 * @context: the generic context used to evaluate generic instantiations in
6636 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6638 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6640 *did_inflate = FALSE;
6645 if (context && (context->class_inst || context->method_inst)) {
6646 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6648 if (!mono_error_ok (error)) {
6649 mono_loader_assert_no_error ();
6655 *did_inflate = TRUE;
6662 * mono_class_create_from_typespec
6663 * @image: context where the image is created
6664 * @type_spec: typespec token
6665 * @context: the generic context used to evaluate generic instantiations in
6668 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6671 gboolean inflated = FALSE;
6672 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6673 if (!mono_error_ok (error))
6675 ret = mono_class_from_mono_type (t);
6677 mono_metadata_free_type (t);
6682 * mono_bounded_array_class_get:
6683 * @element_class: element class
6684 * @rank: the dimension of the array class
6685 * @bounded: whenever the array has non-zero bounds
6687 * Returns: a class object describing the array with element type @element_type and
6691 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6695 MonoClass *parent = NULL;
6696 GSList *list, *rootlist = NULL;
6699 gboolean corlib_type = FALSE;
6701 g_assert (rank <= 255);
6704 /* bounded only matters for one-dimensional arrays */
6707 image = eclass->image;
6709 if (rank == 1 && !bounded) {
6711 * This case is very frequent not just during compilation because of calls
6712 * from mono_class_from_mono_type (), mono_array_new (),
6713 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6715 mono_os_mutex_lock (&image->szarray_cache_lock);
6716 if (!image->szarray_cache)
6717 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6718 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6719 mono_os_mutex_unlock (&image->szarray_cache_lock);
6723 mono_loader_lock ();
6725 mono_loader_lock ();
6727 if (!image->array_cache)
6728 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6730 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6731 for (; list; list = list->next) {
6732 klass = (MonoClass *)list->data;
6733 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6734 mono_loader_unlock ();
6741 /* for the building corlib use System.Array from it */
6742 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6743 parent = mono_class_from_name (image, "System", "Array");
6746 parent = mono_defaults.array_class;
6747 if (!parent->inited)
6748 mono_class_init (parent);
6751 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6753 klass->image = image;
6754 klass->name_space = eclass->name_space;
6755 nsize = strlen (eclass->name);
6756 name = (char *)g_malloc (nsize + 2 + rank + 1);
6757 memcpy (name, eclass->name, nsize);
6760 memset (name + nsize + 1, ',', rank - 1);
6762 name [nsize + rank] = '*';
6763 name [nsize + rank + bounded] = ']';
6764 name [nsize + rank + bounded + 1] = 0;
6765 klass->name = mono_image_strdup (image, name);
6768 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6770 classes_size += sizeof (MonoClass);
6772 klass->type_token = 0;
6773 /* all arrays are marked serializable and sealed, bug #42779 */
6774 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6775 klass->parent = parent;
6776 klass->instance_size = mono_class_instance_size (klass->parent);
6778 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6779 /*Arrays of those two types are invalid.*/
6780 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6781 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6782 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6783 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6784 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6786 /* element_size -1 is ok as this is not an instantitable type*/
6787 klass->sizes.element_size = -1;
6789 klass->sizes.element_size = mono_class_array_element_size (eclass);
6791 mono_class_setup_supertypes (klass);
6793 if (eclass->generic_class)
6794 mono_class_init (eclass);
6795 if (!eclass->size_inited)
6796 mono_class_setup_fields (eclass);
6797 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6798 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6800 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6804 if (eclass->enumtype)
6805 klass->cast_class = eclass->element_class;
6807 klass->cast_class = eclass;
6809 switch (klass->cast_class->byval_arg.type) {
6811 klass->cast_class = mono_defaults.byte_class;
6814 klass->cast_class = mono_defaults.int16_class;
6817 #if SIZEOF_VOID_P == 4
6821 klass->cast_class = mono_defaults.int32_class;
6824 #if SIZEOF_VOID_P == 8
6828 klass->cast_class = mono_defaults.int64_class;
6834 klass->element_class = eclass;
6836 if ((rank > 1) || bounded) {
6837 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6838 klass->byval_arg.type = MONO_TYPE_ARRAY;
6839 klass->byval_arg.data.array = at;
6840 at->eklass = eclass;
6842 /* FIXME: complete.... */
6844 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6845 klass->byval_arg.data.klass = eclass;
6847 klass->this_arg = klass->byval_arg;
6848 klass->this_arg.byref = 1;
6853 klass->generic_container = eclass->generic_container;
6855 if (rank == 1 && !bounded) {
6856 MonoClass *prev_class;
6858 mono_os_mutex_lock (&image->szarray_cache_lock);
6859 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6861 /* Someone got in before us */
6864 g_hash_table_insert (image->szarray_cache, eclass, klass);
6865 mono_os_mutex_unlock (&image->szarray_cache_lock);
6867 list = g_slist_append (rootlist, klass);
6868 g_hash_table_insert (image->array_cache, eclass, list);
6871 mono_loader_unlock ();
6873 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6879 * mono_array_class_get:
6880 * @element_class: element class
6881 * @rank: the dimension of the array class
6883 * Returns: a class object describing the array with element type @element_type and
6887 mono_array_class_get (MonoClass *eclass, guint32 rank)
6889 return mono_bounded_array_class_get (eclass, rank, FALSE);
6893 * mono_class_instance_size:
6896 * Returns: the size of an object instance
6899 mono_class_instance_size (MonoClass *klass)
6901 if (!klass->size_inited)
6902 mono_class_init (klass);
6904 return klass->instance_size;
6908 * mono_class_min_align:
6911 * Returns: minimm alignment requirements
6914 mono_class_min_align (MonoClass *klass)
6916 if (!klass->size_inited)
6917 mono_class_init (klass);
6919 return klass->min_align;
6923 * mono_class_value_size:
6926 * This function is used for value types, and return the
6927 * space and the alignment to store that kind of value object.
6929 * Returns: the size of a value of kind @klass
6932 mono_class_value_size (MonoClass *klass, guint32 *align)
6936 /* fixme: check disable, because we still have external revereces to
6937 * mscorlib and Dummy Objects
6939 /*g_assert (klass->valuetype);*/
6941 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6944 *align = klass->min_align;
6950 * mono_class_data_size:
6953 * Returns: the size of the static class data
6956 mono_class_data_size (MonoClass *klass)
6959 mono_class_init (klass);
6960 /* This can happen with dynamically created types */
6961 if (!klass->fields_inited)
6962 mono_class_setup_fields_locking (klass);
6964 /* in arrays, sizes.class_size is unioned with element_size
6965 * and arrays have no static fields
6969 return klass->sizes.class_size;
6973 * Auxiliary routine to mono_class_get_field
6975 * Takes a field index instead of a field token.
6977 static MonoClassField *
6978 mono_class_get_field_idx (MonoClass *klass, int idx)
6980 mono_class_setup_fields_locking (klass);
6981 if (klass->exception_type)
6985 if (klass->image->uncompressed_metadata) {
6987 * klass->field.first points to the FieldPtr table, while idx points into the
6988 * Field table, so we have to do a search.
6990 /*FIXME this is broken for types with multiple fields with the same name.*/
6991 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6994 for (i = 0; i < klass->field.count; ++i)
6995 if (mono_field_get_name (&klass->fields [i]) == name)
6996 return &klass->fields [i];
6997 g_assert_not_reached ();
6999 if (klass->field.count) {
7000 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
7001 return &klass->fields [idx - klass->field.first];
7005 klass = klass->parent;
7011 * mono_class_get_field:
7012 * @class: the class to lookup the field.
7013 * @field_token: the field token
7015 * Returns: A MonoClassField representing the type and offset of
7016 * the field, or a NULL value if the field does not belong to this
7020 mono_class_get_field (MonoClass *klass, guint32 field_token)
7022 int idx = mono_metadata_token_index (field_token);
7024 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7026 return mono_class_get_field_idx (klass, idx - 1);
7030 * mono_class_get_field_from_name:
7031 * @klass: the class to lookup the field.
7032 * @name: the field name
7034 * Search the class @klass and it's parents for a field with the name @name.
7036 * Returns: the MonoClassField pointer of the named field or NULL
7039 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7041 return mono_class_get_field_from_name_full (klass, name, NULL);
7045 * mono_class_get_field_from_name_full:
7046 * @klass: the class to lookup the field.
7047 * @name: the field name
7048 * @type: the type of the fields. This optional.
7050 * Search the class @klass and it's parents for a field with the name @name and type @type.
7052 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7053 * of its generic type definition.
7055 * Returns: the MonoClassField pointer of the named field or NULL
7058 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7062 mono_class_setup_fields_locking (klass);
7063 if (klass->exception_type)
7067 for (i = 0; i < klass->field.count; ++i) {
7068 MonoClassField *field = &klass->fields [i];
7070 if (strcmp (name, mono_field_get_name (field)) != 0)
7074 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7075 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7080 klass = klass->parent;
7086 * mono_class_get_field_token:
7087 * @field: the field we need the token of
7089 * Get the token of a field. Note that the tokesn is only valid for the image
7090 * the field was loaded from. Don't use this function for fields in dynamic types.
7092 * Returns: the token representing the field in the image it was loaded from.
7095 mono_class_get_field_token (MonoClassField *field)
7097 MonoClass *klass = field->parent;
7100 mono_class_setup_fields_locking (klass);
7105 for (i = 0; i < klass->field.count; ++i) {
7106 if (&klass->fields [i] == field) {
7107 int idx = klass->field.first + i + 1;
7109 if (klass->image->uncompressed_metadata)
7110 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7111 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7114 klass = klass->parent;
7117 g_assert_not_reached ();
7122 mono_field_get_index (MonoClassField *field)
7124 int index = field - field->parent->fields;
7126 g_assert (index >= 0 && index < field->parent->field.count);
7132 * mono_class_get_field_default_value:
7134 * Return the default value of the field as a pointer into the metadata blob.
7137 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7140 guint32 constant_cols [MONO_CONSTANT_SIZE];
7142 MonoClass *klass = field->parent;
7144 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7146 if (!klass->ext || !klass->ext->field_def_values) {
7147 MonoFieldDefaultValue *def_values;
7149 mono_class_alloc_ext (klass);
7151 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7153 mono_image_lock (klass->image);
7154 mono_memory_barrier ();
7155 if (!klass->ext->field_def_values)
7156 klass->ext->field_def_values = def_values;
7157 mono_image_unlock (klass->image);
7160 field_index = mono_field_get_index (field);
7162 if (!klass->ext->field_def_values [field_index].data) {
7163 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7167 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7169 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7170 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7171 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7174 *def_type = klass->ext->field_def_values [field_index].def_type;
7175 return klass->ext->field_def_values [field_index].data;
7179 mono_property_get_index (MonoProperty *prop)
7181 int index = prop - prop->parent->ext->properties;
7183 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7189 * mono_class_get_property_default_value:
7191 * Return the default value of the field as a pointer into the metadata blob.
7194 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7197 guint32 constant_cols [MONO_CONSTANT_SIZE];
7198 MonoClass *klass = property->parent;
7200 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7202 * We don't cache here because it is not used by C# so it's quite rare, but
7203 * we still do the lookup in klass->ext because that is where the data
7204 * is stored for dynamic assemblies.
7207 if (image_is_dynamic (klass->image)) {
7208 int prop_index = mono_property_get_index (property);
7209 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7210 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7211 return klass->ext->prop_def_values [prop_index].data;
7215 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7219 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7220 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7221 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7225 mono_class_get_event_token (MonoEvent *event)
7227 MonoClass *klass = event->parent;
7232 for (i = 0; i < klass->ext->event.count; ++i) {
7233 if (&klass->ext->events [i] == event)
7234 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7237 klass = klass->parent;
7240 g_assert_not_reached ();
7245 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7249 gpointer iter = NULL;
7250 while ((p = mono_class_get_properties (klass, &iter))) {
7251 if (! strcmp (name, p->name))
7254 klass = klass->parent;
7260 mono_class_get_property_token (MonoProperty *prop)
7262 MonoClass *klass = prop->parent;
7266 gpointer iter = NULL;
7267 while ((p = mono_class_get_properties (klass, &iter))) {
7268 if (&klass->ext->properties [i] == prop)
7269 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7273 klass = klass->parent;
7276 g_assert_not_reached ();
7281 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7283 const char *name, *nspace;
7284 if (image_is_dynamic (image))
7285 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7287 switch (type_token & 0xff000000){
7288 case MONO_TOKEN_TYPE_DEF: {
7289 guint32 cols [MONO_TYPEDEF_SIZE];
7290 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7291 guint tidx = mono_metadata_token_index (type_token);
7293 if (tidx > tt->rows)
7294 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7296 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7297 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7298 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7299 if (strlen (nspace) == 0)
7300 return g_strdup_printf ("%s", name);
7302 return g_strdup_printf ("%s.%s", nspace, name);
7305 case MONO_TOKEN_TYPE_REF: {
7307 guint32 cols [MONO_TYPEREF_SIZE];
7308 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7309 guint tidx = mono_metadata_token_index (type_token);
7312 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7314 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7315 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7316 mono_error_cleanup (&error);
7320 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7321 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7322 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7323 if (strlen (nspace) == 0)
7324 return g_strdup_printf ("%s", name);
7326 return g_strdup_printf ("%s.%s", nspace, name);
7329 case MONO_TOKEN_TYPE_SPEC:
7330 return g_strdup_printf ("Typespec 0x%08x", type_token);
7332 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7337 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7339 if (image_is_dynamic (image))
7340 return g_strdup_printf ("DynamicAssembly %s", image->name);
7342 switch (type_token & 0xff000000){
7343 case MONO_TOKEN_TYPE_DEF:
7344 if (image->assembly)
7345 return mono_stringify_assembly_name (&image->assembly->aname);
7346 else if (image->assembly_name)
7347 return g_strdup (image->assembly_name);
7348 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7349 case MONO_TOKEN_TYPE_REF: {
7351 MonoAssemblyName aname;
7352 guint32 cols [MONO_TYPEREF_SIZE];
7353 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7354 guint32 idx = mono_metadata_token_index (type_token);
7357 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7359 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7360 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7361 mono_error_cleanup (&error);
7364 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7366 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7367 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7368 case MONO_RESOLUTION_SCOPE_MODULE:
7370 return g_strdup ("");
7371 case MONO_RESOLUTION_SCOPE_MODULEREF:
7373 return g_strdup ("");
7374 case MONO_RESOLUTION_SCOPE_TYPEREF:
7376 return g_strdup ("");
7377 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7378 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7379 return mono_stringify_assembly_name (&aname);
7381 g_assert_not_reached ();
7385 case MONO_TOKEN_TYPE_SPEC:
7387 return g_strdup ("");
7389 g_assert_not_reached ();
7396 * mono_class_get_full:
7397 * @image: the image where the class resides
7398 * @type_token: the token for the class
7399 * @context: the generic context used to evaluate generic instantiations in
7400 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7402 * Returns: the MonoClass that represents @type_token in @image
7405 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7409 klass = mono_class_get_checked (image, type_token, &error);
7411 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7412 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7414 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7420 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7424 mono_error_init (error);
7425 klass = mono_class_get_checked (image, type_token, error);
7427 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7428 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7433 * mono_class_get_checked:
7434 * @image: the image where the class resides
7435 * @type_token: the token for the class
7436 * @error: error object to return any error
7438 * Returns: the MonoClass that represents @type_token in @image
7441 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7443 MonoClass *klass = NULL;
7445 mono_error_init (error);
7447 if (image_is_dynamic (image)) {
7448 int table = mono_metadata_token_table (type_token);
7450 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7451 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7454 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7458 switch (type_token & 0xff000000){
7459 case MONO_TOKEN_TYPE_DEF:
7460 klass = mono_class_create_from_typedef (image, type_token, error);
7462 case MONO_TOKEN_TYPE_REF:
7463 klass = mono_class_from_typeref_checked (image, type_token, error);
7465 case MONO_TOKEN_TYPE_SPEC:
7466 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7469 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7473 /* Generic case, should be avoided for when a better error is possible. */
7474 if (!klass && mono_error_ok (error)) {
7475 char *name = mono_class_name_from_token (image, type_token);
7476 char *assembly = mono_assembly_name_from_token (image, type_token);
7477 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7485 * mono_type_get_checked:
7486 * @image: the image where the type resides
7487 * @type_token: the token for the type
7488 * @context: the generic context used to evaluate generic instantiations in
7489 * @error: Error handling context
7491 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7493 * Returns: the MonoType that represents @type_token in @image
7496 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7498 MonoType *type = NULL;
7499 gboolean inflated = FALSE;
7501 mono_error_init (error);
7503 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7504 if (image_is_dynamic (image))
7505 return mono_class_get_type ((MonoClass *)mono_lookup_dynamic_token (image, type_token, context));
7507 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7508 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7511 mono_loader_assert_no_error ();
7516 return mono_class_get_type (klass);
7519 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7522 mono_loader_assert_no_error ();
7527 MonoType *tmp = type;
7528 type = mono_class_get_type (mono_class_from_mono_type (type));
7529 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7530 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7531 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7533 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7535 if (type->type != tmp->type)
7538 mono_metadata_free_type (tmp);
7545 mono_class_get (MonoImage *image, guint32 type_token)
7547 return mono_class_get_full (image, type_token, NULL);
7551 * mono_image_init_name_cache:
7553 * Initializes the class name cache stored in image->name_cache.
7555 * LOCKING: Acquires the corresponding image lock.
7558 mono_image_init_name_cache (MonoImage *image)
7560 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7561 guint32 cols [MONO_TYPEDEF_SIZE];
7564 guint32 i, visib, nspace_index;
7565 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7567 if (image->name_cache)
7570 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7572 if (image_is_dynamic (image)) {
7573 mono_image_lock (image);
7574 if (image->name_cache) {
7575 /* Somebody initialized it before us */
7576 g_hash_table_destroy (the_name_cache);
7578 mono_atomic_store_release (&image->name_cache, the_name_cache);
7580 mono_image_unlock (image);
7584 /* Temporary hash table to avoid lookups in the nspace_table */
7585 name_cache2 = g_hash_table_new (NULL, NULL);
7587 for (i = 1; i <= t->rows; ++i) {
7588 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7589 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7591 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7592 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7594 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7596 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7597 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7599 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7600 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7601 if (!nspace_table) {
7602 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7603 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7604 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7607 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7610 /* Load type names from EXPORTEDTYPES table */
7612 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7613 guint32 cols [MONO_EXP_TYPE_SIZE];
7616 for (i = 0; i < t->rows; ++i) {
7617 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7619 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7620 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7624 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7625 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7627 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7628 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7629 if (!nspace_table) {
7630 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7631 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7632 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7635 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7639 g_hash_table_destroy (name_cache2);
7641 mono_image_lock (image);
7642 if (image->name_cache) {
7643 /* Somebody initialized it before us */
7644 g_hash_table_destroy (the_name_cache);
7646 mono_atomic_store_release (&image->name_cache, the_name_cache);
7648 mono_image_unlock (image);
7651 /*FIXME Only dynamic assemblies should allow this operation.*/
7653 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7654 const char *name, guint32 index)
7656 GHashTable *nspace_table;
7657 GHashTable *name_cache;
7660 mono_image_init_name_cache (image);
7661 mono_image_lock (image);
7663 name_cache = image->name_cache;
7664 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7665 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7666 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7669 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7670 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7672 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7674 mono_image_unlock (image);
7683 find_nocase (gpointer key, gpointer value, gpointer user_data)
7685 char *name = (char*)key;
7686 FindUserData *data = (FindUserData*)user_data;
7688 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7689 data->value = value;
7693 * mono_class_from_name_case:
7694 * @image: The MonoImage where the type is looked up in
7695 * @name_space: the type namespace
7696 * @name: the type short name.
7697 * @deprecated: use the _checked variant
7699 * Obtains a MonoClass with a given namespace and a given name which
7700 * is located in the given MonoImage. The namespace and name
7701 * lookups are case insensitive.
7704 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7707 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7708 g_assert (!mono_error_ok (&error));
7713 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7715 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7716 guint32 cols [MONO_TYPEDEF_SIZE];
7721 mono_error_init (error);
7723 if (image_is_dynamic (image)) {
7725 FindUserData user_data;
7727 mono_image_init_name_cache (image);
7728 mono_image_lock (image);
7730 user_data.key = name_space;
7731 user_data.value = NULL;
7732 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7734 if (user_data.value) {
7735 GHashTable *nspace_table = (GHashTable*)user_data.value;
7737 user_data.key = name;
7738 user_data.value = NULL;
7740 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7742 if (user_data.value)
7743 token = GPOINTER_TO_UINT (user_data.value);
7746 mono_image_unlock (image);
7749 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7755 /* add a cache if needed */
7756 for (i = 1; i <= t->rows; ++i) {
7757 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7758 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7760 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7761 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7763 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7765 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7766 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7767 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7768 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7774 return_nested_in (MonoClass *klass, char *nested)
7777 char *s = strchr (nested, '/');
7778 gpointer iter = NULL;
7785 while ((found = mono_class_get_nested_types (klass, &iter))) {
7786 if (strcmp (found->name, nested) == 0) {
7788 return return_nested_in (found, s);
7796 search_modules (MonoImage *image, const char *name_space, const char *name)
7798 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7799 MonoImage *file_image;
7804 * The EXPORTEDTYPES table only contains public types, so have to search the
7806 * Note: image->modules contains the contents of the MODULEREF table, while
7807 * the real module list is in the FILE table.
7809 for (i = 0; i < file_table->rows; i++) {
7810 guint32 cols [MONO_FILE_SIZE];
7811 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7812 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7815 file_image = mono_image_load_file_for_image (image, i + 1);
7817 klass = mono_class_from_name (file_image, name_space, name);
7827 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, GHashTable* visited_images)
7829 GHashTable *nspace_table;
7830 MonoImage *loaded_image;
7837 mono_error_init (error);
7839 // Checking visited images avoids stack overflows when cyclic references exist.
7840 if (g_hash_table_lookup (visited_images, image))
7843 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7845 if ((nested = strchr (name, '/'))) {
7846 int pos = nested - name;
7847 int len = strlen (name);
7850 memcpy (buf, name, len + 1);
7852 nested = buf + pos + 1;
7856 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7857 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7858 gboolean res = get_class_from_name (image, name_space, name, &klass);
7861 klass = search_modules (image, name_space, name);
7863 return klass ? return_nested_in (klass, nested) : NULL;
7869 mono_image_init_name_cache (image);
7870 mono_image_lock (image);
7872 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7875 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7877 mono_image_unlock (image);
7879 if (!token && image_is_dynamic (image) && image->modules) {
7880 /* Search modules as well */
7881 for (i = 0; i < image->module_count; ++i) {
7882 MonoImage *module = image->modules [i];
7884 klass = mono_class_from_name (module, name_space, name);
7891 klass = search_modules (image, name_space, name);
7899 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7900 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7901 guint32 cols [MONO_EXP_TYPE_SIZE];
7904 idx = mono_metadata_token_index (token);
7906 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7908 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7909 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7910 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7913 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, error, visited_images);
7915 return klass ? return_nested_in (klass, nested) : NULL;
7917 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7918 guint32 assembly_idx;
7920 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7922 mono_assembly_load_reference (image, assembly_idx - 1);
7923 g_assert (image->references [assembly_idx - 1]);
7924 if (image->references [assembly_idx - 1] == (gpointer)-1)
7926 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, error, visited_images);
7928 return return_nested_in (klass, nested);
7931 g_assert_not_reached ();
7935 token = MONO_TOKEN_TYPE_DEF | token;
7937 klass = mono_class_get_checked (image, token, error);
7939 return return_nested_in (klass, nested);
7944 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7947 GHashTable *visited_images;
7949 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7951 klass = mono_class_from_name_checked_aux (image, name_space, name, error, visited_images);
7953 g_hash_table_destroy (visited_images);
7959 * mono_class_from_name:
7960 * @image: The MonoImage where the type is looked up in
7961 * @name_space: the type namespace
7962 * @name: the type short name.
7964 * Obtains a MonoClass with a given namespace and a given name which
7965 * is located in the given MonoImage.
7967 * To reference nested classes, use the "/" character as a separator.
7968 * For example use "Foo/Bar" to reference the class Bar that is nested
7969 * inside Foo, like this: "class Foo { class Bar {} }".
7972 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7977 klass = mono_class_from_name_checked (image, name_space, name, &error);
7978 if (!mono_error_ok (&error)) {
7979 mono_loader_set_error_from_mono_error (&error);
7980 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7986 * mono_class_is_subclass_of:
7987 * @klass: class to probe if it is a subclass of another one
7988 * @klassc: the class we suspect is the base class
7989 * @check_interfaces: whether we should perform interface checks
7991 * This method determines whether @klass is a subclass of @klassc.
7993 * If the @check_interfaces flag is set, then if @klassc is an interface
7994 * this method return true if the @klass implements the interface or
7995 * if @klass is an interface, if one of its base classes is @klass.
7997 * If @check_interfaces is false then, then if @klass is not an interface
7998 * then it returns true if the @klass is a subclass of @klassc.
8000 * if @klass is an interface and @klassc is System.Object, then this function
8005 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8006 gboolean check_interfaces)
8008 /*FIXME test for interfaces with variant generic arguments*/
8010 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8011 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8013 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8016 for (i = 0; i < klass->interface_count; i ++) {
8017 MonoClass *ic = klass->interfaces [i];
8022 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8027 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8030 if (klassc == mono_defaults.object_class)
8037 mono_type_is_generic_argument (MonoType *type)
8039 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8043 mono_class_has_variant_generic_params (MonoClass *klass)
8046 MonoGenericContainer *container;
8048 if (!klass->generic_class)
8051 container = klass->generic_class->container_class->generic_container;
8053 for (i = 0; i < container->type_argc; ++i)
8054 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8061 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8063 if (target == candidate)
8066 if (check_for_reference_conv &&
8067 mono_type_is_generic_argument (&target->byval_arg) &&
8068 mono_type_is_generic_argument (&candidate->byval_arg)) {
8069 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8070 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8072 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8075 if (!mono_class_is_assignable_from (target, candidate))
8081 * @container the generic container from the GTD
8082 * @klass: the class to be assigned to
8083 * @oklass: the source class
8085 * Both klass and oklass must be instances of the same generic interface.
8086 * Return true if @klass can be assigned to a @klass variable
8089 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8092 MonoType **klass_argv, **oklass_argv;
8093 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8094 MonoGenericContainer *container = klass_gtd->generic_container;
8096 if (klass == oklass)
8099 /*Viable candidates are instances of the same generic interface*/
8100 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8103 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8104 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8106 for (j = 0; j < container->type_argc; ++j) {
8107 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8108 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8110 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8114 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8115 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8117 if (param1_class != param2_class) {
8118 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8119 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8121 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8122 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8132 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8134 MonoGenericParam *gparam, *ogparam;
8135 MonoGenericParamInfo *tinfo, *cinfo;
8136 MonoClass **candidate_class;
8137 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8140 if (target == candidate)
8142 if (target->byval_arg.type != candidate->byval_arg.type)
8145 gparam = target->byval_arg.data.generic_param;
8146 ogparam = candidate->byval_arg.data.generic_param;
8147 tinfo = mono_generic_param_info (gparam);
8148 cinfo = mono_generic_param_info (ogparam);
8150 class_constraint_satisfied = FALSE;
8151 valuetype_constraint_satisfied = FALSE;
8153 /*candidate must have a super set of target's special constraints*/
8154 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8155 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8157 if (cinfo->constraints) {
8158 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8159 MonoClass *cc = *candidate_class;
8161 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8162 class_constraint_satisfied = TRUE;
8163 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8164 valuetype_constraint_satisfied = TRUE;
8167 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8168 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8170 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8172 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8174 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8175 valuetype_constraint_satisfied)) {
8180 /*candidate type constraints must be a superset of target's*/
8181 if (tinfo->constraints) {
8182 MonoClass **target_class;
8183 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8184 MonoClass *tc = *target_class;
8187 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8188 * check it's constraints since it satisfy the constraint by itself.
8190 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8193 if (!cinfo->constraints)
8196 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8197 MonoClass *cc = *candidate_class;
8199 if (mono_class_is_assignable_from (tc, cc))
8203 * This happens when we have the following:
8205 * Bar<K> where K : IFace
8206 * Foo<T, U> where T : U where U : IFace
8208 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8211 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8212 if (mono_gparam_is_assignable_from (target, cc))
8216 if (!*candidate_class)
8221 /*candidate itself must have a constraint that satisfy target*/
8222 if (cinfo->constraints) {
8223 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8224 MonoClass *cc = *candidate_class;
8225 if (mono_class_is_assignable_from (target, cc))
8233 * mono_class_is_assignable_from:
8234 * @klass: the class to be assigned to
8235 * @oklass: the source class
8237 * Return: true if an instance of object oklass can be assigned to an
8238 * instance of object @klass
8241 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8243 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8245 mono_class_init (klass);
8247 if (!oklass->inited)
8248 mono_class_init (oklass);
8250 if (klass->exception_type || oklass->exception_type)
8253 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8254 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8256 return mono_gparam_is_assignable_from (klass, oklass);
8259 if (MONO_CLASS_IS_INTERFACE (klass)) {
8260 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8261 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8262 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8266 for (i = 0; constraints [i]; ++i) {
8267 if (mono_class_is_assignable_from (klass, constraints [i]))
8275 /* interface_offsets might not be set for dynamic classes */
8276 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8278 * oklass might be a generic type parameter but they have
8279 * interface_offsets set.
8281 return mono_reflection_call_is_assignable_to (oklass, klass);
8282 if (!oklass->interface_bitmap)
8283 /* Happens with generic instances of not-yet created dynamic types */
8285 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8288 if (mono_class_has_variant_generic_params (klass)) {
8291 mono_class_setup_interfaces (oklass, &error);
8292 if (!mono_error_ok (&error)) {
8293 mono_error_cleanup (&error);
8297 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8298 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8299 MonoClass *iface = oklass->interfaces_packed [i];
8301 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8306 } else if (klass->delegate) {
8307 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8309 }else if (klass->rank) {
8310 MonoClass *eclass, *eoclass;
8312 if (oklass->rank != klass->rank)
8315 /* vectors vs. one dimensional arrays */
8316 if (oklass->byval_arg.type != klass->byval_arg.type)
8319 eclass = klass->cast_class;
8320 eoclass = oklass->cast_class;
8323 * a is b does not imply a[] is b[] when a is a valuetype, and
8324 * b is a reference type.
8327 if (eoclass->valuetype) {
8328 if ((eclass == mono_defaults.enum_class) ||
8329 (eclass == mono_defaults.enum_class->parent) ||
8330 (eclass == mono_defaults.object_class))
8334 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8335 } else if (mono_class_is_nullable (klass)) {
8336 if (mono_class_is_nullable (oklass))
8337 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8339 return mono_class_is_assignable_from (klass->cast_class, oklass);
8340 } else if (klass == mono_defaults.object_class)
8343 return mono_class_has_parent (oklass, klass);
8346 /*Check if @oklass is variant compatible with @klass.*/
8348 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8351 MonoType **klass_argv, **oklass_argv;
8352 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8353 MonoGenericContainer *container = klass_gtd->generic_container;
8355 /*Viable candidates are instances of the same generic interface*/
8356 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8359 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8360 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8362 for (j = 0; j < container->type_argc; ++j) {
8363 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8364 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8366 if (param1_class->valuetype != param2_class->valuetype)
8370 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8371 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8373 if (param1_class != param2_class) {
8374 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8375 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8377 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8378 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8386 /*Check if @candidate implements the interface @target*/
8388 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8392 gboolean is_variant = mono_class_has_variant_generic_params (target);
8394 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8395 if (mono_class_is_variant_compatible_slow (target, candidate))
8400 if (candidate == target)
8403 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8404 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8405 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8407 if (tb && tb->interfaces) {
8408 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8409 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8410 MonoClass *iface_class;
8412 /* we can't realize the type here since it can do pretty much anything. */
8415 iface_class = mono_class_from_mono_type (iface->type);
8416 if (iface_class == target)
8418 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8420 if (mono_class_implement_interface_slow (target, iface_class))
8425 /*setup_interfaces don't mono_class_init anything*/
8426 /*FIXME this doesn't handle primitive type arrays.
8427 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8428 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8430 mono_class_setup_interfaces (candidate, &error);
8431 if (!mono_error_ok (&error)) {
8432 mono_error_cleanup (&error);
8436 for (i = 0; i < candidate->interface_count; ++i) {
8437 if (candidate->interfaces [i] == target)
8440 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8443 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8447 candidate = candidate->parent;
8448 } while (candidate);
8454 * Check if @oklass can be assigned to @klass.
8455 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8458 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8460 if (candidate == target)
8462 if (target == mono_defaults.object_class)
8465 if (mono_class_has_parent (candidate, target))
8468 /*If target is not an interface there is no need to check them.*/
8469 if (MONO_CLASS_IS_INTERFACE (target))
8470 return mono_class_implement_interface_slow (target, candidate);
8472 if (target->delegate && mono_class_has_variant_generic_params (target))
8473 return mono_class_is_variant_compatible (target, candidate, FALSE);
8476 MonoClass *eclass, *eoclass;
8478 if (target->rank != candidate->rank)
8481 /* vectors vs. one dimensional arrays */
8482 if (target->byval_arg.type != candidate->byval_arg.type)
8485 eclass = target->cast_class;
8486 eoclass = candidate->cast_class;
8489 * a is b does not imply a[] is b[] when a is a valuetype, and
8490 * b is a reference type.
8493 if (eoclass->valuetype) {
8494 if ((eclass == mono_defaults.enum_class) ||
8495 (eclass == mono_defaults.enum_class->parent) ||
8496 (eclass == mono_defaults.object_class))
8500 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8502 /*FIXME properly handle nullables */
8503 /*FIXME properly handle (M)VAR */
8508 * mono_class_get_cctor:
8509 * @klass: A MonoClass pointer
8511 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8514 mono_class_get_cctor (MonoClass *klass)
8516 MonoCachedClassInfo cached_info;
8518 if (image_is_dynamic (klass->image)) {
8520 * has_cctor is not set for these classes because mono_class_init () is
8523 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8526 if (!klass->has_cctor)
8529 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8531 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8532 if (!mono_error_ok (&error))
8533 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8537 if (klass->generic_class && !klass->methods)
8538 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8540 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8544 * mono_class_get_finalizer:
8545 * @klass: The MonoClass pointer
8547 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8550 mono_class_get_finalizer (MonoClass *klass)
8552 MonoCachedClassInfo cached_info;
8555 mono_class_init (klass);
8556 if (!mono_class_has_finalizer (klass))
8559 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8561 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8562 if (!mono_error_ok (&error))
8563 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8566 mono_class_setup_vtable (klass);
8567 return klass->vtable [finalize_slot];
8572 * mono_class_needs_cctor_run:
8573 * @klass: the MonoClass pointer
8574 * @caller: a MonoMethod describing the caller
8576 * Determines whenever the class has a static constructor and whenever it
8577 * needs to be called when executing CALLER.
8580 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8584 method = mono_class_get_cctor (klass);
8586 return (method == caller) ? FALSE : TRUE;
8592 * mono_class_array_element_size:
8595 * Returns: the number of bytes an element of type @klass
8596 * uses when stored into an array.
8599 mono_class_array_element_size (MonoClass *klass)
8601 MonoType *type = &klass->byval_arg;
8604 switch (type->type) {
8607 case MONO_TYPE_BOOLEAN:
8611 case MONO_TYPE_CHAR:
8620 case MONO_TYPE_CLASS:
8621 case MONO_TYPE_STRING:
8622 case MONO_TYPE_OBJECT:
8623 case MONO_TYPE_SZARRAY:
8624 case MONO_TYPE_ARRAY:
8625 return sizeof (gpointer);
8630 case MONO_TYPE_VALUETYPE:
8631 if (type->data.klass->enumtype) {
8632 type = mono_class_enum_basetype (type->data.klass);
8633 klass = klass->element_class;
8636 return mono_class_instance_size (klass) - sizeof (MonoObject);
8637 case MONO_TYPE_GENERICINST:
8638 type = &type->data.generic_class->container_class->byval_arg;
8641 case MONO_TYPE_MVAR: {
8644 return mono_type_size (type, &align);
8646 case MONO_TYPE_VOID:
8650 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8656 * mono_array_element_size:
8657 * @ac: pointer to a #MonoArrayClass
8659 * Returns: the size of single array element.
8662 mono_array_element_size (MonoClass *ac)
8664 g_assert (ac->rank);
8665 return ac->sizes.element_size;
8669 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8670 MonoGenericContext *context)
8673 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8674 g_assert (mono_error_ok (&error));
8679 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8680 MonoGenericContext *context, MonoError *error)
8682 mono_error_init (error);
8684 if (image_is_dynamic (image)) {
8685 MonoClass *tmp_handle_class;
8686 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8688 g_assert (tmp_handle_class);
8690 *handle_class = tmp_handle_class;
8692 if (tmp_handle_class == mono_defaults.typehandle_class)
8693 return &((MonoClass*)obj)->byval_arg;
8698 switch (token & 0xff000000) {
8699 case MONO_TOKEN_TYPE_DEF:
8700 case MONO_TOKEN_TYPE_REF:
8701 case MONO_TOKEN_TYPE_SPEC: {
8704 *handle_class = mono_defaults.typehandle_class;
8705 type = mono_type_get_checked (image, token, context, error);
8709 mono_class_init (mono_class_from_mono_type (type));
8710 /* We return a MonoType* as handle */
8713 case MONO_TOKEN_FIELD_DEF: {
8715 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8717 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8721 *handle_class = mono_defaults.fieldhandle_class;
8722 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8726 mono_class_init (klass);
8727 return mono_class_get_field (klass, token);
8729 case MONO_TOKEN_METHOD_DEF:
8730 case MONO_TOKEN_METHOD_SPEC: {
8732 meth = mono_get_method_checked (image, token, NULL, context, error);
8734 *handle_class = mono_defaults.methodhandle_class;
8740 case MONO_TOKEN_MEMBER_REF: {
8741 guint32 cols [MONO_MEMBERREF_SIZE];
8743 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8744 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8745 mono_metadata_decode_blob_size (sig, &sig);
8746 if (*sig == 0x6) { /* it's a field */
8748 MonoClassField *field;
8749 field = mono_field_from_token_checked (image, token, &klass, context, error);
8751 *handle_class = mono_defaults.fieldhandle_class;
8755 meth = mono_get_method_checked (image, token, NULL, context, error);
8757 *handle_class = mono_defaults.methodhandle_class;
8762 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8768 * This function might need to call runtime functions so it can't be part
8769 * of the metadata library.
8771 static MonoLookupDynamicToken lookup_dynamic = NULL;
8774 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8776 lookup_dynamic = func;
8780 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8782 MonoClass *handle_class;
8784 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8788 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8790 return lookup_dynamic (image, token, valid_token, handle_class, context);
8793 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8796 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8798 get_cached_class_info = func;
8802 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8804 if (!get_cached_class_info)
8807 return get_cached_class_info (klass, res);
8811 mono_install_get_class_from_name (MonoGetClassFromName func)
8813 get_class_from_name = func;
8817 mono_class_get_image (MonoClass *klass)
8819 return klass->image;
8823 * mono_class_get_element_class:
8824 * @klass: the MonoClass to act on
8826 * Returns: the element class of an array or an enumeration.
8829 mono_class_get_element_class (MonoClass *klass)
8831 return klass->element_class;
8835 * mono_class_is_valuetype:
8836 * @klass: the MonoClass to act on
8838 * Returns: true if the MonoClass represents a ValueType.
8841 mono_class_is_valuetype (MonoClass *klass)
8843 return klass->valuetype;
8847 * mono_class_is_enum:
8848 * @klass: the MonoClass to act on
8850 * Returns: true if the MonoClass represents an enumeration.
8853 mono_class_is_enum (MonoClass *klass)
8855 return klass->enumtype;
8859 * mono_class_enum_basetype:
8860 * @klass: the MonoClass to act on
8862 * Returns: the underlying type representation for an enumeration.
8865 mono_class_enum_basetype (MonoClass *klass)
8867 if (klass->element_class == klass)
8868 /* SRE or broken types */
8871 return &klass->element_class->byval_arg;
8875 * mono_class_get_parent
8876 * @klass: the MonoClass to act on
8878 * Returns: the parent class for this class.
8881 mono_class_get_parent (MonoClass *klass)
8883 return klass->parent;
8887 * mono_class_get_nesting_type;
8888 * @klass: the MonoClass to act on
8890 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8893 mono_class_get_nesting_type (MonoClass *klass)
8895 return klass->nested_in;
8899 * mono_class_get_rank:
8900 * @klass: the MonoClass to act on
8902 * Returns: the rank for the array (the number of dimensions).
8905 mono_class_get_rank (MonoClass *klass)
8911 * mono_class_get_flags:
8912 * @klass: the MonoClass to act on
8914 * The type flags from the TypeDef table from the metadata.
8915 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8918 * Returns: the flags from the TypeDef table.
8921 mono_class_get_flags (MonoClass *klass)
8923 return klass->flags;
8927 * mono_class_get_name
8928 * @klass: the MonoClass to act on
8930 * Returns: the name of the class.
8933 mono_class_get_name (MonoClass *klass)
8939 * mono_class_get_namespace:
8940 * @klass: the MonoClass to act on
8942 * Returns: the namespace of the class.
8945 mono_class_get_namespace (MonoClass *klass)
8947 return klass->name_space;
8951 * mono_class_get_type:
8952 * @klass: the MonoClass to act on
8954 * This method returns the internal Type representation for the class.
8956 * Returns: the MonoType from the class.
8959 mono_class_get_type (MonoClass *klass)
8961 return &klass->byval_arg;
8965 * mono_class_get_type_token
8966 * @klass: the MonoClass to act on
8968 * This method returns type token for the class.
8970 * Returns: the type token for the class.
8973 mono_class_get_type_token (MonoClass *klass)
8975 return klass->type_token;
8979 * mono_class_get_byref_type:
8980 * @klass: the MonoClass to act on
8985 mono_class_get_byref_type (MonoClass *klass)
8987 return &klass->this_arg;
8991 * mono_class_num_fields:
8992 * @klass: the MonoClass to act on
8994 * Returns: the number of static and instance fields in the class.
8997 mono_class_num_fields (MonoClass *klass)
8999 return klass->field.count;
9003 * mono_class_num_methods:
9004 * @klass: the MonoClass to act on
9006 * Returns: the number of methods in the class.
9009 mono_class_num_methods (MonoClass *klass)
9011 return klass->method.count;
9015 * mono_class_num_properties
9016 * @klass: the MonoClass to act on
9018 * Returns: the number of properties in the class.
9021 mono_class_num_properties (MonoClass *klass)
9023 mono_class_setup_properties (klass);
9025 return klass->ext->property.count;
9029 * mono_class_num_events:
9030 * @klass: the MonoClass to act on
9032 * Returns: the number of events in the class.
9035 mono_class_num_events (MonoClass *klass)
9037 mono_class_setup_events (klass);
9039 return klass->ext->event.count;
9043 * mono_class_get_fields:
9044 * @klass: the MonoClass to act on
9046 * This routine is an iterator routine for retrieving the fields in a class.
9048 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9049 * iterate over all of the elements. When no more values are
9050 * available, the return value is NULL.
9052 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9055 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9057 MonoClassField* field;
9061 mono_class_setup_fields_locking (klass);
9062 if (klass->exception_type)
9064 /* start from the first */
9065 if (klass->field.count) {
9066 *iter = &klass->fields [0];
9067 return &klass->fields [0];
9073 field = (MonoClassField *)*iter;
9075 if (field < &klass->fields [klass->field.count]) {
9083 * mono_class_get_methods
9084 * @klass: the MonoClass to act on
9086 * This routine is an iterator routine for retrieving the fields in a class.
9088 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9089 * iterate over all of the elements. When no more values are
9090 * available, the return value is NULL.
9092 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9095 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9097 MonoMethod** method;
9101 mono_class_setup_methods (klass);
9104 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9105 * FIXME we should better report this error to the caller
9107 if (!klass->methods)
9109 /* start from the first */
9110 if (klass->method.count) {
9111 *iter = &klass->methods [0];
9112 return klass->methods [0];
9118 method = (MonoMethod **)*iter;
9120 if (method < &klass->methods [klass->method.count]) {
9128 * mono_class_get_virtual_methods:
9130 * Iterate over the virtual methods of KLASS.
9132 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9135 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9137 MonoMethod** method;
9140 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9142 mono_class_setup_methods (klass);
9144 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9145 * FIXME we should better report this error to the caller
9147 if (!klass->methods)
9149 /* start from the first */
9150 method = &klass->methods [0];
9152 method = (MonoMethod **)*iter;
9155 while (method < &klass->methods [klass->method.count]) {
9156 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9160 if (method < &klass->methods [klass->method.count]) {
9167 /* Search directly in metadata to avoid calling setup_methods () */
9168 MonoMethod *res = NULL;
9174 start_index = GPOINTER_TO_UINT (*iter);
9177 for (i = start_index; i < klass->method.count; ++i) {
9180 /* klass->method.first points into the methodptr table */
9181 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9183 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9187 if (i < klass->method.count) {
9189 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9190 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9192 /* Add 1 here so the if (*iter) check fails */
9193 *iter = GUINT_TO_POINTER (i + 1);
9202 * mono_class_get_properties:
9203 * @klass: the MonoClass to act on
9205 * This routine is an iterator routine for retrieving the properties in a class.
9207 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9208 * iterate over all of the elements. When no more values are
9209 * available, the return value is NULL.
9211 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9214 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9216 MonoProperty* property;
9220 mono_class_setup_properties (klass);
9221 /* start from the first */
9222 if (klass->ext->property.count) {
9223 *iter = &klass->ext->properties [0];
9224 return (MonoProperty *)*iter;
9230 property = (MonoProperty *)*iter;
9232 if (property < &klass->ext->properties [klass->ext->property.count]) {
9234 return (MonoProperty *)*iter;
9240 * mono_class_get_events:
9241 * @klass: the MonoClass to act on
9243 * This routine is an iterator routine for retrieving the properties in a class.
9245 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9246 * iterate over all of the elements. When no more values are
9247 * available, the return value is NULL.
9249 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9252 mono_class_get_events (MonoClass* klass, gpointer *iter)
9258 mono_class_setup_events (klass);
9259 /* start from the first */
9260 if (klass->ext->event.count) {
9261 *iter = &klass->ext->events [0];
9262 return (MonoEvent *)*iter;
9268 event = (MonoEvent *)*iter;
9270 if (event < &klass->ext->events [klass->ext->event.count]) {
9272 return (MonoEvent *)*iter;
9278 * mono_class_get_interfaces
9279 * @klass: the MonoClass to act on
9281 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9283 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9284 * iterate over all of the elements. When no more values are
9285 * available, the return value is NULL.
9287 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9290 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9298 mono_class_init (klass);
9299 if (!klass->interfaces_inited) {
9300 mono_class_setup_interfaces (klass, &error);
9301 if (!mono_error_ok (&error)) {
9302 mono_error_cleanup (&error);
9306 /* start from the first */
9307 if (klass->interface_count) {
9308 *iter = &klass->interfaces [0];
9309 return klass->interfaces [0];
9315 iface = (MonoClass **)*iter;
9317 if (iface < &klass->interfaces [klass->interface_count]) {
9325 setup_nested_types (MonoClass *klass)
9328 GList *classes, *nested_classes, *l;
9331 if (klass->nested_classes_inited)
9334 if (!klass->type_token)
9335 klass->nested_classes_inited = TRUE;
9337 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9341 guint32 cols [MONO_NESTED_CLASS_SIZE];
9342 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9343 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9344 if (!mono_error_ok (&error)) {
9345 /*FIXME don't swallow the error message*/
9346 mono_error_cleanup (&error);
9348 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9352 classes = g_list_prepend (classes, nclass);
9354 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9357 mono_class_alloc_ext (klass);
9359 nested_classes = NULL;
9360 for (l = classes; l; l = l->next)
9361 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9362 g_list_free (classes);
9364 mono_image_lock (klass->image);
9366 mono_memory_barrier ();
9367 if (!klass->nested_classes_inited) {
9368 klass->ext->nested_classes = nested_classes;
9369 mono_memory_barrier ();
9370 klass->nested_classes_inited = TRUE;
9373 mono_image_unlock (klass->image);
9377 * mono_class_get_nested_types
9378 * @klass: the MonoClass to act on
9380 * This routine is an iterator routine for retrieving the nested types of a class.
9381 * This works only if @klass is non-generic, or a generic type definition.
9383 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9384 * iterate over all of the elements. When no more values are
9385 * available, the return value is NULL.
9387 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9390 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9396 if (!klass->nested_classes_inited)
9397 setup_nested_types (klass);
9400 /* start from the first */
9401 if (klass->ext && klass->ext->nested_classes) {
9402 *iter = klass->ext->nested_classes;
9403 return (MonoClass *)klass->ext->nested_classes->data;
9405 /* no nested types */
9409 item = (GList *)*iter;
9413 return (MonoClass *)item->data;
9420 * mono_class_is_delegate
9421 * @klass: the MonoClass to act on
9423 * Returns: true if the MonoClass represents a System.Delegate.
9426 mono_class_is_delegate (MonoClass *klass)
9428 return klass->delegate;
9432 * mono_class_implements_interface
9433 * @klass: The MonoClass to act on
9434 * @interface: The interface to check if @klass implements.
9436 * Returns: true if @klass implements @interface.
9439 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9441 return mono_class_is_assignable_from (iface, klass);
9445 * mono_field_get_name:
9446 * @field: the MonoClassField to act on
9448 * Returns: the name of the field.
9451 mono_field_get_name (MonoClassField *field)
9457 * mono_field_get_type:
9458 * @field: the MonoClassField to act on
9460 * Returns: MonoType of the field.
9463 mono_field_get_type (MonoClassField *field)
9466 MonoType *type = mono_field_get_type_checked (field, &error);
9467 if (!mono_error_ok (&error)) {
9468 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9469 mono_error_cleanup (&error);
9476 * mono_field_get_type_checked:
9477 * @field: the MonoClassField to act on
9478 * @error: used to return any erro found while retrieving @field type
9480 * Returns: MonoType of the field.
9483 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9485 mono_error_init (error);
9487 mono_field_resolve_type (field, error);
9492 * mono_field_get_parent:
9493 * @field: the MonoClassField to act on
9495 * Returns: MonoClass where the field was defined.
9498 mono_field_get_parent (MonoClassField *field)
9500 return field->parent;
9504 * mono_field_get_flags;
9505 * @field: the MonoClassField to act on
9507 * The metadata flags for a field are encoded using the
9508 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9510 * Returns: the flags for the field.
9513 mono_field_get_flags (MonoClassField *field)
9516 return mono_field_resolve_flags (field);
9517 return field->type->attrs;
9521 * mono_field_get_offset;
9522 * @field: the MonoClassField to act on
9524 * Returns: the field offset.
9527 mono_field_get_offset (MonoClassField *field)
9529 return field->offset;
9533 mono_field_get_rva (MonoClassField *field)
9537 MonoClass *klass = field->parent;
9538 MonoFieldDefaultValue *field_def_values;
9540 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9542 if (!klass->ext || !klass->ext->field_def_values) {
9543 mono_class_alloc_ext (klass);
9545 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9547 mono_image_lock (klass->image);
9548 if (!klass->ext->field_def_values)
9549 klass->ext->field_def_values = field_def_values;
9550 mono_image_unlock (klass->image);
9553 field_index = mono_field_get_index (field);
9555 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9556 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9558 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9559 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9562 return klass->ext->field_def_values [field_index].data;
9566 * mono_field_get_data;
9567 * @field: the MonoClassField to act on
9569 * Returns: pointer to the metadata constant value or to the field
9570 * data if it has an RVA flag.
9573 mono_field_get_data (MonoClassField *field)
9575 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9576 MonoTypeEnum def_type;
9578 return mono_class_get_field_default_value (field, &def_type);
9579 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9580 return mono_field_get_rva (field);
9587 * mono_property_get_name:
9588 * @prop: the MonoProperty to act on
9590 * Returns: the name of the property
9593 mono_property_get_name (MonoProperty *prop)
9599 * mono_property_get_set_method
9600 * @prop: the MonoProperty to act on.
9602 * Returns: the setter method of the property (A MonoMethod)
9605 mono_property_get_set_method (MonoProperty *prop)
9611 * mono_property_get_get_method
9612 * @prop: the MonoProperty to act on.
9614 * Returns: the setter method of the property (A MonoMethod)
9617 mono_property_get_get_method (MonoProperty *prop)
9623 * mono_property_get_parent:
9624 * @prop: the MonoProperty to act on.
9626 * Returns: the MonoClass where the property was defined.
9629 mono_property_get_parent (MonoProperty *prop)
9631 return prop->parent;
9635 * mono_property_get_flags:
9636 * @prop: the MonoProperty to act on.
9638 * The metadata flags for a property are encoded using the
9639 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9641 * Returns: the flags for the property.
9644 mono_property_get_flags (MonoProperty *prop)
9650 * mono_event_get_name:
9651 * @event: the MonoEvent to act on
9653 * Returns: the name of the event.
9656 mono_event_get_name (MonoEvent *event)
9662 * mono_event_get_add_method:
9663 * @event: The MonoEvent to act on.
9665 * Returns: the @add' method for the event (a MonoMethod).
9668 mono_event_get_add_method (MonoEvent *event)
9674 * mono_event_get_remove_method:
9675 * @event: The MonoEvent to act on.
9677 * Returns: the @remove method for the event (a MonoMethod).
9680 mono_event_get_remove_method (MonoEvent *event)
9682 return event->remove;
9686 * mono_event_get_raise_method:
9687 * @event: The MonoEvent to act on.
9689 * Returns: the @raise method for the event (a MonoMethod).
9692 mono_event_get_raise_method (MonoEvent *event)
9694 return event->raise;
9698 * mono_event_get_parent:
9699 * @event: the MonoEvent to act on.
9701 * Returns: the MonoClass where the event is defined.
9704 mono_event_get_parent (MonoEvent *event)
9706 return event->parent;
9710 * mono_event_get_flags
9711 * @event: the MonoEvent to act on.
9713 * The metadata flags for an event are encoded using the
9714 * EVENT_* constants. See the tabledefs.h file for details.
9716 * Returns: the flags for the event.
9719 mono_event_get_flags (MonoEvent *event)
9721 return event->attrs;
9725 * mono_class_get_method_from_name:
9726 * @klass: where to look for the method
9727 * @name: name of the method
9728 * @param_count: number of parameters. -1 for any number.
9730 * Obtains a MonoMethod with a given name and number of parameters.
9731 * It only works if there are no multiple signatures for any given method name.
9734 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9736 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9740 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9742 MonoMethod *res = NULL;
9745 /* Search directly in the metadata to avoid calling setup_methods () */
9746 for (i = 0; i < klass->method.count; ++i) {
9748 guint32 cols [MONO_METHOD_SIZE];
9750 MonoMethodSignature *sig;
9752 /* klass->method.first points into the methodptr table */
9753 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9755 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9756 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9758 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9761 if (param_count == -1) {
9765 sig = mono_method_signature_checked (method, &error);
9767 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9770 if (sig->param_count == param_count) {
9781 * mono_class_get_method_from_name_flags:
9782 * @klass: where to look for the method
9783 * @name_space: name of the method
9784 * @param_count: number of parameters. -1 for any number.
9785 * @flags: flags which must be set in the method
9787 * Obtains a MonoMethod with a given name and number of parameters.
9788 * It only works if there are no multiple signatures for any given method name.
9791 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9793 MonoMethod *res = NULL;
9796 mono_class_init (klass);
9798 if (klass->generic_class && !klass->methods) {
9799 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9802 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9803 if (!mono_error_ok (&error))
9804 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9809 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9810 mono_class_setup_methods (klass);
9812 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9813 See mono/tests/array_load_exception.il
9814 FIXME we should better report this error to the caller
9816 if (!klass->methods)
9818 for (i = 0; i < klass->method.count; ++i) {
9819 MonoMethod *method = klass->methods [i];
9821 if (method->name[0] == name [0] &&
9822 !strcmp (name, method->name) &&
9823 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9824 ((method->flags & flags) == flags)) {
9831 res = find_method_in_metadata (klass, name, param_count, flags);
9838 * mono_class_set_failure:
9839 * @klass: class in which the failure was detected
9840 * @ex_type: the kind of exception/error to be thrown (later)
9841 * @ex_data: exception data (specific to each type of exception/error)
9843 * Keep a detected failure informations in the class for later processing.
9844 * Note that only the first failure is kept.
9846 * LOCKING: Acquires the loader lock.
9849 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9851 if (klass->exception_type)
9854 mono_loader_lock ();
9855 klass->exception_type = ex_type;
9857 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9858 mono_loader_unlock ();
9864 * mono_class_get_exception_data:
9866 * Return the exception_data property of KLASS.
9868 * LOCKING: Acquires the loader lock.
9871 mono_class_get_exception_data (MonoClass *klass)
9873 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9877 * mono_classes_init:
9879 * Initialize the resources used by this module.
9882 mono_classes_init (void)
9884 mono_os_mutex_init (&classes_mutex);
9886 mono_counters_register ("Inflated methods size",
9887 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9888 mono_counters_register ("Inflated classes",
9889 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9890 mono_counters_register ("Inflated classes size",
9891 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9892 mono_counters_register ("MonoClass size",
9893 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9894 mono_counters_register ("MonoClassExt size",
9895 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9899 * mono_classes_cleanup:
9901 * Free the resources used by this module.
9904 mono_classes_cleanup (void)
9906 if (global_interface_bitset)
9907 mono_bitset_free (global_interface_bitset);
9908 global_interface_bitset = NULL;
9909 mono_os_mutex_destroy (&classes_mutex);
9913 * mono_class_get_exception_for_failure:
9914 * @klass: class in which the failure was detected
9916 * Return a constructed MonoException than the caller can then throw
9917 * using mono_raise_exception - or NULL if no failure is present (or
9918 * doesn't result in an exception).
9921 mono_class_get_exception_for_failure (MonoClass *klass)
9923 gpointer exception_data = mono_class_get_exception_data (klass);
9925 switch (klass->exception_type) {
9926 case MONO_EXCEPTION_TYPE_LOAD: {
9929 char *str = mono_type_get_full_name (klass);
9930 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9931 name = mono_string_new (mono_domain_get (), str);
9933 ex = mono_get_exception_type_load (name, astr);
9937 case MONO_EXCEPTION_MISSING_METHOD: {
9938 char *class_name = (char *)exception_data;
9939 char *assembly_name = class_name + strlen (class_name) + 1;
9941 return mono_get_exception_missing_method (class_name, assembly_name);
9943 case MONO_EXCEPTION_MISSING_FIELD: {
9944 char *class_name = (char *)exception_data;
9945 char *member_name = class_name + strlen (class_name) + 1;
9947 return mono_get_exception_missing_field (class_name, member_name);
9949 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9950 char *msg_format = (char *)exception_data;
9951 char *assembly_name = msg_format + strlen (msg_format) + 1;
9952 char *msg = g_strdup_printf (msg_format, assembly_name);
9955 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9961 case MONO_EXCEPTION_BAD_IMAGE: {
9962 return mono_get_exception_bad_image_format ((const char *)exception_data);
9965 MonoLoaderError *error;
9968 error = mono_loader_get_last_error ();
9970 ex = mono_loader_error_prepare_exception (error);
9974 /* TODO - handle other class related failures */
9981 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9983 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9984 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9986 if (outer_klass == inner_klass)
9988 inner_klass = inner_klass->nested_in;
9989 } while (inner_klass);
9994 mono_class_get_generic_type_definition (MonoClass *klass)
9996 return klass->generic_class ? klass->generic_class->container_class : klass;
10000 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10002 * Generic instantiations are ignored for all super types of @klass.
10004 * Visibility checks ignoring generic instantiations.
10007 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10010 klass = mono_class_get_generic_type_definition (klass);
10011 parent = mono_class_get_generic_type_definition (parent);
10012 mono_class_setup_supertypes (klass);
10014 for (i = 0; i < klass->idepth; ++i) {
10015 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10021 * Subtype can only access parent members with family protection if the site object
10022 * is subclass of Subtype. For example:
10023 * class A { protected int x; }
10025 * void valid_access () {
10029 * void invalid_access () {
10036 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10038 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10041 if (context_klass == NULL)
10043 /*if access_klass is not member_klass context_klass must be type compat*/
10044 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10050 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10053 if (accessing == accessed)
10055 if (!accessed || !accessing)
10058 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10059 * anywhere so untrusted friends are not safe to access platform's code internals */
10060 if (mono_security_core_clr_enabled ()) {
10061 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10065 mono_assembly_load_friends (accessed);
10066 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10067 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10068 /* Be conservative with checks */
10069 if (!friend_->name)
10071 if (strcmp (accessing->aname.name, friend_->name))
10073 if (friend_->public_key_token [0]) {
10074 if (!accessing->aname.public_key_token [0])
10076 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10085 * If klass is a generic type or if it is derived from a generic type, return the
10086 * MonoClass of the generic definition
10087 * Returns NULL if not found
10090 get_generic_definition_class (MonoClass *klass)
10093 if (klass->generic_class && klass->generic_class->container_class)
10094 return klass->generic_class->container_class;
10095 klass = klass->parent;
10101 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10104 for (i = 0; i < ginst->type_argc; ++i) {
10105 MonoType *type = ginst->type_argv[i];
10106 switch (type->type) {
10107 case MONO_TYPE_SZARRAY:
10108 if (!can_access_type (access_klass, type->data.klass))
10111 case MONO_TYPE_ARRAY:
10112 if (!can_access_type (access_klass, type->data.array->eklass))
10115 case MONO_TYPE_PTR:
10116 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10119 case MONO_TYPE_CLASS:
10120 case MONO_TYPE_VALUETYPE:
10121 case MONO_TYPE_GENERICINST:
10122 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10132 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10136 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10139 if (access_klass->element_class && !access_klass->enumtype)
10140 access_klass = access_klass->element_class;
10142 if (member_klass->element_class && !member_klass->enumtype)
10143 member_klass = member_klass->element_class;
10145 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10147 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10150 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10153 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10156 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10159 /*Non nested type with nested visibility. We just fail it.*/
10160 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10163 switch (access_level) {
10164 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10165 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10167 case TYPE_ATTRIBUTE_PUBLIC:
10170 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10173 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10174 return is_nesting_type (member_klass, access_klass);
10176 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10177 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10179 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10180 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10182 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10183 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10184 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10186 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10187 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10188 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10193 /* FIXME: check visibility of type, too */
10195 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10197 MonoClass *member_generic_def;
10198 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10201 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10202 access_klass->generic_container) &&
10203 (member_generic_def = get_generic_definition_class (member_klass))) {
10204 MonoClass *access_container;
10206 if (access_klass->generic_container)
10207 access_container = access_klass;
10209 access_container = access_klass->generic_class->container_class;
10211 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10215 /* Partition I 8.5.3.2 */
10216 /* the access level values are the same for fields and methods */
10217 switch (access_level) {
10218 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10219 /* same compilation unit */
10220 return access_klass->image == member_klass->image;
10221 case FIELD_ATTRIBUTE_PRIVATE:
10222 return access_klass == member_klass;
10223 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10224 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10225 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10228 case FIELD_ATTRIBUTE_ASSEMBLY:
10229 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10230 case FIELD_ATTRIBUTE_FAMILY:
10231 if (is_valid_family_access (access_klass, member_klass, context_klass))
10234 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10235 if (is_valid_family_access (access_klass, member_klass, context_klass))
10237 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10238 case FIELD_ATTRIBUTE_PUBLIC:
10245 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10247 /* FIXME: check all overlapping fields */
10248 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10250 MonoClass *nested = method->klass->nested_in;
10252 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10255 nested = nested->nested_in;
10262 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10264 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10266 MonoClass *nested = method->klass->nested_in;
10268 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10271 nested = nested->nested_in;
10276 * with generics calls to explicit interface implementations can be expressed
10277 * directly: the method is private, but we must allow it. This may be opening
10278 * a hole or the generics code should handle this differently.
10279 * Maybe just ensure the interface type is public.
10281 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10287 * mono_method_can_access_method_full:
10288 * @method: The caller method
10289 * @called: The called method
10290 * @context_klass: The static type on stack of the owner @called object used
10292 * This function must be used with instance calls, as they have more strict family accessibility.
10293 * It can be used with static methods, but context_klass should be NULL.
10295 * Returns: TRUE if caller have proper visibility and acessibility to @called
10298 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10300 MonoClass *access_class = method->klass;
10301 MonoClass *member_class = called->klass;
10302 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10304 MonoClass *nested = access_class->nested_in;
10306 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10309 nested = nested->nested_in;
10316 can = can_access_type (access_class, member_class);
10318 MonoClass *nested = access_class->nested_in;
10320 can = can_access_type (nested, member_class);
10323 nested = nested->nested_in;
10330 if (called->is_inflated) {
10331 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10332 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10341 * mono_method_can_access_field_full:
10342 * @method: The caller method
10343 * @field: The accessed field
10344 * @context_klass: The static type on stack of the owner @field object used
10346 * This function must be used with instance fields, as they have more strict family accessibility.
10347 * It can be used with static fields, but context_klass should be NULL.
10349 * Returns: TRUE if caller have proper visibility and acessibility to @field
10352 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10354 MonoClass *access_class = method->klass;
10355 MonoClass *member_class = field->parent;
10356 /* FIXME: check all overlapping fields */
10357 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10359 MonoClass *nested = access_class->nested_in;
10361 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10364 nested = nested->nested_in;
10371 can = can_access_type (access_class, member_class);
10373 MonoClass *nested = access_class->nested_in;
10375 can = can_access_type (nested, member_class);
10378 nested = nested->nested_in;
10388 * mono_class_can_access_class:
10389 * @source_class: The source class
10390 * @target_class: The accessed class
10392 * This function returns is @target_class is visible to @source_class
10394 * Returns: TRUE if source have proper visibility and acessibility to target
10397 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10399 return can_access_type (source_class, target_class);
10403 * mono_type_is_valid_enum_basetype:
10404 * @type: The MonoType to check
10406 * Returns: TRUE if the type can be used as the basetype of an enum
10408 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10409 switch (type->type) {
10412 case MONO_TYPE_BOOLEAN:
10415 case MONO_TYPE_CHAR:
10429 * mono_class_is_valid_enum:
10430 * @klass: An enum class to be validated
10432 * This method verify the required properties an enum should have.
10434 * Returns: TRUE if the informed enum class is valid
10436 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10437 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10438 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10440 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10441 MonoClassField * field;
10442 gpointer iter = NULL;
10443 gboolean found_base_field = FALSE;
10445 g_assert (klass->enumtype);
10446 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10447 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10451 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10454 while ((field = mono_class_get_fields (klass, &iter))) {
10455 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10456 if (found_base_field)
10458 found_base_field = TRUE;
10459 if (!mono_type_is_valid_enum_basetype (field->type))
10464 if (!found_base_field)
10467 if (klass->method.count > 0)
10474 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10476 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10480 * mono_class_setup_interface_id:
10482 * Initializes MonoClass::interface_id if required.
10484 * LOCKING: Acquires the loader lock.
10487 mono_class_setup_interface_id (MonoClass *klass)
10489 mono_loader_lock ();
10490 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10491 klass->interface_id = mono_get_unique_iid (klass);
10492 mono_loader_unlock ();
10496 * mono_class_alloc_ext:
10498 * Allocate klass->ext if not already done.
10501 mono_class_alloc_ext (MonoClass *klass)
10508 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10509 mono_image_lock (klass->image);
10510 mono_memory_barrier ();
10513 class_ext_size += sizeof (MonoClassExt);
10514 mono_image_unlock (klass->image);
10518 * mono_class_setup_interfaces:
10520 * Initialize klass->interfaces/interfaces_count.
10521 * LOCKING: Acquires the loader lock.
10522 * This function can fail the type.
10525 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10527 int i, interface_count;
10528 MonoClass **interfaces;
10530 mono_error_init (error);
10532 if (klass->interfaces_inited)
10535 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10536 MonoType *args [1];
10538 /* generic IList, ICollection, IEnumerable */
10539 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10540 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10542 args [0] = &klass->element_class->byval_arg;
10543 interfaces [0] = mono_class_bind_generic_parameters (
10544 mono_defaults.generic_ilist_class, 1, args, FALSE);
10545 if (interface_count > 1)
10546 interfaces [1] = mono_class_bind_generic_parameters (
10547 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10548 } else if (klass->generic_class) {
10549 MonoClass *gklass = klass->generic_class->container_class;
10551 mono_class_setup_interfaces (gklass, error);
10552 if (!mono_error_ok (error)) {
10553 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10557 interface_count = gklass->interface_count;
10558 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10559 for (i = 0; i < interface_count; i++) {
10560 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10561 if (!mono_error_ok (error)) {
10562 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10567 interface_count = 0;
10571 mono_image_lock (klass->image);
10573 if (!klass->interfaces_inited) {
10574 klass->interface_count = interface_count;
10575 klass->interfaces = interfaces;
10577 mono_memory_barrier ();
10579 klass->interfaces_inited = TRUE;
10582 mono_image_unlock (klass->image);
10586 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10588 MonoClass *klass = field->parent;
10589 MonoImage *image = klass->image;
10590 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10591 int field_idx = field - klass->fields;
10593 mono_error_init (error);
10596 MonoClassField *gfield = >d->fields [field_idx];
10597 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10598 if (!mono_error_ok (error)) {
10599 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10600 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10604 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10605 if (!mono_error_ok (error)) {
10606 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10607 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10612 guint32 cols [MONO_FIELD_SIZE];
10613 MonoGenericContainer *container = NULL;
10614 int idx = klass->field.first + field_idx;
10616 /*FIXME, in theory we do not lazy load SRE fields*/
10617 g_assert (!image_is_dynamic (image));
10619 if (klass->generic_container) {
10620 container = klass->generic_container;
10622 container = gtd->generic_container;
10623 g_assert (container);
10626 /* klass->field.first and idx points into the fieldptr table */
10627 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10629 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10630 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);
10631 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10635 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10637 mono_metadata_decode_value (sig, &sig);
10638 /* FIELD signature == 0x06 */
10639 g_assert (*sig == 0x06);
10640 field->type = mono_metadata_parse_type_full (image, container, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10642 mono_class_set_failure_from_loader_error (klass, error, g_strdup_printf ("Could not load field %s type", field->name));
10647 mono_field_resolve_flags (MonoClassField *field)
10649 MonoClass *klass = field->parent;
10650 MonoImage *image = klass->image;
10651 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10652 int field_idx = field - klass->fields;
10656 MonoClassField *gfield = >d->fields [field_idx];
10657 return mono_field_get_flags (gfield);
10659 int idx = klass->field.first + field_idx;
10661 /*FIXME, in theory we do not lazy load SRE fields*/
10662 g_assert (!image_is_dynamic (image));
10664 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10669 * mono_class_setup_basic_field_info:
10670 * @class: The class to initialize
10672 * Initializes the klass->fields array of fields.
10673 * Aquires the loader lock.
10676 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10678 mono_loader_lock ();
10679 mono_class_setup_basic_field_info (klass);
10680 mono_loader_unlock ();
10684 * mono_class_get_fields_lazy:
10685 * @klass: the MonoClass to act on
10687 * This routine is an iterator routine for retrieving the fields in a class.
10688 * Only minimal information about fields are loaded. Accessors must be used
10689 * for all MonoClassField returned.
10691 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10692 * iterate over all of the elements. When no more values are
10693 * available, the return value is NULL.
10695 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10698 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10700 MonoClassField* field;
10704 mono_class_setup_basic_field_info_locking (klass);
10705 if (!klass->fields)
10707 /* start from the first */
10708 if (klass->field.count) {
10709 *iter = &klass->fields [0];
10710 return (MonoClassField *)*iter;
10716 field = (MonoClassField *)*iter;
10718 if (field < &klass->fields [klass->field.count]) {
10720 return (MonoClassField *)*iter;
10726 mono_class_full_name (MonoClass *klass)
10728 return mono_type_full_name (&klass->byval_arg);